diff --git a/ProSystem.dat b/ProSystem.dat index fae44f8..9217f05 100644 --- a/ProSystem.dat +++ b/ProSystem.dat @@ -6,6 +6,9 @@ controller1=1 controller2=1 region=0 flags=0 +pokey450=false +xm=false +hsc=true [0be996d25144966d5541c9eb4919b289] title=Ace Of Aces type=4 @@ -26,8 +29,8 @@ flags=0 title=Alien Brigade type=2 pokey=false -controller1=3 -controller2=3 +controller1=2 +controller2=2 region=0 flags=0 crossx=15 @@ -36,8 +39,8 @@ crossy=15 title=Alien Brigade type=2 pokey=false -controller1=3 -controller2=3 +controller1=2 +controller2=2 region=1 flags=0 crossx=15 @@ -50,6 +53,33 @@ controller1=1 controller2=1 region=0 flags=0 +[404f95103b70975a42cb09946dc3adca] +title=Apple Snaffle (Jul 17-Rev 24) (2009) +type=3 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[5c66261d7be74184a047f77233919e06] +title=Arkanoid +type=1 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +hblank=8 +[212ee2a6e66d8bb7fbf26f343cc8dc19] +title=Arkanoid +type=1 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +hblank=8 [07342c78619ba6ffcc61c10e907e3b50] title=Asteroids type=0 @@ -58,6 +88,7 @@ controller1=1 controller2=1 region=0 flags=0 +hsc=true [8fc3a695eaea3984912d98ed4a543376] title=Ballblazer type=0 @@ -112,21 +143,13 @@ controller1=1 controller2=1 region=1 flags=0 -[7adbd2cec2e2cbc1e0ad237778ee46b9] -title=Beef Drop (Jul 18 2006) +[3e63be18e480fa63fce5e4c823286e53] +title=Beef Drop type=0 pokey=true controller1=1 controller2=1 -region=0 -flags=0 -[aefb78276913e8a166e460222e378fec] -title=Beef Drop (Oct 15 2006) -type=0 -pokey=true -controller1=1 -controller2=1 -region=0 +region=1 flags=0 [5a09946e57dbe30408a8f253a28d07db] title=Centipede @@ -136,6 +159,7 @@ controller1=1 controller2=1 region=0 flags=0 +hsc=true [38c056a48472d9a9e16ebda5ed91dae7] title=Centipede type=0 @@ -196,8 +220,8 @@ flags=0 title=Crossbow type=2 pokey=false -controller1=3 -controller2=3 +controller1=2 +controller2=2 region=0 flags=0 crossx=15 @@ -206,8 +230,8 @@ crossy=10 title=Crossbow type=2 pokey=false -controller1=3 -controller2=3 +controller1=2 +controller2=2 region=1 flags=0 crossx=15 @@ -252,6 +276,7 @@ controller1=1 controller2=1 region=0 flags=0 +hsc=true [408dca9fc40e2b5d805f403fa0509436] title=Dig Dug type=0 @@ -364,6 +389,7 @@ controller1=1 controller2=1 region=0 flags=0 +hsc=true [de0d4f5a9bf1c1bddee3ed2f7ec51209] title=Food Fight type=0 @@ -380,6 +406,7 @@ controller1=1 controller2=1 region=0 flags=0 +hsc=true [f5dc7dc8e38072d3d65bd90a660148ce] title=Galaga type=0 @@ -389,7 +416,7 @@ controller2=1 region=1 flags=0 [06204dadc975be5e5e37e7cc66f984cf] -title=Gato +title=Gato type=0 pokey=false controller1=1 @@ -397,7 +424,7 @@ controller2=1 region=0 flags=0 [fd9e78e201b6baafddfd3e1fbfe6ba31] -title=Hat Trick +title=Hat Trick type=0 pokey=false controller1=1 @@ -405,7 +432,7 @@ controller2=1 region=0 flags=0 [0baec96787ce17f390e204de1a136e59] -title=Hat Trick +title=Hat Trick type=0 pokey=false controller1=1 @@ -461,15 +488,16 @@ controller2=1 region=1 flags=0 [f18b3b897a25ab3885b43b4bd141b396] -title=Joust +title=Joust type=0 pokey=false controller1=1 controller2=1 region=0 flags=0 +hsc=true [f2dae0264a4b4a73762b9d7177e989f6] -title=Joust +title=Joust type=0 pokey=false controller1=1 @@ -477,7 +505,7 @@ controller2=1 region=1 flags=0 [c3a5a8692a423d43d9d28dd5b7d109d9] -title=Karateka +title=Karateka type=0 pokey=false controller1=1 @@ -485,7 +513,7 @@ controller2=1 region=0 flags=0 [5e0a1e832bbcea6facb832fde23a440a] -title=Karateka +title=Karateka type=4 pokey=false controller1=1 @@ -493,7 +521,7 @@ controller2=1 region=1 flags=0 [17b3b764d33eae9b5260f01df7bb9d2f] -title=Klax +title=Klax type=4 pokey=false controller1=1 @@ -625,15 +653,16 @@ controller2=1 region=1 flags=0 [fc0ea52a9fac557251b65ee680d951e5] -title=Ms. Pac-Man +title=Ms. Pac-Man type=0 pokey=false controller1=1 controller2=1 region=0 flags=0 +hsc=true [56469e8c5ff8983c6cb8dadc64eb0363] -title=Ms. Pac-Man +title=Ms. Pac-Man type=0 pokey=false controller1=1 @@ -729,7 +758,7 @@ controller2=1 region=0 flags=0 [584582bb09ee8122e7fc09dc7d1ed813] -title=Pole Position II +title=Pole Position II type=0 pokey=false controller1=1 @@ -737,7 +766,7 @@ controller2=1 region=0 flags=0 [865457e0e0f48253b08f77b9e18f93b2] -title=Pole Position II +title=Pole Position II type=0 pokey=false controller1=1 @@ -793,7 +822,7 @@ controller2=1 region=0 flags=0 [66ecaafe1b82ae68ffc96267aaf7a4d7] -title=Robotron +title=Robotron type=0 pokey=false controller1=1 @@ -801,6 +830,7 @@ controller2=1 region=0 flags=0 dualanalog=true +hsc=true [980c35ae9625773a450aa7ef51751c04] title=Scrapyard Dog type=4 @@ -877,6 +907,7 @@ controller1=1 controller2=1 region=0 flags=0 +rightswitch=1 [95d7c321dce8f57623a9c5b4947bb375] title=Super Skatebordin' type=0 @@ -885,6 +916,7 @@ controller1=1 controller2=1 region=1 flags=0 +rightswitch=1 [44f862bca77d68b56b32534eda5c198d] title=Tank Command (Overdump) type=1 @@ -1013,6 +1045,7 @@ controller1=1 controller2=1 region=0 flags=0 +hsc=true [b1a9f196ce5f47ca8caf8fa7bc4ca46c] title=Xevious type=0 @@ -1021,3 +1054,1528 @@ controller1=1 controller2=1 region=1 flags=0 +[e1f0a708fbc107001fc49ce48151fefa] +title=Bentley Bear's CQ Wonder Hack +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +leftswitch=0 +swapbuttons=true +[34483432b92f565f4ced82a141119164] +title=Bentley Bear's Crystal Quest +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +xm=false +leftswitch=0 +swapbuttons=true +[ad35a98040a2facb10ecb120bf83bcc3] +title=Bentley Bear's Crystal Quest +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +leftswitch=0 +swapbuttons=true +[707e98991390a4e8874508e5ed4edeef] +title=Bentley Bear's Crystal Quest +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=true +leftswitch=0 +swapbuttons=true +[ec81468e31fde04b67b5b99b7da8edb1] +title=Bentley Bear's Crystal Quest +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=true +leftswitch=0 +swapbuttons=true +[87484e54ab8e45aac978dcc3efd924e5] +title=Bentley Bear's Crystal Quest P +type=2 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=true +leftswitch=0 +swapbuttons=true +[4d0b5bf95e4cb366990dbaeecb7f706d] +title=BentleyBear +type=2 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=true +leftswitch=0 +swapbuttons=true +[ba8d0d0be821b29a0ca9a6fa031a970d] +title=BentleyBear +type=2 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=true +leftswitch=0 +swapbuttons=true +[1926b9b322ac0f8f36e119b524aa48bd] +title=Bentley Bear's Crystal Quest P +type=2 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=true +leftswitch=0 +swapbuttons=true +[3e4b11a99271fd807b5c6db411dc6643] +title=Bentley Bear's Crystal Quest P +type=2 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=false +leftswitch=0 +swapbuttons=true +[8385daccee02ccda081eed45eba1479d] +title=Legend Of Silverpeak +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[9ea73fd07e43f61209876d33e6f6dc04] +title=Desert Falcon HSC Support +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[90fa275f9f2a65b341796e11b2f551af] +title=Winter Games Alternate Version +type=3 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[299d31c8e181fdd011df2014451bdf0f] +title=Crazy Brix (Joystick) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +leftswitch=0 +rightswitch=1 +hsc=true +[3209039148e0b7a2b1927bd05bae4685] +title=Tric Brix (NTSC) (Joy) (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +leftswitch=0 +rightswitch=1 +[32e937e7796db3a01e9bcf5fe93929b0] +title=Trix Brix-NoLvl13-NTSC-Joy-Hack +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +leftswitch=0 +rightswitch=1 +[a60e4b608505d1fb201703b266f754a7] +title=TiME Salvo +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +dualanalog=true +[dbb493bdc4e98436dbbfd4f2e4413397] +title=Dig Dog (No Harp) (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[54829fb744d4cd7a794ccd2580df7c3d] +title=Dig Dog (Harp) (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[f2047b149e72be8f97e9671314748ec4] +title=ReZolve +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[42fa4bd854a2813b19099da524461a64] +title=Battlezone (PAL) +type=7 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[f5150c0fc1948832211e57852abb0c6e] +title=7800 Utility Cart +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +xm=true +hsc=true +[a8458c510fdd71a1f9cc4c0b243b177a] +title=Battlezone (NTSC) +type=7 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[67ee0011090a6ada38f3eef8a3020fb4] +title=Apple Snaffle V1.25F +type=1 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[13f11c4e8c019ee326b571d059accea4] +title=Froggie +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +[608fa599f06f935e05d445ff236f6d7a] +title=Asterix Quest (BBCQ Hack) +type=2 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +swapbuttons=true +[a65f79ad4a0bbdecd59d5f7eb3623fd7] +title=Asteroids Deluxe (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[3d38281ed8a8d8c7cd457a18c92c8604] +title=Astro Blaster +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[a51e5df28a0fe8c52e9d28fb5f8e44a6] +title=Astro Fighter +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[78b1061d651ef806becac1dd3fda29a0] +title=Beef Drop +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[6010a398070dfacb4c0173d75d73c50a] +title=Beef Drop (New Levels Hack) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[9fa7743a016c9b7015ee1d386326f88e] +title=b*nQ +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[af1c8f89f0aef0d9e2e15901d6e0539a] +title=Centipede PMI PAL +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[2d2fe4da9f1bae102fa8ca2d8830a626] +title=Crazy Otto (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[40bd21c9698c6b8e71b703f860c11359] +title=Cyb Ur +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[cf3c5a32205506af3c09e6e0c82cfa09] +title=Donkey Kong PK-XM Concerto Demo +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +hsc=true +[c956d5ce7417cc2dab61a9afd8f372d0] +title=Donkey Kong PK-XM Demo NTSC v1.2 +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +hsc=true +[df700753d8ba9353a7045868778eef6d] +title=Donkey Kong PK-XM Demo PAL v1.2 +type=2 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=true +[098b209aac126f2c2edbc982df09cd1b] +title=Double Dragon GPX Hack +type=6 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[4565867aa6e5cc710a7edaf6d434b3af] +title=Double Dragon Sprite Hack Test 2 +type=6 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[fab1290f9a4c4f2b4d831c8a57f969f5] +title=Draker Quest (Beta 4) +type=1 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[a9f29004412621f20ad9f5c51cc11486] +title=Draker Quest II +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[fa4aec407b90e9360b9cfeb41839b09a] +title=Dual Pac-Man (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[6287727ab36391a62f728bbdee88675c] +title=FailSafe (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[84c4b4ed75f41417ac7cbceac71e3856] +title=FailSafe (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[2fb85cab6e0f0582e3057bf1ac33c74a] +title=Fatal Run Graphics Hack RC1 +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[e7d89669a7f92ec2cc99d9663a28671c] +title=Frenzy (w-Berzerk) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +xm=true +hsc=true +[6053233cb59c0b4ca633623fd76c4576] +title=Froggie +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[ee09789d61a693e387ccdc9a2f025b43] +title=Galaxians (Hack) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[3d12489c553cb1a90c8ebd6534383fa1] +title=Gorf +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[1e21bf1d9d7b3c0cebaac576964c9eb2] +title=Graze Suit Alpha +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[46dbc5108151e963b120cdaedd7d6d4c] +title=Hangly-Man (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[25ce1f5dfc909bcb46086e414d6a0f30] +title=Hearty Manslapper +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[61809684eefd6cbb2963574ffb0a3fab] +title=Humantron 2084 +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +dualanalog=true +[bf070f04c8fc7ec721b9506b63b48470] +title=Impossible Mission (Blue Hack) +type=3 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[4a811d87d1730a334a21e7bda9fe535a] +title=Impossible Mission (Green Hack) +type=3 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[05c21a88fd736d59d28b1d95e79840b6] +title=Impossible Mission (Red Hack) +type=3 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[dde5703c488c4ad5268c2696704f1c68] +title=Impossible Mission (C64 Hack) +type=3 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[f4216cb77cd6db15225968f315c9793f] +title=Impossible Mission C64 GPX Hack +type=3 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[e54edc299e72d22d0ba05d16f3393e8c] +title=Jr. Pac-Man (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[e274e7285bb8f97d4d9acddc8497ed9e] +title=Jr. Pac-Man (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[5fb805f2b69820a9b196f5fed2a23c99] +title=Klax (Prototype) (Fixed) +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[114e215b8cfc8698bc0286a79e1cb9b2] +title=Merry Xmas 2012 e-card v1.10F +type=0 +pokey=true +controller1=1 +controller2=0 +region=0 +flags=0 +[eb3c1443f4a25806de4657e106d504e8] +title=Meteor Bath (Hack) (RC2) (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[c3f6201d6a9388e860328c963a3301cc] +title=Meteor Shower (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[dc0bf52475030c05671dd187e9a99f08] +title=Meteor Shower (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[9ff38ea62004201d870caa8bd9463525] +title=Moon Cresta (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[675c5b79238eaa641f2e3fe9c5e22589] +title=Moon Cresta (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[89f90b661d1b79e956b10bb6a9771f78] +title=More Beef Drop (Hack) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[d8dbb5c4d7d02e6b0627df8f657a13b4] +title=Ms Pac-Attack (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[27c133965dfd80b3acb1ed598817aea0] +title=Ms Pac-Man (Fast Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[cf007563fe94cacf5ea5295dc93ce9ef] +title=Ms Pac-Man (PacManPlus' Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[cad1e733986bce1ee4c9da73de1dcff1] +title=Ms Pac-Man Invincible Fast Hack +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[db768297985178cec034c12a41d6f1a7] +title=Ms Pac-Man 320 Invincible NTSC +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[889fc7e7ba5c807be44e85ba7a6bd26e] +title=Ms Pac-Man 320 (NTSC) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[bc56f803d65658f92c17e6c2b271a507] +title=Ms. Pac-Man 320 (PAL) +type=0 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +[2a17dc5a61be342dd00af719cc335852] +title=Ms Pac-Man 320 Sound Upd NTSC +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[99055c3e627bbc17fc81cbe0b3ae176c] +title=Ms Pac-Man 320 Sound Upd PAL +type=0 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +[a69347c8a681b8e94f79d8d848998007] +title=Ms Pac-Man Twin +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[79202cb7d2bc150ffca0c96a4d8b42cf] +title=Multi-Lock On +type=1 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[04edf4f3c6b186147c1117359c8f5076] +title=Pac Pollux (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +hsc=true +[8338eca612eedf6ddec57d54942863e7] +title=Pac-Man (Fast Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[575c18f77a4215332bf56d0080a234b8] +title=Pac-Man (Ferrell's Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[72ec68627bb7d879ae35a71d7679f71e] +title=Pac-Man (PacManPlus' Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +hsc=true +[60982f430b762343d53e48f70acfa6d0] +title=Pac-Man 320 (NTSC) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[180121ecb4aabc7daa945b355e15c254] +title=Pac-Man 320 (PAL) +type=0 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +[4fb119f6db26380abba03e4ce3ca04c8] +title=Pac-Man Christmas 2018 Hack +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[0b7635d0f39ff97d1e841888e1b23b7b] +title=Pac-Man Christmas 2018 Inv Hack +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[5013b69cb05b21a1194ce48517df7bfc] +title=Pac-Man Collection +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true +[6f80cac59023a69afa26182eabbdfbad] +title=Pac-Man Collection New Monsters +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[b1685dcbaf1b578cb1b6643666d813e4] +title=Pac-Man Collection 2 (Hack) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[4748a62d5c628fefd28df5de5567edec] +title=Pac-Man Handheld (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[1d7d65997d7cd0858e9bee71ded272aa] +title=Pac-Man Plus (Ferrell's Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[791e55db03903988280388573a2fcdc1] +title=Pac-Man Plus (PacManPlus' Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +hsc=true +[d0bf3b841ad4bbd356e9588874749a13] +title=Pac-Man Plus (320 Mode) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +xm=true +[1482beef7dbdb122f6bb4b03640888f2] +title=Pac-Man Plus (320 Mode) +type=0 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=true +xm=true +[8cb66c6ed5b379181b1420d8e4758834] +title=Pactron 1984 (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +dualanalog=true +[c1ac9987a9483e200c338ccbd2ee94b5] +title=Pactron 1984 Extreme (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +dualanalog=true +[b5c9f0bf5b5763a923b7f370376b1849] +title=Panda Racer +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[b55e4d255173e5b2c2e620f3186a1ecc] +title=PC-Man (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[26897ab47b8c5d3b57d3cc235d7635d8] +title=Chomper (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[2b1f78aaa2b8de5dae3ee4b93ab678f4] +title=Christmas Pac-Man (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[a3a4dbd27c80eff9bef51f73cd26f1d5] +title=Invisible Maze Pac-Man (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[43a0059ff1b5bf76e0c7023fde7c33a5] +title=Jawbreaker (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[a8e752d108efceff504ae4edc4766b75] +title=Munchkin (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[04c985ebbd0bea4c557207e69b8cbd8f] +title=Munchman Texas (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[bc1f56d7cc14f15ddfcba5e21e19937b] +title=YPS Quest (Hack) +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +leftswitch=0 +rightswitch=1 +[8e0c5fc77b27422a39d86ac2e57dc73d] +title=Xmas Time (Hack) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[f9fa5107ed213e709858d8876359309e] +title=POKEY (Sample) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +[2370f7ce1b91fc775bce3e72454f908a] +title=Pokey Kong (Hack) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +[b4f137e85588ce42d302102ba7215437] +title=Prickle (POKEY Utility) (v09) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +[e1b01dd7e842d2b682ef48f689d5a4eb] +title=Rider of the Night +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[43525a0405184875c2ecfd0196886a34] +title=Rip-Off (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +xm=true +hsc=true +[106b409c6f4c219b1a3b3d099ead3b2b] +title=Rip-Off (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +xm=true +[03daa19b7aae2d27e61f2a4dbe3b9b79] +title=RMT POKEY Player Test (Demo) +type=0 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +[03935b9a1f2561bada58fcd5d9fd27de] +title=Robotron X (NTSC) (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +dualanalog=true +[d27ed8f883af9b4ee3b5570f30e9ff71] +title=Rowdytron (NTSC) (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +dualanalog=true +[01c7bc3cd8375e353c8aa837fe1262ec] +title=RPG Player and Map Tiles (Demo) +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[a3a85e507d6f718972b1464ce1aaf8a4] +title=Scramble +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +xm=true +[32f1a1b5a7e3b4493c3b7b637aeea7d8] +title=Scrapyard Dog Graphics-Life Hack +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[6e27f73bd4a49b647bcd58bc5f8b739d] +title=Srapyard Dog (Graphics Hack) +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[0070751edb8bbf4dd4a685f58b5b72c5] +title=Scrapyard Dog Unlimit Lives Hack +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[9bd70c06d3386f76f8162881699a777a] +title=Serpentine +type=3 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +[95c8a795e30640c9ec82609872c80517] +title=Shark Attack (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +rightswitch=1 +[1c8139c584e1cf5c6afdd2f3455a2446] +title=Sky Scraper 2115 +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[ca1c27b53fcfb9fed83bc9e92920707c] +title=Soft Cell-Tainted Love MusicDemo +type=4 +pokey=false +controller1=0 +controller2=0 +region=0 +flags=0 +[771cb4609347657f63e6f0eb26036e35] +title=Space Duel (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[a84c1b2300fbfbf21b1c02387f613dad] +title=Space Duel (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +[6adf79558a3d7f5beca1bb8d34337417] +title=Space Invaders (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[0f4bd5800359a62a5874b93dc92a47f1] +title=Spire of the Ancients +type=2 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +[02508e6df5e173b4063a7e6e63295817] +title=Super Circus AA-NTSC-Joy-0450 +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=true +xm=true +hsc=true +[81cee326b99d6831de10a566e338bd25] +title=Super Circus AA-NTSC-joy-4000 +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +hsc=true +[1c9b0bb028e63f83a2d1c1def675acc9] +title=Super Circus AA-PAL-Joy-0450 +type=0 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +xm=true +[f4ad1a1d732c2c8cdbd21dabaf38a46c] +title=Super Circus AA-PAL-Joy-4000 +type=0 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=false +hsc=false +[f41f651417c234104d37296477fa29eb] +title=Super Cobra (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true +[7ab539bb0e99e1e5a1c89230bde64610] +title=Super Pac-Man (NTSC) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true +[61aa4a074ad08c524fbee88d15e369ea] +title=Super Pac-Man (PAL) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=false +hsc=false +[3632fcc732a33591b91f0eea2c01e599] +title=Tank Command-Color Sprite Title +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[d0b87d349d6d5e40920cc4ff95253339] +title=Tank Command-Midnight Run Hack +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[9cb3848416e39ebf642357dbee3e5970] +title=Tempest (BBC X-Port 1) (v1_00F) +type=3 +pokey=false +controller1=1 +controller2=0 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[b1ec7bd809ab3deb746c5a5eb2efaecb] +title=UFO! +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[43f8e9cec3d9991017709f48a7aa22f6] +title=UFO! Genesys (Hack) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[f85d506f5933427c8de664be0c5510a3] +title=Ultra Pac-Man (PacManPlus' Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true +[f83849cf3f5ac95856e8f93ee90d5a8d] +title=Upside Down Pac-Man (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +rightswitch=1 +[c62632545c91823f72f6f14b19766804] +title=WarBirds +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[40913dcf24a623c1dc2495a1c4931b48] +title=Water Ski - Title Color Realign +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[8b49549763f4f0e42a23942b8df6b248] +title=Water Ski-Titl Col Reali Trained +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[7db031f1c4dc957719812fe68ee42531] +title=Xevious X (PAL) (Hack) +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=false +hsc=false +[5837c4ac8b481fb98381adfd2fe87969] +title=Armor Attack +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=true +hsc=false +[05b04e9822a75ceeeaa2eb106ffe768e] +title=Adventure Map Demo +type=4 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[727b6d447e21af42b3767f9c2cff6012] +title=DFHSC78.BIN +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true +[c3107d3e3e17d67e3a11d47a5946a4f3] +title=DONKEY KONG XM +type=2 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true +[8caa29a8d9214ca02697b3357102309a] +title=DONKEY KONG XM +type=2 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=false +hsc=false +[b3143adbbb7d7d189e918e5b29d55a72] +title=DungeonStalker_Final +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[e547492ebd342e57c28bb235546da299] +title=3D Demo +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=false +hsc=false +[89b8b3df46733e0c4d57aeb9bb245e6f] +title=Armor Attack II +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[7cdfbe37634e7dcd4dc67db7edbcd3ba] +title=Baby Pac-Man +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=false +[1ae0b27d47f19d59652168fad3966375] +title=Crazy Otto +type=0 +pokey=true +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=false +hsc=false +[35433868dfe383ae21fd77507e5a478d] +title=Ms. Pac-Man (320 Mode) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=true +hsc=false +[59f1c1e7f6653a4e66ea898ce6eab50f] +title=Pac-Man Collection! v2 +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true +[c2b42639718d005a6d0aefa0809f77db] +title=Pac-Man Collection! v2 +type=0 +pokey=false +controller1=1 +controller2=1 +region=1 +flags=0 +pokey450=false +xm=false +hsc=false +[80ffad3edb50f0970e780a727a4524dd] +title=Pac-Man (320 Mode) +type=0 +pokey=true +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true +[ff8d8283553af5d5dbdaddb5781b4896] +title=Vector Asteroids +type=0 +pokey=false +controller1=1 +controller2=1 +region=0 +flags=0 +pokey450=false +xm=false +hsc=true diff --git a/ProSystem.xcodeproj/project.pbxproj b/ProSystem.xcodeproj/project.pbxproj index 4fd6f46..d5dd0cc 100644 --- a/ProSystem.xcodeproj/project.pbxproj +++ b/ProSystem.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ /* Begin PBXBuildFile section */ 82EC409F0FD9EC420017FC19 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 82EC409E0FD9EC420017FC19 /* libz.dylib */; }; + 871EC9A224F08BF700CEC578 /* ExpansionModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */; }; 8794D9691B74713300897F57 /* Sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 941F59AF17A6189D0005D7EA /* Sound.cpp */; }; 8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; }; 8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; }; @@ -98,6 +99,8 @@ 089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 82EC409E0FD9EC420017FC19 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; + 871EC9A024F08BF600CEC578 /* ExpansionModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpansionModule.h; sourceTree = ""; }; + 871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExpansionModule.cpp; sourceTree = ""; }; 8D5B49B6048680CD000E48DA /* ProSystem.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ProSystem.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 941DFB2615B6425200C6552F /* ProSystemGameCore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProSystemGameCore.mm; sourceTree = ""; }; @@ -269,6 +272,8 @@ 941F598917A6189D0005D7EA /* Database.cpp */, 941F598A17A6189D0005D7EA /* Database.h */, 941F598B17A6189D0005D7EA /* Equates.h */, + 871EC9A124F08BF600CEC578 /* ExpansionModule.cpp */, + 871EC9A024F08BF600CEC578 /* ExpansionModule.h */, 941F598C17A6189D0005D7EA /* Hash.cpp */, 941F598D17A6189D0005D7EA /* Hash.h */, 941F598E17A6189D0005D7EA /* lib */, @@ -453,6 +458,7 @@ 941F59CD17A6189D0005D7EA /* Pokey.cpp in Sources */, 941F59CE17A6189D0005D7EA /* ProSystem.cpp in Sources */, 941F59CF17A6189D0005D7EA /* Region.cpp in Sources */, + 871EC9A224F08BF700CEC578 /* ExpansionModule.cpp in Sources */, 941F59D017A6189D0005D7EA /* Riot.cpp in Sources */, 941F59D117A6189D0005D7EA /* Sally.cpp in Sources */, 941F59D317A6189D0005D7EA /* Tia.cpp in Sources */, diff --git a/ProSystemGameCore.mm b/ProSystemGameCore.mm index a7c1e18..72ebd8c 100644 --- a/ProSystemGameCore.mm +++ b/ProSystemGameCore.mm @@ -96,18 +96,20 @@ database_enabled = true; // BIOS is optional - NSString *biosROM = [[self biosDirectoryPath] stringByAppendingPathComponent:@"7800 BIOS (U).rom"]; + NSString *biosROM = [self.biosDirectoryPath stringByAppendingPathComponent:@"7800 BIOS (U).rom"]; if (bios_Load(biosROM.fileSystemRepresentation)) bios_enabled = true; - NSLog(@"Headerless MD5 hash: %s", cartridge_digest.c_str()); - NSLog(@"Header info (often wrong):\ntitle: %s\ntype: %d\nregion: %s\npokey: %s", cartridge_title.c_str(), cartridge_type, cartridge_region == REGION_NTSC ? "NTSC" : "PAL", cartridge_pokey ? "true" : "false"); + NSLog(@"[ProSystem] Headerless MD5 hash: %s", cartridge_digest.c_str()); + NSLog(@"[ProSystem] Header info (often wrong):\ntitle: %s\ntype: %d\nregion: %s\npokey: %s", cartridge_title.c_str(), cartridge_type, cartridge_region == REGION_NTSC ? "NTSC" : "PAL", cartridge_pokey ? "true" : "false"); database_Load(cartridge_digest); prosystem_Reset(); - std::string title = common_Trim(cartridge_title); - NSLog(@"Database info:\ntitle: %@\ntype: %d\nregion: %s\npokey: %s", [NSString stringWithUTF8String:title.c_str()], cartridge_type, cartridge_region == REGION_NTSC ? "NTSC" : "PAL", cartridge_pokey ? "true" : "false"); + if (cart_in_db) { + std::string title = common_Trim(cartridge_title); + NSLog(@"[ProSystem] Database info:\ntitle: %@\ntype: %d\nregion: %s\npokey: %s", [NSString stringWithUTF8String:title.c_str()], cartridge_type, cartridge_region == REGION_NTSC ? "NTSC" : "PAL", cartridge_pokey ? "true" : "false"); + } //sound_SetSampleRate(48000); [self setPalette32]; @@ -117,12 +119,9 @@ if(_isLightgunEnabled) _inputState[3] = 1; - // Set defaults for Bentley Bear (homebrew) so button 1 = run/shoot and button 2 = jump - if(cartridge_digest == "ad35a98040a2facb10ecb120bf83bcc3") - { - _inputState[LEFT_DIFF_SWITCH] = RIGHT_POSITION; - _inputState[RIGHT_DIFF_SWITCH] = LEFT_POSITION; - } + // Set switch overrides from database + _inputState[LEFT_DIFF_SWITCH] = cartridge_left_switch; + _inputState[RIGHT_DIFF_SWITCH] = cartridge_right_switch; return YES; } @@ -232,6 +231,9 @@ - (NSData *)serializeStateWithError:(NSError **)outError { size_t length = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453; + if(cartridge_xm) { + length += 4 + XM_RAM_SIZE; + } void *bytes = malloc(length); if(prosystem_Save_buffer((uint8_t *)bytes)) @@ -250,18 +252,21 @@ - (BOOL)deserializeState:(NSData *)state withError:(NSError **)outError { size_t serial_size = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453; - if(serial_size != [state length]) { + if(cartridge_xm) { + serial_size += 4 + XM_RAM_SIZE; + } + if(serial_size != state.length) { if(outError) { *outError = [NSError errorWithDomain:OEGameCoreErrorDomain code:OEGameCoreStateHasWrongSizeError userInfo:@{ NSLocalizedDescriptionKey : @"Save state has wrong file size.", - NSLocalizedRecoverySuggestionErrorKey : [NSString stringWithFormat:@"The save state does not have the right size, %ld expected, got: %ld.", serial_size, [state length]] + NSLocalizedRecoverySuggestionErrorKey : [NSString stringWithFormat:@"The save state does not have the right size, %ld expected, got: %ld.", serial_size, state.length] }]; } return NO; } - if(prosystem_Load_buffer((uint8_t *)[state bytes])) + if(prosystem_Load_buffer((uint8_t *)state.bytes)) return YES; if(outError) { diff --git a/core/Cartridge.cpp b/core/Cartridge.cpp index b3624a9..766a2c3 100755 --- a/core/Cartridge.cpp +++ b/core/Cartridge.cpp @@ -5,7 +5,7 @@ // // ---------------------------------------------------------------------------- // Copyright 2005 Greg Stanton -// +// // 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 @@ -23,6 +23,9 @@ // Cartridge.cpp // ---------------------------------------------------------------------------- #include "Cartridge.h" +#include "Region.h" + +#include #define CARTRIDGE_SOURCE "Cartridge.cpp" std::string cartridge_title; @@ -34,13 +37,20 @@ std::string cartridge_filename; byte cartridge_type; byte cartridge_region; bool cartridge_pokey; -byte cartridge_controller[2]; +bool cartridge_pokey450; +byte cartridge_controller[2] = {1, 1}; byte cartridge_bank; uint cartridge_flags; int cartridge_crosshair_x; int cartridge_crosshair_y; bool cartridge_dualanalog = false; +bool cartridge_xm = false; +bool cartridge_disable_bios = false; uint cartridge_hblank = 34; +byte cartridge_left_switch = 1; +byte cartridge_right_switch = 0; +bool cartridge_swap_buttons = false; +bool cartridge_hsc_enabled = false; static byte* cartridge_buffer = NULL; static uint cartridge_size = 0; @@ -72,16 +82,23 @@ static bool cartridge_CC2(const byte* header) { } // ---------------------------------------------------------------------------- -// GetBankOffset +// GetBank // ---------------------------------------------------------------------------- -static uint cartridge_GetBankOffset(byte bank) { +static uint cartridge_GetBank(byte bank) { if ((cartridge_type == CARTRIDGE_TYPE_SUPERCART || cartridge_type == CARTRIDGE_TYPE_SUPERCART_ROM || cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) && cartridge_size <= 65536) { // for some of these carts, there are only 4 banks. in this case we ignore bit 3 // previously, games of this type had to be doubled. The first 4 banks needed to be duplicated at the end of the ROM - return (bank & 3) * 16384; + return (bank & 3); } - return bank * 16384; + return bank; +} + +// ---------------------------------------------------------------------------- +// GetBankOffset +// ---------------------------------------------------------------------------- +static uint cartridge_GetBankOffset(byte bank) { + return cartridge_GetBank(bank) * 16384; } // ---------------------------------------------------------------------------- @@ -95,16 +112,29 @@ static void cartridge_WriteBank(word address, byte bank) { } } +static void cartridge_SetTypeBySize(uint size) { + if (size <= 0x10000) { + cartridge_type = CARTRIDGE_TYPE_NORMAL; + } else if (size == 0x24000 ) { + cartridge_type = CARTRIDGE_TYPE_SUPERCART_LARGE; + } else if (size == 0x20000 ) { + cartridge_type = CARTRIDGE_TYPE_SUPERCART_ROM; + } else { + cartridge_type = CARTRIDGE_TYPE_SUPERCART; + } +} + // ---------------------------------------------------------------------------- // ReadHeader // ---------------------------------------------------------------------------- static void cartridge_ReadHeader(const byte* header) { + char temp[33] = {0}; for(int index = 0; index < 32; index++) { - temp[index] = header[index + 17]; + temp[index] = header[index + 17]; } cartridge_title = temp; - + cartridge_size = header[49] << 24; cartridge_size |= header[50] << 16; cartridge_size |= header[51] << 8; @@ -128,22 +158,47 @@ static void cartridge_ReadHeader(const byte* header) { } } else { - if(header[53] == 1) { + if(header[53] == 2 /*1*/) { // Wii: Abs and Act were swapped cartridge_type = CARTRIDGE_TYPE_ABSOLUTE; } - else if(header[53] == 2) { + else if(header[53] == 1 /*2*/) { // Wii: Abs and Act were swapped cartridge_type = CARTRIDGE_TYPE_ACTIVISION; } else { cartridge_type = CARTRIDGE_TYPE_NORMAL; } } - + cartridge_pokey = (header[54] & 1)? true: false; + cartridge_pokey450 = (header[54] & 0x40)? true : false; + if (cartridge_pokey450) { + cartridge_pokey = true; + } cartridge_controller[0] = header[55]; cartridge_controller[1] = header[56]; cartridge_region = header[57]; cartridge_flags = 0; + cartridge_xm = (header[63] & 1)? true: false; + cartridge_hsc_enabled = header[58]&0x01; + + // Wii: Updates to header interpretation + byte ct1 = header[54]; + if(header[53] == 0) { + if ((ct1&0x0a)==0x0a) { // BIT1 and BIT3 (Supercart Large: 2) rom at $4000 + cartridge_type = CARTRIDGE_TYPE_SUPERCART_LARGE; + } else if ((ct1&0x12)==0x12) { // BIT1 and BIT4 (Supercart ROM: 4) bank6 at $4000 + cartridge_type = CARTRIDGE_TYPE_SUPERCART_ROM; + } else if ((ct1&0x06)==0x06) { // BIT1 and BIT2 (Supercart RAM: 3) ram at $4000 + cartridge_type = CARTRIDGE_TYPE_SUPERCART_RAM; + } else if ((ct1&0x02)==0x02) { // BIT1 (Supercart) bank switched + cartridge_type = CARTRIDGE_TYPE_SUPERCART; + } else if (cartridge_size <= 0x10000 && ((ct1&0x04)==0x04)) { // Size < 64k && BIT2 (Normal RAM: ?) ram at $4000 ) + cartridge_type = CARTRIDGE_TYPE_NORMAL_RAM; + } else { + // Attempt to determine the cartridge type based on its size + cartridge_SetTypeBySize(cartridge_size); + } + } } // ---------------------------------------------------------------------------- @@ -156,7 +211,7 @@ static bool cartridge_Load(const byte* data, uint size) { } cartridge_Release( ); - + byte header[128] = {0}; for(int index = 0; index < 128; index++) { header[index] = data[index]; @@ -172,19 +227,29 @@ if (cartridge_CC2(header)) { cartridge_ReadHeader(header); size -= 128; offset = 128; - cartridge_size = size; + + // Several cartridge headers do not have the proper size. So attempt to use the size + // of the file. + if (cartridge_size != size) { + // Necessary for the following roms: + // Impossible Mission hacks w/ C64 style graphics + if (size % 1024 == 0) { + cartridge_size = size; + } + } } else { cartridge_size = size; + // Attempt to guess the cartridge type based on its size + cartridge_SetTypeBySize(size); } - + cartridge_buffer = new byte[cartridge_size]; for(int index = 0; index < cartridge_size; index++) { cartridge_buffer[index] = data[index + offset]; } - + cartridge_digest = hash_Compute(cartridge_buffer, cartridge_size); - return true; } @@ -196,10 +261,10 @@ bool cartridge_Load(std::string filename) { logger_LogError("Cartridge filename is invalid.", CARTRIDGE_SOURCE); return false; } - + cartridge_Release( ); logger_LogInfo("Opening cartridge file " + filename + ".", CARTRIDGE_SOURCE); - + byte* data = NULL; //uint size = archive_GetUncompressedFileSize(filename); uint size = 0; @@ -208,7 +273,7 @@ bool cartridge_Load(std::string filename) { FILE *file = fopen(filename.c_str( ), "rb"); if(file == NULL) { logger_LogError("Failed to open the cartridge file " + filename + " for reading.", CARTRIDGE_SOURCE); - return false; + return false; } if(fseek(file, 0L, SEEK_END)) { @@ -222,7 +287,7 @@ bool cartridge_Load(std::string filename) { logger_LogError("Failed to find the size of the cartridge file.", CARTRIDGE_SOURCE); return false; } - + data = new byte[size]; if(fread(data, 1, size, file) != size && ferror(file)) { fclose(file); @@ -230,15 +295,15 @@ bool cartridge_Load(std::string filename) { cartridge_Release( ); delete [ ] data; return false; - } + } - fclose(file); + fclose(file); } else { data = new byte[size]; //archive_Uncompress(filename, data, size); } - + if(!cartridge_Load(data, size)) { logger_LogError("Failed to load the cartridge data into memory.", CARTRIDGE_SOURCE); delete [ ] data; @@ -247,7 +312,7 @@ bool cartridge_Load(std::string filename) { if(data != NULL) { delete [ ] data; } - + cartridge_filename = filename; return true; } @@ -260,29 +325,37 @@ void cartridge_Store( ) { case CARTRIDGE_TYPE_NORMAL: memory_WriteROM(65536 - cartridge_size, cartridge_size, cartridge_buffer); break; - case CARTRIDGE_TYPE_SUPERCART: - if(cartridge_GetBankOffset(7) < cartridge_size) { - memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7)); - } + case CARTRIDGE_TYPE_NORMAL_RAM: + memory_WriteROM(65536 - cartridge_size, cartridge_size, cartridge_buffer); + memory_ClearROM(16384, 16384); break; - case CARTRIDGE_TYPE_SUPERCART_LARGE: - if(cartridge_GetBankOffset(8) < cartridge_size) { - memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(8)); + case CARTRIDGE_TYPE_SUPERCART: { + uint offset = cartridge_size - 16384; + if(offset < cartridge_size) { + memory_WriteROM(49152, 16384, cartridge_buffer + offset); + } + } break; + case CARTRIDGE_TYPE_SUPERCART_LARGE: { + uint offset = cartridge_size - 16384; + if(offset < cartridge_size) { + memory_WriteROM(49152, 16384, cartridge_buffer + offset); memory_WriteROM(16384, 16384, cartridge_buffer + cartridge_GetBankOffset(0)); } - break; - case CARTRIDGE_TYPE_SUPERCART_RAM: - if(cartridge_GetBankOffset(7) < cartridge_size) { - memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7)); + } break; + case CARTRIDGE_TYPE_SUPERCART_RAM: { + uint offset = cartridge_size - 16384; + if(offset < cartridge_size) { + memory_WriteROM(49152, 16384, cartridge_buffer + offset); memory_ClearROM(16384, 16384); } - break; - case CARTRIDGE_TYPE_SUPERCART_ROM: - if(cartridge_GetBankOffset(7) < cartridge_size && cartridge_GetBankOffset(6) < cartridge_size) { - memory_WriteROM(49152, 16384, cartridge_buffer + cartridge_GetBankOffset(7)); + } break; + case CARTRIDGE_TYPE_SUPERCART_ROM: { + uint offset = cartridge_size - 16384; + if(offset < cartridge_size && cartridge_GetBankOffset(6) < cartridge_size) { + memory_WriteROM(49152, 16384, cartridge_buffer + offset); memory_WriteROM(16384, 16384, cartridge_buffer + cartridge_GetBankOffset(6)); } - break; + } break; case CARTRIDGE_TYPE_ABSOLUTE: memory_WriteROM(16384, 16384, cartridge_buffer); memory_WriteROM(32768, 32768, cartridge_buffer + cartridge_GetBankOffset(2)); @@ -306,16 +379,18 @@ void cartridge_Write(word address, byte data) { switch(cartridge_type) { case CARTRIDGE_TYPE_SUPERCART: case CARTRIDGE_TYPE_SUPERCART_RAM: - case CARTRIDGE_TYPE_SUPERCART_ROM: - if(address >= 32768 && address < 49152 && data < 9) { + case CARTRIDGE_TYPE_SUPERCART_ROM: { + uint maxbank = cartridge_size / 16384; + if(address >= 32768 && address < 49152 && cartridge_GetBank(data) < maxbank /*9*/) { cartridge_StoreBank(data); } - break; - case CARTRIDGE_TYPE_SUPERCART_LARGE: - if(address >= 32768 && address < 49152 && data < 9) { + } break; + case CARTRIDGE_TYPE_SUPERCART_LARGE: { + uint maxbank = cartridge_size / 16384; + if(address >= 32768 && address < 49152 && cartridge_GetBank(data) < maxbank /*9*/) { cartridge_StoreBank(data + 1); } - break; + } break; case CARTRIDGE_TYPE_ABSOLUTE: if(address == 32768 && (data == 1 || data == 2)) { cartridge_StoreBank(data - 1); @@ -328,6 +403,7 @@ void cartridge_Write(word address, byte data) { break; } +#if 0 // WIi: Moved to Memory.cpp if(cartridge_pokey && address >= 0x4000 && address <= 0x400f) { switch(address) { case POKEY_AUDF1: @@ -362,6 +438,7 @@ void cartridge_Write(word address, byte data) { break; } } +#endif } // ---------------------------------------------------------------------------- @@ -379,7 +456,7 @@ void cartridge_StoreBank(byte bank) { cartridge_WriteBank(32768, bank); break; case CARTRIDGE_TYPE_SUPERCART_LARGE: - cartridge_WriteBank(32768, bank); + cartridge_WriteBank(32768, bank); break; case CARTRIDGE_TYPE_ABSOLUTE: cartridge_WriteBank(16384, bank); @@ -387,7 +464,7 @@ void cartridge_StoreBank(byte bank) { case CARTRIDGE_TYPE_ACTIVISION: cartridge_WriteBank(40960, bank); break; - } + } } // ---------------------------------------------------------------------------- @@ -405,16 +482,24 @@ void cartridge_Release( ) { delete [ ] cartridge_buffer; cartridge_size = 0; cartridge_buffer = NULL; - + cartridge_title = ""; cartridge_type = 0; cartridge_region = 0; cartridge_pokey = 0; - memset(cartridge_controller, 0, sizeof(cartridge_controller)); + cartridge_pokey450 = 0; + cartridge_xm = false; + // Default to joysticks + memset( cartridge_controller, 1, sizeof( cartridge_controller ) ); cartridge_bank = 0; cartridge_flags = 0; + cartridge_disable_bios = false; cartridge_crosshair_x = 0; cartridge_crosshair_y = 0; - cartridge_hblank = 34; + cartridge_hblank = HBLANK_DEFAULT; cartridge_dualanalog = false; + cartridge_left_switch = 1; + cartridge_right_switch = 0; + cartridge_swap_buttons = false; + cartridge_hsc_enabled = false; } } diff --git a/core/Cartridge.h b/core/Cartridge.h index 3f8bd72..8b661ee 100755 --- a/core/Cartridge.h +++ b/core/Cartridge.h @@ -31,12 +31,15 @@ #define CARTRIDGE_TYPE_SUPERCART_ROM 4 #define CARTRIDGE_TYPE_ABSOLUTE 5 #define CARTRIDGE_TYPE_ACTIVISION 6 +#define CARTRIDGE_TYPE_NORMAL_RAM 7 #define CARTRIDGE_CONTROLLER_NONE 0 #define CARTRIDGE_CONTROLLER_JOYSTICK 1 #define CARTRIDGE_CONTROLLER_LIGHTGUN 2 #define CARTRIDGE_WSYNC_MASK 2 #define CARTRIDGE_CYCLE_STEALING_MASK 1 +#define HBLANK_DEFAULT 34 + #include #include #include "Equates.h" @@ -65,9 +68,15 @@ extern std::string cartridge_filename; extern byte cartridge_type; extern byte cartridge_region; extern bool cartridge_pokey; +extern bool cartridge_pokey450; +extern bool cartridge_xm; extern byte cartridge_controller[2]; extern byte cartridge_bank; extern uint cartridge_flags; +extern bool cartridge_disable_bios; +extern byte cartridge_left_switch; +extern byte cartridge_right_switch; +extern bool cartridge_swap_buttons; // The x offset for the lightgun crosshair (allows per cartridge adjustments) extern int cartridge_crosshair_x; @@ -77,5 +86,7 @@ extern int cartridge_crosshair_y; extern uint cartridge_hblank; // Whether the cartridge supports dual analog extern bool cartridge_dualanalog; +// Whether the high score cart is enabled +extern bool cartridge_hsc_enabled; -#endif \ No newline at end of file +#endif diff --git a/core/Database.cpp b/core/Database.cpp index d986a38..6c64b4a 100755 --- a/core/Database.cpp +++ b/core/Database.cpp @@ -25,6 +25,7 @@ #include "Database.h" #define DATABASE_SOURCE "Database.cpp" +bool cart_in_db = false; bool database_enabled = true; std::string database_filename; @@ -44,6 +45,7 @@ void database_Initialize( ) { // Load // ---------------------------------------------------------------------------- bool database_Load(std::string digest) { + cart_in_db = false; if(database_enabled) { logger_LogInfo("Accessing database " + database_filename + ".", DATABASE_SOURCE); @@ -53,13 +55,22 @@ bool database_Load(std::string digest) { return false; } + // max count of items in the database + static int count = 17; + char buffer[256]; while(fgets(buffer, 256, file) != NULL) { std::string line = buffer; if(line.compare(1, 32, digest.c_str( )) == 0) { - std::string entry[11]; - for(int index = 0; index < 11; index++) { + cart_in_db = true; + std::string entry[count]; + for (int index = 0; index < count; index++) { + buffer[0] = '\0'; fgets(buffer, 256, file); + if (strchr(buffer, '[')) { + // Passed the current game in DB + break; + } entry[index] = common_Remove(buffer, '\n'); entry[index] = common_Remove(entry[index], '\r'); } @@ -73,7 +84,7 @@ bool database_Load(std::string digest) { cartridge_flags = common_ParseUint(database_GetValue(entry[6])); // Optionally load the lightgun crosshair offsets, hblank, dual analog - for(int index = 7; index < 11; index++) + for(int index = 7; index < count; index++) { if(entry[index].find("crossx") != std::string::npos) { @@ -90,9 +101,32 @@ bool database_Load(std::string digest) { if(entry[index].find("dualanalog") != std::string::npos) { cartridge_dualanalog = common_ParseBool(database_GetValue(entry[index])); - } + } + if (entry[index].find("pokey450") != std::string::npos) { + cartridge_pokey450 = common_ParseBool(database_GetValue(entry[index])); + if (cartridge_pokey450) { + cartridge_pokey = true; + } + } + if (entry[index].find("xm") != std::string::npos) { + cartridge_xm = common_ParseBool(database_GetValue(entry[index])); + } + if (entry[index].find("disablebios") != std::string::npos) { + cartridge_disable_bios = common_ParseBool(database_GetValue(entry[index])); + } + if (entry[index].find("leftswitch") != std::string::npos) { + cartridge_left_switch = common_ParseByte(database_GetValue(entry[index])); + } + if (entry[index].find("rightswitch") != std::string::npos) { + cartridge_right_switch = common_ParseByte(database_GetValue(entry[index])); + } + if (entry[index].find("swapbuttons") != std::string::npos) { + cartridge_swap_buttons = common_ParseBool(database_GetValue(entry[index])); + } + if (entry[index].find("hsc") != std::string::npos) { + cartridge_hsc_enabled = common_ParseBool(database_GetValue(entry[index])); + } } - break; } } diff --git a/core/Database.h b/core/Database.h index d00f3b5..01e1c97 100755 --- a/core/Database.h +++ b/core/Database.h @@ -38,5 +38,6 @@ extern void database_Initialize( ); extern bool database_Load(std::string digest); extern bool database_enabled; extern std::string database_filename; +extern bool cart_in_db; -#endif \ No newline at end of file +#endif diff --git a/core/ExpansionModule.cpp b/core/ExpansionModule.cpp new file mode 100644 index 0000000..26f1e63 --- /dev/null +++ b/core/ExpansionModule.cpp @@ -0,0 +1,81 @@ +/* + Memory map: + + POKEY1 $0450 $045F 16 bytes + POKEY2* $0460 $046F 16 bytes + XCTRL $0470 $047F 1 byte + RAM $4000 $7FFF 16384 bytes + +XCTRL Bit Description + ++-------------------------------+ +| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ++-------------------------------+ + | | | | | | | | + | | | | | | | +-- Bank select bit 0 \ + | | | | | | +------ Bank select bit 1 | Totally 128 KByte in 16 KByte banks + | | | | | +---------- Bank select bit 3 / + | | | | +-------------- Enable memory bit (1 = Memory enabled, 0 after power on) + | | | +------------------ Enable POKEY bit** (1 = POKEY enabled, 0 after power on) + | | | + NA NA NA = Not Available or Not Used + +* = Can be mounted piggy back on the first POKEY. Description how to do this will come when i have tried it out. +** This bit controls both POKEY chip select signals. + + +The mapping is totally non compatible with pretty much everything. +There is a bank select latch located at $0470 and the POKEY is located at $0450 +(There's also a chip select output ($0460) on the PLD which alows you to simply piggy back a second POKEY). +Since the PLD is reconfigurable I could map the POKEY (or the RAM for that matter) to pretty much anything +if you wanted to. However since the PLD is soldered under the POKEY this needs to be configured before delivery. +*/ + +#include +#include "ExpansionModule.h" + +byte xm_ram[XM_RAM_SIZE] = {0}; +byte xm_reg = 0; +byte xm_bank = 0; +bool xm_pokey_enabled = false; +bool xm_mem_enabled = false; + +void xm_Reset() { + memset(xm_ram, 0, XM_RAM_SIZE); + xm_bank = 0; + xm_reg = 0; + xm_pokey_enabled = false; + xm_mem_enabled = false; +} + +byte xm_Read(word address) { + if (xm_pokey_enabled && (address >= 0x0450 && address < 0x0460)) { + byte b = pokey_GetRegister(0x4000 + (address - 0x0450)); + return b; + } else if (xm_pokey_enabled && (address >= 0x0460 && address < 0x0470)) { + byte b = pokey_GetRegister(0x4000 + (address - 0x0460)); + return b; + } else if (xm_mem_enabled && (address >= 0x4000 && address < 0x8000)) { + byte b = xm_ram[(xm_bank * 0x4000) + (address - 0x4000)]; + return b; + } else if (address >= 0x0470 && address < 0x0480) { + // TODO: Should the value be returned? + } + return 0; +} + +void xm_Write(word address, byte data) { + if (xm_pokey_enabled && (address >= 0x0450 && address < 0x0460)) { + pokey_SetRegister(0x4000 + (address - 0x0450), data); + } else if (xm_pokey_enabled && (address >= 0x0460 && address < 0x0470)) { + pokey_SetRegister(0x4000 + (address - 0x0460), data); + } else if (xm_mem_enabled && (address >= 0x4000 && address < 0x8000)) { + + xm_ram[(xm_bank * 0x4000) + (address - 0x4000)] = data; + } else if (address >= 0x0470 && address < 0x0480) { + xm_reg = data; + xm_bank = xm_reg & 7; + xm_pokey_enabled = (xm_reg & 0x10) > 0; + xm_mem_enabled = (xm_reg & 0x08) > 0; + } +} diff --git a/core/ExpansionModule.h b/core/ExpansionModule.h new file mode 100644 index 0000000..ee811b0 --- /dev/null +++ b/core/ExpansionModule.h @@ -0,0 +1,19 @@ +#ifndef EXPANSIONMODULE_H +#define EXPANSIONMODULE_H + +#include "Cartridge.h" +#include "Memory.h" + +#define XM_RAM_SIZE 0x20000 + +extern byte xm_ram[XM_RAM_SIZE]; +extern bool xm_pokey_enabled; +extern bool xm_mem_enabled; +extern byte xm_reg; +extern byte xm_bank; + + +void xm_Reset(); +byte xm_Read(word address); +void xm_Write(word address, byte data); +#endif diff --git a/core/Maria.cpp b/core/Maria.cpp index 380ce07..9d925e5 100755 --- a/core/Maria.cpp +++ b/core/Maria.cpp @@ -5,7 +5,7 @@ // // ---------------------------------------------------------------------------- // Copyright 2005 Greg Stanton -// +// // 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 @@ -45,12 +45,12 @@ static byte maria_wmode; // ---------------------------------------------------------------------------- // StoreCell // ---------------------------------------------------------------------------- -static void maria_StoreCell(byte data) { +static inline void maria_StoreCell(byte data) { if(maria_horizontal < MARIA_LINERAM_SIZE) { if(data) { maria_lineRAM[maria_horizontal] = maria_palette | data; } - else { + else { byte kmode = memory_ram[CTRL] & 4; if(kmode) { maria_lineRAM[maria_horizontal] = 0; @@ -63,12 +63,12 @@ static void maria_StoreCell(byte data) { // ---------------------------------------------------------------------------- // StoreCell // ---------------------------------------------------------------------------- -static void maria_StoreCell(byte high, byte low) { +static inline void maria_StoreCell(byte high, byte low) { if(maria_horizontal < MARIA_LINERAM_SIZE) { if(low || high) { maria_lineRAM[maria_horizontal] = (maria_palette & 16) | high | low; } - else { + else { byte kmode = memory_ram[CTRL] & 4; if(kmode) { maria_lineRAM[maria_horizontal] = 0; @@ -81,7 +81,7 @@ static void maria_StoreCell(byte high, byte low) { // ---------------------------------------------------------------------------- // IsHolyDMA // ---------------------------------------------------------------------------- -static bool maria_IsHolyDMA( ) { +static inline bool maria_IsHolyDMA( ) { if(maria_pp.w > 32767) { if(maria_h16 && (maria_pp.w & 4096)) { return true; @@ -96,7 +96,7 @@ static bool maria_IsHolyDMA( ) { // ---------------------------------------------------------------------------- // GetColor // ---------------------------------------------------------------------------- -static byte maria_GetColor(byte data) { +static inline byte maria_GetColor(byte data) { if(data & 3) { return memory_ram[BACKGRND + data]; } @@ -108,12 +108,15 @@ static byte maria_GetColor(byte data) { // ---------------------------------------------------------------------------- // StoreGraphic // ---------------------------------------------------------------------------- -static void maria_StoreGraphic( ) { +static inline void maria_StoreGraphic( ) { byte data = memory_ram[maria_pp.w]; if(maria_wmode) { if(maria_IsHolyDMA( )) { +#if 0 // Wii: disabled due to rendering in Kangaroo mode maria_StoreCell(0, 0); maria_StoreCell(0, 0); +#endif + maria_horizontal+=2; } else { maria_StoreCell((data & 12), (data & 192) >> 6); @@ -122,10 +125,13 @@ static void maria_StoreGraphic( ) { } else { if(maria_IsHolyDMA( )) { +#if 0 // Wii: disabled due to rendering in Kangaroo mode maria_StoreCell(0); maria_StoreCell(0); maria_StoreCell(0); maria_StoreCell(0); +#endif + maria_horizontal+=4; } else { maria_StoreCell((data & 192) >> 6); @@ -140,9 +146,10 @@ static void maria_StoreGraphic( ) { // ---------------------------------------------------------------------------- // WriteLineRAM // ---------------------------------------------------------------------------- -static void maria_WriteLineRAM(byte* buffer) { +static inline void maria_WriteLineRAM(byte* buffer) { byte rmode = memory_ram[CTRL] & 3; if(rmode == 0) { + // 160A/B int pixel = 0; for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) { word color; @@ -160,7 +167,8 @@ static void maria_WriteLineRAM(byte* buffer) { buffer[pixel++] = color; } } - else if(rmode == 2) { + else if(rmode == 2) { + // 320B/D int pixel = 0; for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) { buffer[pixel++] = maria_GetColor((maria_lineRAM[index + 0] & 16) | ((maria_lineRAM[index + 0] & 8) >> 3) | ((maria_lineRAM[index + 0] & 2))); @@ -174,6 +182,7 @@ static void maria_WriteLineRAM(byte* buffer) { } } else if(rmode == 3) { + // 320A/C int pixel = 0; for(int index = 0; index < MARIA_LINERAM_SIZE; index += 4) { buffer[pixel++] = maria_GetColor((maria_lineRAM[index + 0] & 30)); @@ -191,20 +200,20 @@ static void maria_WriteLineRAM(byte* buffer) { // ---------------------------------------------------------------------------- // StoreLineRAM // ---------------------------------------------------------------------------- -static void maria_StoreLineRAM( ) { +static inline void maria_StoreLineRAM( ) { for(int index = 0; index < MARIA_LINERAM_SIZE; index++) { maria_lineRAM[index] = 0; } - + byte mode = memory_ram[maria_dp.w + 1]; while(mode & 0x5f) { byte width; byte indirect = 0; - + maria_pp.b.l = memory_ram[maria_dp.w]; maria_pp.b.h = memory_ram[maria_dp.w + 2]; - - if(mode & 31) { + + if(mode & 31) { maria_cycles += 8; // Maria cycles (Header 4 byte) maria_palette = (memory_ram[maria_dp.w + 1] & 224) >> 3; maria_horizontal = memory_ram[maria_dp.w + 3]; @@ -212,7 +221,7 @@ static void maria_StoreLineRAM( ) { width = ((~width) & 31) + 1; maria_dp.w += 4; } - else { + else { maria_cycles += 12; // Maria cycles (Header 5 byte) maria_palette = (memory_ram[maria_dp.w + 3] & 224) >> 3; maria_horizontal = memory_ram[maria_dp.w + 4]; @@ -237,7 +246,6 @@ static void maria_StoreLineRAM( ) { maria_cycles += 3; // Maria cycles (Indirect) maria_pp.b.l = memory_ram[basePP.w++]; maria_pp.b.h = memory_ram[CHARBASE] + maria_offset; - maria_cycles += 3; // Maria cycles (Indirect, 1 byte) maria_StoreGraphic( ); if(cwidth) { @@ -280,10 +288,10 @@ uint maria_RenderScanline( ) { // lightgun flash // Displays the background color when Maria is disabled (if applicable) if( ( ( memory_ram[CTRL] & 96 ) != 64 ) && - maria_scanline >= maria_visibleArea.top && + maria_scanline >= maria_visibleArea.top && maria_scanline <= maria_visibleArea.bottom ) { byte bgcolor = maria_GetColor(0); - byte *bgstart = maria_surface + ((maria_scanline - maria_displayArea.top) * maria_displayArea.GetLength()); + byte *bgstart = maria_surface + ((maria_scanline - maria_displayArea.top) * maria_displayArea.GetLength()); for(uint index = 0; index < MARIA_LINERAM_SIZE; index++ ) { *bgstart++ = bgcolor; *bgstart++ = bgcolor; @@ -329,7 +337,7 @@ uint maria_RenderScanline( ) { { maria_cycles += 4; // Maria cycles (Other lines of zone) } - } + } } return maria_cycles; } @@ -341,4 +349,4 @@ void maria_Clear( ) { for(int index = 0; index < MARIA_SURFACE_SIZE; index++) { maria_surface[index] = 0; } -} \ No newline at end of file +} diff --git a/core/Memory.cpp b/core/Memory.cpp index 84ccbb9..26da85d 100755 --- a/core/Memory.cpp +++ b/core/Memory.cpp @@ -5,7 +5,7 @@ // // ---------------------------------------------------------------------------- // Copyright 2005 Greg Stanton -// +// // 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 @@ -23,6 +23,7 @@ // Memory.cpp // ---------------------------------------------------------------------------- #include "Memory.h" +#include "ExpansionModule.h" byte memory_ram[MEMORY_SIZE] = {0}; byte memory_rom[MEMORY_SIZE] = {0}; @@ -46,22 +47,32 @@ void memory_Reset( ) { byte memory_Read(word address) { byte tmp_byte; - if(cartridge_pokey && address == POKEY_RANDOM) - { - return pokey_GetRegister(POKEY_RANDOM); + if (cartridge_xm) { + if ((address >= 0x0470 && address < 0x0480) || + (xm_pokey_enabled && (address >= 0x0450 && address < 0x0470)) || + (xm_mem_enabled && (address >= 0x4000 && address < 0x8000))) { + return xm_Read(address); + } + } + + if (cartridge_pokey && ( + (!cartridge_pokey450 && (address >= 0x4000 && address <= 0x400f)) || + (cartridge_pokey450 && (address >= 0x0450 && address < 0x0470)))) { + return pokey_GetRegister( + cartridge_pokey450 ? 0x4000 + (address - 0x0450) : address); } switch ( address ) { case INTIM: case INTIM | 0x2: - memory_ram[INTFLG] &= 0x7f; + memory_ram[INTFLG] &= 0x7f; return memory_ram[INTIM]; - break; + break; case INTFLG: case INTFLG | 0x2: - tmp_byte = memory_ram[INTFLG]; - memory_ram[INTFLG] &= 0x7f; - return tmp_byte; + tmp_byte = memory_ram[INTFLG]; + memory_ram[INTFLG] &= 0x7f; + return tmp_byte; break; default: return memory_ram[address]; @@ -73,6 +84,21 @@ byte memory_Read(word address) { // Write // ---------------------------------------------------------------------------- void memory_Write(word address, byte data) { + if (cartridge_xm && + ((address >= 0x0470 && address < 0x0480) || + ((xm_pokey_enabled && (address >= 0x0450 && address < 0x0470)) || + (xm_mem_enabled && (address >= 0x4000 && address < 0x8000))))) { + xm_Write(address, data); + return; + } + + if (cartridge_pokey && ( + (!cartridge_pokey450 && (address >= 0x4000 && address <= 0x400f)) || + (cartridge_pokey450 && (address >= 0x0450 && address < 0x0470)))) { + pokey_SetRegister( + (cartridge_pokey450 ? 0x4000 + (address - 0x0450) : address), data); + return; + } if(!memory_rom[address]) { switch(address) { @@ -82,8 +108,8 @@ void memory_Write(word address, byte data) { } break; case INPTCTRL: - if(data == 22 && cartridge_IsLoaded( )) { - cartridge_Store( ); + if(data == 22 && cartridge_IsLoaded( )) { + cartridge_Store( ); } else if(data == 2 && bios_enabled) { bios_Store( ); @@ -168,7 +194,7 @@ void memory_Write(word address, byte data) { // ---------------------------------------------------------------------------- // WriteROM // ---------------------------------------------------------------------------- -void memory_WriteROM(word address, word size, const byte* data) { +void memory_WriteROM(word address, uint size, const byte* data) { if((address + size) <= MEMORY_SIZE && data != NULL) { for(uint index = 0; index < size; index++) { memory_ram[address + index] = data[index]; @@ -180,7 +206,7 @@ void memory_WriteROM(word address, word size, const byte* data) { // ---------------------------------------------------------------------------- // ClearROM // ---------------------------------------------------------------------------- -void memory_ClearROM(word address, word size) { +void memory_ClearROM(word address, uint size) { if((address + size) <= MEMORY_SIZE) { for(uint index = 0; index < size; index++) { memory_ram[address + index] = 0; diff --git a/core/Memory.h b/core/Memory.h index 19a0e21..4b5d85e 100755 --- a/core/Memory.h +++ b/core/Memory.h @@ -5,7 +5,7 @@ // // ---------------------------------------------------------------------------- // Copyright 2005 Greg Stanton -// +// // 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 @@ -39,8 +39,8 @@ typedef unsigned int uint; extern void memory_Reset( ); extern byte memory_Read(word address); extern void memory_Write(word address, byte data); -extern void memory_WriteROM(word address, word size, const byte* data); -extern void memory_ClearROM(word address, word size); +extern void memory_WriteROM(word address, uint size, const byte* data); +extern void memory_ClearROM(word address, uint size); extern byte memory_ram[MEMORY_SIZE]; extern byte memory_rom[MEMORY_SIZE]; diff --git a/core/Pokey.cpp b/core/Pokey.cpp index aec0f42..1f0a437 100755 --- a/core/Pokey.cpp +++ b/core/Pokey.cpp @@ -5,7 +5,7 @@ // // ---------------------------------------------------------------------------- // Copyright 2005 Greg Stanton -// +// // 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 @@ -21,32 +21,33 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ---------------------------------------------------------------------------- // PokeySound is Copyright(c) 1997 by Ron Fries -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of version 2 of the GNU Library General Public License -// as published by the Free Software Foundation. -// -// This library 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 Library -// General Public License for more details. -// To obtain a copy of the GNU Library General Public License, write to the -// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// Any permitted reproduction of these routines, in whole or in part, must -// bear this legend. +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of version 2 of the GNU Library General Public License +// as published by the Free Software Foundation. +// +// This library 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 Library +// General Public License for more details. +// To obtain a copy of the GNU Library General Public License, write to the +// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// Any permitted reproduction of these routines, in whole or in part, must +// bear this legend. // ---------------------------------------------------------------------------- // Pokey.cpp // ---------------------------------------------------------------------------- + #include #include "Pokey.h" -#include "Prosystem.h" +#include "ProSystem.h" #define POKEY_NOTPOLY5 0x80 #define POKEY_POLY4 0x40 #define POKEY_PURE 0x20 #define POKEY_VOLUME_ONLY 0x10 #define POKEY_VOLUME_MASK 0x0f -#define POKEY_POLY9 0x80 +#define POKEY_POLY9 0x80 #define POKEY_CH1_179 0x40 #define POKEY_CH3_179 0x20 #define POKEY_CH1_CH2 0x10 @@ -66,10 +67,10 @@ #define POKEY_CHANNEL4 3 #define POKEY_SAMPLE 4 -#define SK_RESET 0x03 +#define SK_RESET 0x03 byte pokey_buffer[POKEY_BUFFER_SIZE] = {0}; -uint pokey_size = 524; +uint pokey_size = (POKEY_BUFFER_SIZE - 512); // 524 previously static uint pokey_frequency = 1787520; static uint pokey_sampleRate = 31440; @@ -100,6 +101,9 @@ static uint r17; static byte SKCTL; byte RANDOM; +byte POT_input[8] = {228, 228, 228, 228, 228, 228, 228, 228}; +static int pot_scanline; + static ulong random_scanline_counter; static ulong prev_random_scanline_counter; @@ -109,15 +113,15 @@ static void rand_init(byte *rng, int size, int left, int right, int add) int i, x = 0; for( i = 0; i < mask; i++ ) - { - if (size == 17) - *rng = x >> 6; /* use bits 6..13 */ - else - *rng = x; /* use bits 0..7 */ + { + if (size == 17) + *rng = x >> 6; /* use bits 6..13 */ + else + *rng = x; /* use bits 0..7 */ rng++; /* calculate next bit */ - x = ((x << left) + (x >> right) + add) & mask; - } + x = ((x << left) + (x >> right) + add) & mask; + } } void pokey_setSampleRate( uint rate ) { @@ -128,6 +132,9 @@ void pokey_setSampleRate( uint rate ) { // Reset // ---------------------------------------------------------------------------- void pokey_Reset( ) { + pot_scanline = 0; + pokey_soundCntr = 0; + for(int index = 0; index < POKEY_POLY17_SIZE; index++) { pokey_poly17[index] = rand( ) & 1; } @@ -152,6 +159,10 @@ void pokey_Reset( ) { pokey_audf[channel] = 0; } + for(int i = 0; i < 8; i++) { + POT_input[i] = 228; + } + pokey_audctl = 0; pokey_baseMultiplier = POKEY_DIV_64; @@ -166,7 +177,7 @@ void pokey_Reset( ) { r17 = 0; random_scanline_counter = 0; prev_random_scanline_counter = 0; -} +} /* Called prior to each frame */ void pokey_Frame() { @@ -174,15 +185,33 @@ void pokey_Frame() { /* Called prior to each scanline */ void pokey_Scanline() { - random_scanline_counter += CYCLES_PER_SCANLINE; + random_scanline_counter += CYCLES_PER_SCANLINE; + + if (pot_scanline < 228) + pot_scanline++; } byte pokey_GetRegister(word address) { byte data = 0; + byte addr = address & 0x0f; + if (addr < 8) { + byte b = POT_input[addr]; + if (b <= pot_scanline) + return b; + return pot_scanline; + } + switch (address) { + case POKEY_ALLPOT: { + byte b = 0; + for (int i = 0; i < 8; i++) + if (POT_input[addr] <= pot_scanline) + b &= ~(1 << i); /* reset bit if pot value known */ + return b; + } case POKEY_RANDOM: - ulong curr_scanline_counter = + ulong curr_scanline_counter = ( random_scanline_counter + prosystem_cycles + prosystem_extra_cycles ); if( SKCTL & SK_RESET ) @@ -209,21 +238,27 @@ byte pokey_GetRegister(word address) { RANDOM = RANDOM ^ 0xff; data = RANDOM; - break; } return data; -} +} // ---------------------------------------------------------------------------- // SetRegister // ---------------------------------------------------------------------------- void pokey_SetRegister(word address, byte value) { - byte channelMask; + byte channelMask; switch(address) { + case POKEY_POTGO: + if (!(SKCTL & 4)) + pot_scanline = 0; /* slow pot mode */ + return; + case POKEY_SKCTLS: SKCTL = value; + if (value & 4) + pot_scanline = 228; /* fast pot mode - return results immediately */ return; case POKEY_AUDF1: @@ -233,7 +268,7 @@ void pokey_SetRegister(word address, byte value) { channelMask |= 1 << POKEY_CHANNEL2; } break; - + case POKEY_AUDC1: pokey_audc[POKEY_CHANNEL1] = value; channelMask = 1 << POKEY_CHANNEL1; @@ -294,7 +329,7 @@ void pokey_SetRegister(word address, byte value) { channelMask = 0; break; } - + uint newValue = 0; if(channelMask & (1 << POKEY_CHANNEL1)) { @@ -342,7 +377,7 @@ void pokey_SetRegister(word address, byte value) { } if(newValue!= pokey_divideMax[POKEY_CHANNEL3]) { pokey_divideMax[POKEY_CHANNEL3] = newValue; - if(pokey_divideCount[POKEY_CHANNEL3] > newValue) { + if(pokey_divideCount[POKEY_CHANNEL3] > newValue) { pokey_divideCount[POKEY_CHANNEL3] = newValue; } } @@ -364,19 +399,25 @@ void pokey_SetRegister(word address, byte value) { pokey_divideMax[POKEY_CHANNEL4] = newValue; if(pokey_divideCount[POKEY_CHANNEL4] > newValue) { pokey_divideCount[POKEY_CHANNEL4] = newValue; - } + } } } for(byte channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) { if(channelMask & (1 << channel)) { - if((pokey_audc[channel] & POKEY_VOLUME_ONLY) || ((pokey_audc[channel] & POKEY_VOLUME_MASK) == 0) || (pokey_divideMax[channel] < (pokey_sampleMax >> 8))) { + if((pokey_audc[channel] & POKEY_VOLUME_ONLY) || + ((pokey_audc[channel] & POKEY_VOLUME_MASK) == 0) || + (pokey_divideMax[channel] < (pokey_sampleMax >> 8))) { +#if 1 // WII + pokey_outVol[channel] = 1; +#else pokey_outVol[channel] = pokey_audc[channel] & POKEY_VOLUME_MASK; +#endif pokey_divideCount[channel] = 0x7fffffff; pokey_divideMax[channel] = 0x7fffffff; } } - } + } } // ---------------------------------------------------------------------------- @@ -384,13 +425,18 @@ void pokey_SetRegister(word address, byte value) { // ---------------------------------------------------------------------------- void pokey_Process(uint length) { byte* buffer = pokey_buffer + pokey_soundCntr; - uint* sampleCntrPtr = (uint*)((byte*)(&pokey_sampleCount[0]) + 1); +//#ifdef BIG_ENDIAN +// uint* sampleCntrPtrB = (uint*)((byte*)&pokey_sampleCount[0] + 3); +//#else + uint* sampleCntrPtrB = (uint*)((byte*)&pokey_sampleCount[0] + 1); +//#endif uint size = length; while(length) { + byte currentValue; byte nextEvent = POKEY_SAMPLE; - uint eventMin = *sampleCntrPtr; + uint eventMin = *sampleCntrPtrB; byte channel; for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) { @@ -399,12 +445,12 @@ void pokey_Process(uint length) { nextEvent = channel; } } - + for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) { pokey_divideCount[channel] -= eventMin; } - *sampleCntrPtr -= eventMin; + *sampleCntrPtrB -= eventMin; pokey_polyAdjust += eventMin; if(nextEvent != POKEY_SAMPLE) { @@ -434,7 +480,11 @@ void pokey_Process(uint length) { } } else { +//#ifdef BIG_ENDIAN +// *(pokey_sampleCount + 1) += pokey_sampleMax; +//#else *pokey_sampleCount += pokey_sampleMax; +//#endif currentValue = 0; for(channel = POKEY_CHANNEL1; channel <= POKEY_CHANNEL4; channel++) { @@ -445,8 +495,8 @@ void pokey_Process(uint length) { *buffer++ = currentValue; length--; } - } - + } + pokey_soundCntr += size; if(pokey_soundCntr >= pokey_size) { pokey_soundCntr = 0; @@ -457,7 +507,6 @@ void pokey_Process(uint length) { // Clear // ---------------------------------------------------------------------------- void pokey_Clear( ) { - for(int index = 0; index < POKEY_BUFFER_SIZE; index++) { - pokey_buffer[index] = 0; - } -} \ No newline at end of file + pokey_soundCntr = 0; + memset(pokey_buffer, 0, POKEY_BUFFER_SIZE); +} diff --git a/core/ProSystem.cpp b/core/ProSystem.cpp index fc1c462..153924a 100755 --- a/core/ProSystem.cpp +++ b/core/ProSystem.cpp @@ -52,6 +52,7 @@ void prosystem_Reset( ) { tia_Reset( ); pokey_Clear( ); pokey_Reset( ); + xm_Reset( ); memory_Reset( ); maria_Clear( ); maria_Reset( ); @@ -102,7 +103,7 @@ void prosystem_ExecuteFrame(const byte* input) { prosystem_extra_cycles = 0; - if(cartridge_pokey) pokey_Frame(); + if(cartridge_pokey || cartridge_xm) pokey_Frame(); for(maria_scanline = 1; maria_scanline <= prosystem_scanlines; maria_scanline++) { if(maria_scanline == maria_displayArea.top) { @@ -196,11 +197,11 @@ void prosystem_ExecuteFrame(const byte* input) { if(lightgun) prosystem_FireLightGun(); tia_Process(2); - if(cartridge_pokey) { + if(cartridge_pokey || cartridge_xm) { pokey_Process(2); } - if(cartridge_pokey) pokey_Scanline(); + if(cartridge_pokey || cartridge_xm) pokey_Scanline(); } prosystem_frame++; @@ -220,7 +221,7 @@ bool prosystem_Save(std::string filename, bool compress) { logger_LogInfo("Saving game state to file " + filename + ".", PRO_SYSTEM_SOURCE); - byte loc_buffer[33000] = {0}; + byte loc_buffer[33000 + XM_RAM_SIZE + 4] = {0}; uint size = 0; @@ -272,9 +273,19 @@ bool prosystem_Save(std::string filename, bool compress) { loc_buffer[size++] = ( 0xff & ( riot_clocks >> 8 ) ); loc_buffer[size++] = ( 0xff & riot_clocks ); -#if 0 - if(!compress) { -#endif + // XM (if applicable) + if (cartridge_xm) { + loc_buffer[size++] = xm_reg; + loc_buffer[size++] = xm_bank; + loc_buffer[size++] = xm_pokey_enabled; + loc_buffer[size++] = xm_mem_enabled; + + for (index = 0; index < XM_RAM_SIZE; index++) { + loc_buffer[size + index] = xm_ram[index]; + } + size += XM_RAM_SIZE; + } + FILE* file = fopen(filename.c_str( ), "wb"); if(file == NULL) { logger_LogError("Failed to open the file " + filename + " for writing.", PRO_SYSTEM_SOURCE); @@ -289,15 +300,6 @@ bool prosystem_Save(std::string filename, bool compress) { fflush(file); fclose(file); -#if 0 - } - else { - if(!archive_Compress(filename.c_str( ), "Save.sav", loc_buffer, size)) { - logger_LogError("Failed to compress the save state data to the file " + filename + ".", PRO_SYSTEM_SOURCE); - return false; - } - } -#endif return true; } @@ -354,6 +356,19 @@ bool prosystem_Save_buffer(byte *buffer) buffer[size++] = ( 0xff & ( riot_clocks >> 8 ) ); buffer[size++] = ( 0xff & riot_clocks ); + // XM (if applicable) + if (cartridge_xm) { + buffer[size++] = xm_reg; + buffer[size++] = xm_bank; + buffer[size++] = xm_pokey_enabled; + buffer[size++] = xm_mem_enabled; + + for (index = 0; index < XM_RAM_SIZE; index++) { + buffer[size + index] = xm_ram[index]; + } + size += XM_RAM_SIZE; + } + return true; } @@ -368,7 +383,7 @@ bool prosystem_Load(const std::string filename) { logger_LogInfo("Loading game state from file " + filename + ".", PRO_SYSTEM_SOURCE); - byte loc_buffer[33000] = {0}; + byte loc_buffer[33000 + XM_RAM_SIZE + 4] = {0}; uint size = archive_GetUncompressedFileSize(filename); if(size == 0) { @@ -391,10 +406,11 @@ bool prosystem_Load(const std::string filename) { return false; } - if( size != 16445 && - size != 32829 && - size != 16453 && - size != 32837 ) { + if( size != 16445 && size != 32829 && /* no RIOT */ + size != 16453 && size != 32837 && /* with RIOT */ + size != (16453 + 4 + XM_RAM_SIZE) && /* XM without supercart ram */ + size != (32837 + 4 + XM_RAM_SIZE)) /* XM with supercart ram */ + { fclose(file); logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE); return false; @@ -406,9 +422,6 @@ bool prosystem_Load(const std::string filename) { return false; } fclose(file); - } - else if(size == 16445 || size == 32829) { - archive_Uncompress(filename, loc_buffer, size); } else { logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE); @@ -459,7 +472,9 @@ bool prosystem_Load(const std::string filename) { offset += 16384; if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) { - if(size != 32829 && size != 32837) { + if (size != 32829 && /* no RIOT */ + size != 32837 && /* with RIOT */ + size != (32837 + 4 + XM_RAM_SIZE)) /* XM */ { logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE); return false; } @@ -469,8 +484,10 @@ bool prosystem_Load(const std::string filename) { offset += 16384; } - if( size == 16453 || size == 32837 ) - { + if (size == 16453 || /* no supercart ram */ + size == 32837 || /* supercart ram */ + size == (16453 + 4 + XM_RAM_SIZE) || /* xm, no supercart ram */ + size == (32837 + 4 + XM_RAM_SIZE)) /* xm, supercart ram */ { // RIOT state riot_dra = loc_buffer[offset++]; riot_drb = loc_buffer[offset++]; @@ -480,7 +497,23 @@ bool prosystem_Load(const std::string filename) { riot_intervals = loc_buffer[offset++]; riot_clocks = ( loc_buffer[offset++] << 8 ); riot_clocks |= loc_buffer[offset++]; + } + // XM (if applicable) + if (cartridge_xm) { + if ((size != (16453 + 4 + XM_RAM_SIZE)) && + (size != (32837 + 4 + XM_RAM_SIZE))) { + logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE); + return false; + } + xm_reg = loc_buffer[offset++]; + xm_bank = loc_buffer[offset++]; + xm_pokey_enabled = loc_buffer[offset++]; + xm_mem_enabled = loc_buffer[offset++]; + + for (index = 0; index < XM_RAM_SIZE; index++) { + xm_ram[index] = loc_buffer[offset++]; + } } return true; @@ -489,6 +522,9 @@ bool prosystem_Load(const std::string filename) { bool prosystem_Load_buffer(const byte *buffer) { uint size = cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM ? 32837 : 16453; + if(cartridge_xm) { + size += 4 + XM_RAM_SIZE; + } uint offset = 0; uint index; @@ -533,25 +569,49 @@ bool prosystem_Load_buffer(const byte *buffer) offset += 16384; if(cartridge_type == CARTRIDGE_TYPE_SUPERCART_RAM) { - if(size != 32829 && size != 32837) { + if (size != 32829 && /* no RIOT */ + size != 32837 && /* with RIOT */ + size != (32837 + 4 + XM_RAM_SIZE)) /* XM */ { + logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE); + return false; + } + for(index = 0; index < 16384; index++) { + memory_ram[16384 + index] = buffer[offset + index]; + } + offset += 16384; + } + + if (size == 16453 || /* no supercart ram */ + size == 32837 || /* supercart ram */ + size == (16453 + 4 + XM_RAM_SIZE) || /* xm, no supercart ram */ + size == (32837 + 4 + XM_RAM_SIZE)) /* xm, supercart ram */ { + // RIOT state + riot_dra = buffer[offset++]; + riot_drb = buffer[offset++]; + riot_timing = buffer[offset++]; + riot_timer = ( buffer[offset++] << 8 ); + riot_timer |= buffer[offset++]; + riot_intervals = buffer[offset++]; + riot_clocks = ( buffer[offset++] << 8 ); + riot_clocks |= buffer[offset++]; + } + + // XM (if applicable) + if (cartridge_xm) { + if ((size != (16453 + 4 + XM_RAM_SIZE)) && + (size != (32837 + 4 + XM_RAM_SIZE))) { logger_LogError("Save state file has an invalid size.", PRO_SYSTEM_SOURCE); return false; } - for(index = 0; index < 16384; index++) { - memory_ram[16384 + index] = buffer[offset + index]; - } - offset += 16384; - } + xm_reg = buffer[offset++]; + xm_bank = buffer[offset++]; + xm_pokey_enabled = buffer[offset++]; + xm_mem_enabled = buffer[offset++]; - // RIOT state - riot_dra = buffer[offset++]; - riot_drb = buffer[offset++]; - riot_timing = buffer[offset++]; - riot_timer = ( buffer[offset++] << 8 ); - riot_timer |= buffer[offset++]; - riot_intervals = buffer[offset++]; - riot_clocks = ( buffer[offset++] << 8 ); - riot_clocks |= buffer[offset++]; + for (index = 0; index < XM_RAM_SIZE; index++) { + xm_ram[index] = buffer[offset++]; + } + } return true; } diff --git a/core/ProSystem.h b/core/ProSystem.h index c08a244..b652623 100755 --- a/core/ProSystem.h +++ b/core/ProSystem.h @@ -38,6 +38,7 @@ #include "Archive.h" #include "Tia.h" #include "Pokey.h" +#include "ExpansionModule.h" typedef unsigned char byte; typedef unsigned short word; @@ -75,4 +76,4 @@ extern float lightgun_cycle; // Whether the lightgun is enabled for the current cartridge //extern bool lightgun_enabled; -#endif \ No newline at end of file +#endif diff --git a/core/Sound.cpp b/core/Sound.cpp index 8a195c9..9b67f7b 100755 --- a/core/Sound.cpp +++ b/core/Sound.cpp @@ -1,11 +1,12 @@ // ---------------------------------------------------------------------------- -// ___ ___ ___ ___ ___ ____ ___ _ _ -// /__/ /__/ / / /__ /__/ /__ / /_ / |/ / -// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator +// ___ ___ ___ ___ ___ ____ ___ _ _ __ ___ +// /__/ /__/ / / /__ /__/ /__ / /_ / |/ / / / _ +// / / \ /__/ ___/ ___/ ___/ / /__ / / ___/ /__/ // // ---------------------------------------------------------------------------- // Copyright 2005 Greg Stanton -// +// Copyright 2020 Rupert Carmichael +// // 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 @@ -20,101 +21,67 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ---------------------------------------------------------------------------- -// Sound.cpp +// Sound.c // ---------------------------------------------------------------------------- +#include +#include +#include + #include "Sound.h" #define MAX_BUFFER_SIZE 8192 -typedef struct -{ - uint nSamplesPerSec; - word nChannels; - word wBitsPerSample; -} SOUNDCONFIG; +static uint32_t nSamplesPerSec = 48000; -static const SOUNDCONFIG soundDefaults = {48000, 1, 8}; -static SOUNDCONFIG sound_format = soundDefaults; - -// ---------------------------------------------------------------------------- -// GetSampleLength -// ---------------------------------------------------------------------------- -static uint sound_GetSampleLength(uint length, uint unit, uint unitMax) -{ - uint sampleLength = length / unitMax; - uint sampleRemain = length % unitMax; - - if(sampleRemain != 0 && sampleRemain >= unit) - { - sampleLength++; - } - - return sampleLength; -} - -// ---------------------------------------------------------------------------- -// Resample -// ---------------------------------------------------------------------------- -static void sound_Resample(const byte *source, byte *target, int length) -{ - int measurement = sound_format.nSamplesPerSec; +static void sound_Resample(const uint8_t *source, uint8_t *target, int length) { + int measurement = nSamplesPerSec; int sourceIndex = 0; int targetIndex = 0; int max = ((prosystem_frequency * prosystem_scanlines) << 1); - while(targetIndex < length) - { - if(measurement >= max) - { + while (targetIndex < length) { + if (measurement >= max) { target[targetIndex++] = source[sourceIndex]; measurement -= max; } - else - { + else { sourceIndex++; - measurement += sound_format.nSamplesPerSec; + measurement += nSamplesPerSec; } } } -// ---------------------------------------------------------------------------- -// Store -// ---------------------------------------------------------------------------- -uint sound_Store(byte *out_buffer) -{ +uint32_t sound_Store(uint8_t *out_buffer) { memset(out_buffer, 0, MAX_BUFFER_SIZE); - uint length = 48000 / prosystem_frequency; // sound_GetSampleLength(sound_format.nSamplesPerSec, prosystem_frame, prosystem_frequency); + uint32_t length = nSamplesPerSec / prosystem_frequency; sound_Resample(tia_buffer, out_buffer, length); + tia_Clear(); // Ballblazer, Commando, various homebrew and hacks - if(cartridge_pokey) - { - byte pokeySample[MAX_BUFFER_SIZE]; + if(cartridge_pokey || xm_pokey_enabled) { + uint8_t pokeySample[MAX_BUFFER_SIZE]; memset(pokeySample, 0, MAX_BUFFER_SIZE); sound_Resample(pokey_buffer, pokeySample, length); - for(uint index = 0; index < length; index++) - { - out_buffer[index] += pokeySample[index]; - out_buffer[index] = out_buffer[index] / 2; + for(uint32_t index = 0; index < length; index++) { + uint32_t sound = out_buffer[index] + pokeySample[index]; + out_buffer[index] = sound >> 1; } } + else { + for(uint32_t index = 0; index < length; index++) { + out_buffer[index] = out_buffer[index] * 0.75; //>> 1; + } + } + pokey_Clear(); return length; } -// ---------------------------------------------------------------------------- -// SetSampleRate -// ---------------------------------------------------------------------------- -void sound_SetSampleRate(uint rate) -{ - sound_format.nSamplesPerSec = rate; +void sound_SetSampleRate(uint32_t rate) { + nSamplesPerSec = rate; } -// ---------------------------------------------------------------------------- -// GetSampleRate -// ---------------------------------------------------------------------------- -uint sound_GetSampleRate() -{ - return sound_format.nSamplesPerSec; +uint32_t sound_GetSampleRate(void) { + return nSamplesPerSec; } diff --git a/core/Tia.cpp b/core/Tia.cpp index 6ca4596..566f95c 100755 --- a/core/Tia.cpp +++ b/core/Tia.cpp @@ -5,7 +5,7 @@ // // ---------------------------------------------------------------------------- // Copyright 2005 Greg Stanton -// +// // 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 @@ -21,30 +21,31 @@ // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // ---------------------------------------------------------------------------- // TiaSound is Copyright(c) 1997 by Ron Fries -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of version 2 of the GNU Library General Public License -// as published by the Free Software Foundation. -// -// This library 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 Library -// General Public License for more details. -// To obtain a copy of the GNU Library General Public License, write to the -// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of version 2 of the GNU Library General Public License +// as published by the Free Software Foundation. +// +// This library 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 Library +// General Public License for more details. +// To obtain a copy of the GNU Library General Public License, write to the +// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// // Any permitted reproduction of these routines, in whole or in part, must -// bear this legend. +// bear this legend. // ---------------------------------------------------------------------------- // Tia.cpp // ---------------------------------------------------------------------------- #include "Tia.h" +#include #define TIA_POLY4_SIZE 15 #define TIA_POLY5_SIZE 31 #define TIA_POLY9_SIZE 511 byte tia_buffer[TIA_BUFFER_SIZE] = {0}; -uint tia_size = 524; +uint tia_size = TIA_BUFFER_SIZE; // previously was 524 static const byte TIA_POLY4[ ] = {1,1,0,1,1,1,0,0,0,0,1,0,1,0,0}; static const byte TIA_POLY5[ ] = {0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1}; @@ -119,9 +120,8 @@ void tia_Reset( ) { // Clear // ---------------------------------------------------------------------------- void tia_Clear( ) { - for(int index = 0; index < TIA_BUFFER_SIZE; index++) { - tia_buffer[index] = 0; - } + tia_soundCntr = 0; + memset(tia_buffer, 0, TIA_BUFFER_SIZE); } // ---------------------------------------------------------------------------- @@ -130,7 +130,7 @@ void tia_Clear( ) { void tia_SetRegister(word address, byte data) { byte channel; byte frequency; - + switch(address) { case AUDC0: tia_audc[0] = data & 15; @@ -203,4 +203,4 @@ void tia_Process(uint length) { tia_soundCntr = 0; } } -} \ No newline at end of file +}