From 95f92626179893f12434f7854bb5feab1de849df Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 08:10:50 +0800 Subject: [PATCH 01/16] Rewritten mapper code and expansion audio, add nsfe support and others - Mapper code rewrite, fixes and updates, additions - Expansion Audio updates - update VRC7 sound code (emu2413) - replace Sunsoft 5B sound code with emu2149 for better accuracy (including envelop and noise emulation) - Update FDS sound expansion (fds audio code from Mednafen with modification for fceumm' use) - Update NSF support - Add NSFE support - others (maybe) --- Makefile.common | 9 +- fceumm_libretro.info | 45 + src/cart.h | 4 + src/drivers/libretro/libretro.c | 2 +- src/fceu-types.h | 8 + src/fceu.c | 6 + src/fceu.h | 11 + src/ines.c | 491 ++++++ src/ines.h | 325 ++-- src/input.c | 4 +- src/mappers/hw/bandai.c | 231 +++ src/mappers/hw/bandai.h | 39 + src/mappers/hw/eeprom_93Cx6.c | 173 ++ src/mappers/hw/eeprom_93Cx6.h | 28 + src/mappers/hw/eeprom_x24c0x.c | 251 +++ src/mappers/hw/eeprom_x24c0x.h | 40 + src/mappers/hw/flashrom.c | 135 ++ src/mappers/hw/flashrom.h | 30 + src/mappers/hw/fme7.c | 236 +++ src/mappers/hw/fme7.h | 47 + src/mappers/hw/jv001.c | 134 ++ src/mappers/hw/jv001.h | 46 + src/mappers/hw/jyasic.c | 520 ++++++ src/mappers/hw/jyasic.h | 75 + src/mappers/hw/ks202.c | 137 ++ src/mappers/hw/ks202.h | 40 + src/mappers/hw/latch.c | 92 + src/mappers/hw/latch.h | 39 + src/mappers/hw/mmc1.c | 280 ++++ src/mappers/hw/mmc1.h | 59 + src/mappers/hw/mmc2.c | 150 ++ src/mappers/hw/mmc2.h | 48 + src/mappers/hw/mmc3.c | 337 ++++ src/mappers/hw/mmc3.h | 56 + src/mappers/hw/mmc4.c | 148 ++ src/mappers/hw/mmc4.h | 48 + src/mappers/hw/mmc6.c | 285 ++++ src/mappers/hw/mmc6.h | 26 + src/mappers/hw/n118.c | 127 ++ src/mappers/hw/n118.h | 44 + src/mappers/hw/pic16c5x.c | 1001 +++++++++++ src/mappers/hw/pic16c5x.h | 57 + src/mappers/hw/pic16c5x_ops_00x.inc | 16 + src/mappers/hw/pic16c5x_ops_main.inc | 287 ++++ src/mappers/hw/txc.c | 138 ++ src/mappers/hw/txc.h | 46 + src/mappers/hw/vrc24.c | 277 ++++ src/mappers/hw/vrc24.h | 74 + src/mappers/hw/vrc6.c | 203 +++ src/mappers/hw/vrc6.h | 49 + src/mappers/hw/vrc7.c | 185 +++ src/mappers/hw/vrc7.h | 46 + src/mappers/hw/vrcirq.c | 117 ++ src/mappers/hw/vrcirq.h | 33 + src/mappers/mapinc.h | 46 + src/mappers/mapper.c | 10 + src/mappers/mapper000.c | 73 + src/mappers/mapper001.c | 67 + src/mappers/mapper002.c | 34 + src/mappers/mapper003.c | 33 + src/mappers/mapper004.c | 70 + src/mappers/mapper005.c | 807 +++++++++ src/mappers/mapper006.c | 486 ++++++ src/mappers/mapper006.h | 262 +++ src/mappers/mapper007.c | 33 + src/mappers/mapper009.c | 38 + src/mappers/mapper010.c | 38 + src/mappers/mapper011.c | 32 + src/mappers/mapper012.c | 74 + src/mappers/mapper013.c | 33 + src/mappers/mapper014.c | 107 ++ src/mappers/mapper015.c | 56 + src/mappers/mapper016.c | 51 + src/mappers/mapper018.c | 163 ++ src/mappers/mapper019.c | 252 +++ src/mappers/mapper021.c | 31 + src/mappers/mapper022.c | 32 + src/mappers/mapper023.c | 32 + src/mappers/mapper024.c | 44 + src/mappers/mapper025.c | 37 + src/mappers/mapper026.c | 38 + src/mappers/mapper027.c | 34 + src/mappers/mapper028.c | 107 ++ src/mappers/mapper029.c | 37 + src/mappers/mapper030.c | 144 ++ src/mappers/mapper031.c | 74 + src/mappers/mapper032.c | 132 ++ src/mappers/mapper033.c | 86 + src/mappers/mapper034.c | 149 ++ src/mappers/mapper036.c | 55 + src/mappers/mapper037.c | 66 + src/mappers/mapper038.c | 55 + src/mappers/mapper040.c | 113 ++ src/mappers/mapper041.c | 72 + src/mappers/mapper042.c | 201 +++ src/mappers/mapper043.c | 97 ++ src/mappers/mapper044.c | 63 + src/mappers/mapper045.c | 108 ++ src/mappers/mapper046.c | 58 + src/mappers/mapper047.c | 65 + src/mappers/mapper048.c | 120 ++ src/mappers/mapper049.c | 72 + src/mappers/mapper050.c | 90 + src/mappers/mapper051.c | 95 ++ src/mappers/mapper052.c | 110 ++ src/mappers/mapper053.c | 79 + src/mappers/mapper055.c | 52 + src/mappers/mapper056.c | 94 ++ src/mappers/mapper057.c | 90 + src/mappers/mapper058.c | 39 + src/mappers/mapper059.c | 73 + src/mappers/mapper060.c | 52 + src/mappers/mapper061.c | 39 + src/mappers/mapper062.c | 41 + src/mappers/mapper063.c | 55 + src/mappers/mapper064.c | 183 ++ src/mappers/mapper065.c | 153 ++ src/mappers/mapper066.c | 32 + src/mappers/mapper067.c | 126 ++ src/mappers/mapper068.c | 150 ++ src/mappers/mapper069.c | 37 + src/mappers/mapper070.c | 33 + src/mappers/mapper071.c | 74 + src/mappers/mapper072.c | 80 + src/mappers/mapper073.c | 131 ++ src/mappers/mapper074.c | 45 + src/mappers/mapper075.c | 91 + src/mappers/mapper076.c | 48 + src/mappers/mapper077.c | 44 + src/mappers/mapper078.c | 43 + src/mappers/mapper079.c | 59 + src/mappers/mapper080.c | 125 ++ src/mappers/mapper081.c | 32 + src/mappers/mapper082.c | 145 ++ src/mappers/mapper083.c | 268 +++ src/mappers/mapper085.c | 42 + src/mappers/mapper086.c | 57 + src/mappers/mapper087.c | 55 + src/mappers/mapper088.c | 36 + src/mappers/mapper089.c | 34 + src/mappers/mapper091.c | 162 ++ src/mappers/mapper093.c | 33 + src/mappers/mapper094.c | 33 + src/mappers/mapper095.c | 121 ++ src/mappers/mapper096.c | 71 + src/mappers/mapper097.c | 34 + src/mappers/mapper099.c | 73 + src/mappers/mapper100.c | 167 ++ src/mappers/mapper101.c | 55 + src/mappers/mapper103.c | 110 ++ src/mappers/mapper104.c | 81 + src/mappers/mapper105.c | 74 + src/mappers/mapper106.c | 124 ++ src/mappers/mapper107.c | 32 + src/mappers/mapper108.c | 98 ++ src/mappers/mapper111.c | 178 ++ src/mappers/mapper112.c | 111 ++ src/mappers/mapper113.c | 58 + src/mappers/mapper114.c | 117 ++ src/mappers/mapper115.c | 67 + src/mappers/mapper116.c | 208 +++ src/mappers/mapper117.c | 123 ++ src/mappers/mapper118.c | 75 + src/mappers/mapper119.c | 44 + src/mappers/mapper120.c | 62 + src/mappers/mapper121.c | 129 ++ src/mappers/mapper123.c | 73 + src/mappers/mapper124.c | 234 +++ src/mappers/mapper125.c | 76 + src/mappers/mapper126.c | 201 +++ src/mappers/mapper127.c | 116 ++ src/mappers/mapper128.c | 61 + src/mappers/mapper132.c | 98 ++ src/mappers/mapper133.c | 59 + src/mappers/mapper134.c | 112 ++ src/mappers/mapper136.c | 48 + src/mappers/mapper137.c | 77 + src/mappers/mapper138.c | 76 + src/mappers/mapper139.c | 76 + src/mappers/mapper140.c | 55 + src/mappers/mapper141.c | 80 + src/mappers/mapper142.c | 37 + src/mappers/mapper143.c | 41 + src/mappers/mapper144.c | 44 + src/mappers/mapper145.c | 54 + src/mappers/mapper147.c | 49 + src/mappers/mapper148.c | 33 + src/mappers/mapper149.c | 33 + src/mappers/mapper150.c | 102 ++ src/mappers/mapper152.c | 34 + src/mappers/mapper153.c | 91 + src/mappers/mapper154.c | 73 + src/mappers/mapper155.c | 33 + src/mappers/mapper156.c | 128 ++ src/mappers/mapper157.c | 290 ++++ src/mappers/mapper159.c | 37 + src/mappers/mapper160.c | 59 + src/mappers/mapper162.c | 108 ++ src/mappers/mapper163.c | 114 ++ src/mappers/mapper164.c | 146 ++ src/mappers/mapper165.c | 87 + src/mappers/mapper166.c | 88 + src/mappers/mapper167.c | 88 + src/mappers/mapper168.c | 75 + src/mappers/mapper170.c | 52 + src/mappers/mapper171.c | 58 + src/mappers/mapper172.c | 54 + src/mappers/mapper173.c | 52 + src/mappers/mapper174.c | 37 + src/mappers/mapper175.c | 78 + src/mappers/mapper176.c | 599 +++++++ src/mappers/mapper177.c | 37 + src/mappers/mapper178.c | 107 ++ src/mappers/mapper180.c | 33 + src/mappers/mapper183.c | 87 + src/mappers/mapper184.c | 56 + src/mappers/mapper185.c | 63 + src/mappers/mapper186.c | 95 ++ src/mappers/mapper187.c | 78 + src/mappers/mapper188.c | 47 + src/mappers/mapper189.c | 57 + src/mappers/mapper190.c | 86 + src/mappers/mapper191.c | 45 + src/mappers/mapper192.c | 46 + src/mappers/mapper193.c | 68 + src/mappers/mapper194.c | 45 + src/mappers/mapper195.c | 103 ++ src/mappers/mapper196.c | 68 + src/mappers/mapper197.c | 121 ++ src/mappers/mapper198.c | 42 + src/mappers/mapper199.c | 40 + src/mappers/mapper200.c | 38 + src/mappers/mapper201.c | 33 + src/mappers/mapper202.c | 38 + src/mappers/mapper203.c | 33 + src/mappers/mapper204.c | 39 + src/mappers/mapper205.c | 78 + src/mappers/mapper206.c | 37 + src/mappers/mapper208.c | 132 ++ src/mappers/mapper209.c | 62 + src/mappers/mapper210.c | 146 ++ src/mappers/mapper212.c | 48 + src/mappers/mapper214.c | 33 + src/mappers/mapper215.c | 184 ++ src/mappers/mapper216.c | 32 + src/mappers/mapper217.c | 33 + src/mappers/mapper218.c | 57 + src/mappers/mapper219.c | 113 ++ src/mappers/mapper221.c | 92 + src/mappers/mapper222.c | 76 + src/mappers/mapper225.c | 86 + src/mappers/mapper226.c | 85 + src/mappers/mapper227.c | 69 + src/mappers/mapper228.c | 72 + src/mappers/mapper229.c | 38 + src/mappers/mapper230.c | 68 + src/mappers/mapper231.c | 43 + src/mappers/mapper232.c | 62 + src/mappers/mapper233.c | 72 + src/mappers/mapper234.c | 95 ++ src/mappers/mapper235.c | 78 + src/mappers/mapper236.c | 102 ++ src/mappers/mapper237.c | 88 + src/mappers/mapper238.c | 54 + src/mappers/mapper240.c | 71 + src/mappers/mapper241.c | 37 + src/mappers/mapper242.c | 79 + src/mappers/mapper244.c | 77 + src/mappers/mapper245.c | 61 + src/mappers/mapper246.c | 99 ++ src/mappers/mapper249.c | 89 + src/mappers/mapper250.c | 36 + src/mappers/mapper252.c | 93 ++ src/mappers/mapper254.c | 58 + src/mappers/mapper256.c | 418 +++++ src/mappers/mapper257.c | 123 ++ src/mappers/mapper259.c | 70 + src/mappers/mapper260.c | 119 ++ src/mappers/mapper261.c | 40 + src/mappers/mapper262.c | 89 + src/mappers/mapper263.c | 47 + src/mappers/mapper265.c | 65 + src/mappers/mapper266.c | 67 + src/mappers/mapper267.c | 69 + src/mappers/mapper268.c | 210 +++ src/mappers/mapper269.c | 95 ++ src/mappers/mapper271.c | 33 + src/mappers/mapper272.c | 162 ++ src/mappers/mapper274.c | 84 + src/mappers/mapper277.c | 67 + src/mappers/mapper281.c | 37 + src/mappers/mapper282.c | 41 + src/mappers/mapper283.c | 32 + src/mappers/mapper284.c | 228 +++ src/mappers/mapper285.c | 58 + src/mappers/mapper286.c | 98 ++ src/mappers/mapper287.c | 98 ++ src/mappers/mapper288.c | 55 + src/mappers/mapper289.c | 81 + src/mappers/mapper290.c | 44 + src/mappers/mapper291.c | 68 + src/mappers/mapper292.c | 80 + src/mappers/mapper293.c | 87 + src/mappers/mapper294.c | 63 + src/mappers/mapper295.c | 44 + src/mappers/mapper297.c | 94 ++ src/mappers/mapper298.c | 30 + src/mappers/mapper299.c | 37 + src/mappers/mapper300.c | 36 + src/mappers/mapper301.c | 68 + src/mappers/mapper302.c | 54 + src/mappers/mapper303.c | 144 ++ src/mappers/mapper304.c | 99 ++ src/mappers/mapper305.c | 86 + src/mappers/mapper306.c | 75 + src/mappers/mapper307.c | 55 + src/mappers/mapper308.c | 76 + src/mappers/mapper309.c | 83 + src/mappers/mapper310.c | 93 ++ src/mappers/mapper312.c | 60 + src/mappers/mapper313.c | 78 + src/mappers/mapper314.c | 81 + src/mappers/mapper315.c | 81 + src/mappers/mapper319.c | 92 + src/mappers/mapper320.c | 58 + src/mappers/mapper322.c | 97 ++ src/mappers/mapper323.c | 74 + src/mappers/mapper324.c | 54 + src/mappers/mapper325.c | 51 + src/mappers/mapper326.c | 89 + src/mappers/mapper327.c | 108 ++ src/mappers/mapper328.c | 51 + src/mappers/mapper329.c | 37 + src/mappers/mapper330.c | 135 ++ src/mappers/mapper331.c | 84 + src/mappers/mapper332.c | 89 + src/mappers/mapper333.c | 72 + src/mappers/mapper334.c | 73 + src/mappers/mapper335.c | 77 + src/mappers/mapper336.c | 50 + src/mappers/mapper337.c | 79 + src/mappers/mapper338.c | 39 + src/mappers/mapper339.c | 77 + src/mappers/mapper340.c | 50 + src/mappers/mapper341.c | 39 + src/mappers/mapper342.c | 2304 ++++++++++++++++++++++++++ src/mappers/mapper343.c | 54 + src/mappers/mapper344.c | 78 + src/mappers/mapper345.c | 76 + src/mappers/mapper346.c | 84 + src/mappers/mapper347.c | 193 +++ src/mappers/mapper348.c | 77 + src/mappers/mapper349.c | 45 + src/mappers/mapper350.c | 88 + src/mappers/mapper351.c | 274 +++ src/mappers/mapper352.c | 62 + src/mappers/mapper353.c | 163 ++ src/mappers/mapper354.c | 87 + src/mappers/mapper355.c | 135 ++ src/mappers/mapper355.h | 140 ++ src/mappers/mapper356.c | 107 ++ src/mappers/mapper357.c | 125 ++ src/mappers/mapper358.c | 41 + src/mappers/mapper359.c | 226 +++ src/mappers/mapper360.c | 67 + src/mappers/mapper361.c | 70 + src/mappers/mapper362.c | 92 + src/mappers/mapper364.c | 62 + src/mappers/mapper366.c | 67 + src/mappers/mapper368.c | 123 ++ src/mappers/mapper369.c | 165 ++ src/mappers/mapper370.c | 136 ++ src/mappers/mapper372.c | 95 ++ src/mappers/mapper374.c | 55 + src/mappers/mapper375.c | 65 + src/mappers/mapper376.c | 71 + src/mappers/mapper377.c | 74 + src/mappers/mapper380.c | 64 + src/mappers/mapper381.c | 44 + src/mappers/mapper382.c | 65 + src/mappers/mapper383.c | 121 ++ src/mappers/mapper385.c | 34 + src/mappers/mapper386.c | 41 + src/mappers/mapper387.c | 41 + src/mappers/mapper388.c | 41 + src/mappers/mapper389.c | 84 + src/mappers/mapper390.c | 90 + src/mappers/mapper391.c | 90 + src/mappers/mapper393.c | 106 ++ src/mappers/mapper394.c | 140 ++ src/mappers/mapper395.c | 78 + src/mappers/mapper396.c | 56 + src/mappers/mapper397.c | 44 + src/mappers/mapper398.c | 92 + src/mappers/mapper399.c | 86 + src/mappers/mapper400.c | 70 + src/mappers/mapper401.c | 97 ++ src/mappers/mapper402.c | 47 + src/mappers/mapper403.c | 86 + src/mappers/mapper404.c | 65 + src/mappers/mapper406.c | 87 + src/mappers/mapper409.c | 33 + src/mappers/mapper410.c | 96 ++ src/mappers/mapper411.c | 89 + src/mappers/mapper412.c | 93 ++ src/mappers/mapper413.c | 147 ++ src/mappers/mapper414.c | 60 + src/mappers/mapper415.c | 40 + src/mappers/mapper416.c | 110 ++ src/mappers/mapper417.c | 115 ++ src/mappers/mapper418.c | 39 + src/mappers/mapper420.c | 70 + src/mappers/mapper421.c | 41 + src/mappers/mapper428.c | 84 + src/mappers/mapper429.c | 40 + src/mappers/mapper430.c | 77 + src/mappers/mapper431.c | 64 + src/mappers/mapper432.c | 98 ++ src/mappers/mapper433.c | 44 + src/mappers/mapper434.c | 58 + src/mappers/mapper435.c | 53 + src/mappers/mapper436.c | 66 + src/mappers/mapper437.c | 58 + src/mappers/mapper438.c | 46 + src/mappers/mapper439.c | 66 + src/mappers/mapper441.c | 77 + src/mappers/mapper443.c | 84 + src/mappers/mapper444.c | 92 + src/mappers/mapper445.c | 120 ++ src/mappers/mapper446.c | 475 ++++++ src/mappers/mapper447.c | 94 ++ src/mappers/mapper448.c | 98 ++ src/mappers/mapper449.c | 59 + src/mappers/mapper450.c | 39 + src/mappers/mapper451.c | 111 ++ src/mappers/mapper452.c | 80 + src/mappers/mapper453.c | 59 + src/mappers/mapper454.c | 63 + src/mappers/mapper455.c | 79 + src/mappers/mapper456.c | 61 + src/mappers/mapper457.c | 67 + src/mappers/mapper458.c | 82 + src/mappers/mapper459.c | 42 + src/mappers/mapper460.c | 112 ++ src/mappers/mapper461.c | 40 + src/mappers/mapper463.c | 77 + src/mappers/mapper464.c | 42 + src/mappers/mapper465.c | 62 + src/mappers/mapper466.c | 108 ++ src/mappers/mapper467.c | 102 ++ src/mappers/mapper471.c | 52 + src/mappers/mapper500.c | 58 + src/mappers/mapper501.c | 57 + src/mappers/mapper502.c | 68 + src/mappers/mapper512.c | 85 + src/mappers/mapper513.c | 85 + src/mappers/mapper514.c | 95 ++ src/mappers/mapper516.c | 61 + src/mappers/mapper517.c | 101 ++ src/mappers/mapper518.c | 109 ++ src/mappers/mapper519.c | 86 + src/mappers/mapper520.c | 57 + src/mappers/mapper521.c | 52 + src/mappers/mapper522.c | 83 + src/mappers/mapper524.c | 74 + src/mappers/mapper525.c | 87 + src/mappers/mapper526.c | 123 ++ src/mappers/mapper527.c | 40 + src/mappers/mapper528.c | 98 ++ src/mappers/mapper529.c | 72 + src/mappers/mapper530.c | 55 + src/mappers/mapper533.c | 48 + src/mappers/mapper535.c | 99 ++ src/mappers/mapper538.c | 80 + src/mappers/mapper539.c | 115 ++ src/mappers/mapper541.c | 54 + src/mappers/mapper543.c | 90 + src/mappers/mapper544.c | 119 ++ src/mappers/mapper547.c | 220 +++ src/mappers/mapper548.c | 107 ++ src/mappers/mapper549.c | 52 + src/mappers/mapper550.c | 89 + src/mappers/mapper553.c | 38 + src/mappers/mapper554.c | 85 + src/mappers/mapper555.c | 133 ++ src/mappers/mapper556.c | 180 ++ src/mappers/mapper557.c | 43 + src/mappers/mapper558.c | 144 ++ src/mappers/mapper559.c | 91 + src/mappers/mapper561.c | 294 ++++ src/mappers/mapper562.c | 590 +++++++ src/mappers/nsf.c | 858 ++++++++++ src/mappers/nsf.h | 84 + src/mappers/nsfe.c | 283 ++++ src/mappers/nsfe.h | 6 + src/mappers/sound/dripsound.c | 250 +++ src/mappers/sound/dripsound.h | 29 + src/mappers/sound/emu2149.c | 431 +++++ src/mappers/sound/emu2149.h | 94 ++ src/mappers/sound/emu2413.c | 1507 +++++++++++++++++ src/mappers/sound/emu2413.h | 237 +++ src/mappers/sound/fdssound.c | 417 +++++ src/mappers/sound/fdssound.h | 96 ++ src/mappers/sound/mmc5sound.c | 301 ++++ src/mappers/sound/mmc5sound.h | 28 + src/mappers/sound/n163sound.c | 326 ++++ src/mappers/sound/n163sound.h | 32 + src/mappers/sound/s5bsound.c | 324 ++++ src/mappers/sound/s5bsound.h | 28 + src/mappers/sound/vrc6sound.c | 351 ++++ src/mappers/sound/vrc6sound.h | 28 + src/mappers/sound/vrc7sound.c | 150 ++ src/mappers/sound/vrc7sound.h | 28 + src/mappers/unif3Dblock.c | 109 ++ src/mappers/unifEt4320.c | 154 ++ src/mappers/unifFamicombox.c | 115 ++ src/mappers/unifKG256.c | 111 ++ src/mappers/unifT2271.c | 101 ++ src/mappers/unifTransformer.c | 103 ++ src/ppu.c | 7 + src/ppu.h | 15 + src/sound.c | 20 + src/sound.h | 7 + src/unif.c | 243 ++- src/unif.h | 2 +- src/x6502.c | 7 + src/x6502.h | 19 +- src/x6502struct.h | 1 + 528 files changed, 54369 insertions(+), 111 deletions(-) create mode 100644 fceumm_libretro.info create mode 100644 src/mappers/hw/bandai.c create mode 100644 src/mappers/hw/bandai.h create mode 100644 src/mappers/hw/eeprom_93Cx6.c create mode 100644 src/mappers/hw/eeprom_93Cx6.h create mode 100644 src/mappers/hw/eeprom_x24c0x.c create mode 100644 src/mappers/hw/eeprom_x24c0x.h create mode 100644 src/mappers/hw/flashrom.c create mode 100644 src/mappers/hw/flashrom.h create mode 100644 src/mappers/hw/fme7.c create mode 100644 src/mappers/hw/fme7.h create mode 100644 src/mappers/hw/jv001.c create mode 100644 src/mappers/hw/jv001.h create mode 100644 src/mappers/hw/jyasic.c create mode 100644 src/mappers/hw/jyasic.h create mode 100644 src/mappers/hw/ks202.c create mode 100644 src/mappers/hw/ks202.h create mode 100644 src/mappers/hw/latch.c create mode 100644 src/mappers/hw/latch.h create mode 100644 src/mappers/hw/mmc1.c create mode 100644 src/mappers/hw/mmc1.h create mode 100644 src/mappers/hw/mmc2.c create mode 100644 src/mappers/hw/mmc2.h create mode 100644 src/mappers/hw/mmc3.c create mode 100644 src/mappers/hw/mmc3.h create mode 100644 src/mappers/hw/mmc4.c create mode 100644 src/mappers/hw/mmc4.h create mode 100644 src/mappers/hw/mmc6.c create mode 100644 src/mappers/hw/mmc6.h create mode 100644 src/mappers/hw/n118.c create mode 100644 src/mappers/hw/n118.h create mode 100644 src/mappers/hw/pic16c5x.c create mode 100644 src/mappers/hw/pic16c5x.h create mode 100644 src/mappers/hw/pic16c5x_ops_00x.inc create mode 100644 src/mappers/hw/pic16c5x_ops_main.inc create mode 100644 src/mappers/hw/txc.c create mode 100644 src/mappers/hw/txc.h create mode 100644 src/mappers/hw/vrc24.c create mode 100644 src/mappers/hw/vrc24.h create mode 100644 src/mappers/hw/vrc6.c create mode 100644 src/mappers/hw/vrc6.h create mode 100644 src/mappers/hw/vrc7.c create mode 100644 src/mappers/hw/vrc7.h create mode 100644 src/mappers/hw/vrcirq.c create mode 100644 src/mappers/hw/vrcirq.h create mode 100644 src/mappers/mapinc.h create mode 100644 src/mappers/mapper.c create mode 100644 src/mappers/mapper000.c create mode 100644 src/mappers/mapper001.c create mode 100644 src/mappers/mapper002.c create mode 100644 src/mappers/mapper003.c create mode 100644 src/mappers/mapper004.c create mode 100644 src/mappers/mapper005.c create mode 100644 src/mappers/mapper006.c create mode 100644 src/mappers/mapper006.h create mode 100644 src/mappers/mapper007.c create mode 100644 src/mappers/mapper009.c create mode 100644 src/mappers/mapper010.c create mode 100644 src/mappers/mapper011.c create mode 100644 src/mappers/mapper012.c create mode 100644 src/mappers/mapper013.c create mode 100644 src/mappers/mapper014.c create mode 100644 src/mappers/mapper015.c create mode 100644 src/mappers/mapper016.c create mode 100644 src/mappers/mapper018.c create mode 100644 src/mappers/mapper019.c create mode 100644 src/mappers/mapper021.c create mode 100644 src/mappers/mapper022.c create mode 100644 src/mappers/mapper023.c create mode 100644 src/mappers/mapper024.c create mode 100644 src/mappers/mapper025.c create mode 100644 src/mappers/mapper026.c create mode 100644 src/mappers/mapper027.c create mode 100644 src/mappers/mapper028.c create mode 100644 src/mappers/mapper029.c create mode 100644 src/mappers/mapper030.c create mode 100644 src/mappers/mapper031.c create mode 100644 src/mappers/mapper032.c create mode 100644 src/mappers/mapper033.c create mode 100644 src/mappers/mapper034.c create mode 100644 src/mappers/mapper036.c create mode 100644 src/mappers/mapper037.c create mode 100644 src/mappers/mapper038.c create mode 100644 src/mappers/mapper040.c create mode 100644 src/mappers/mapper041.c create mode 100644 src/mappers/mapper042.c create mode 100644 src/mappers/mapper043.c create mode 100644 src/mappers/mapper044.c create mode 100644 src/mappers/mapper045.c create mode 100644 src/mappers/mapper046.c create mode 100644 src/mappers/mapper047.c create mode 100644 src/mappers/mapper048.c create mode 100644 src/mappers/mapper049.c create mode 100644 src/mappers/mapper050.c create mode 100644 src/mappers/mapper051.c create mode 100644 src/mappers/mapper052.c create mode 100644 src/mappers/mapper053.c create mode 100644 src/mappers/mapper055.c create mode 100644 src/mappers/mapper056.c create mode 100644 src/mappers/mapper057.c create mode 100644 src/mappers/mapper058.c create mode 100644 src/mappers/mapper059.c create mode 100644 src/mappers/mapper060.c create mode 100644 src/mappers/mapper061.c create mode 100644 src/mappers/mapper062.c create mode 100644 src/mappers/mapper063.c create mode 100644 src/mappers/mapper064.c create mode 100644 src/mappers/mapper065.c create mode 100644 src/mappers/mapper066.c create mode 100644 src/mappers/mapper067.c create mode 100644 src/mappers/mapper068.c create mode 100644 src/mappers/mapper069.c create mode 100644 src/mappers/mapper070.c create mode 100644 src/mappers/mapper071.c create mode 100644 src/mappers/mapper072.c create mode 100644 src/mappers/mapper073.c create mode 100644 src/mappers/mapper074.c create mode 100644 src/mappers/mapper075.c create mode 100644 src/mappers/mapper076.c create mode 100644 src/mappers/mapper077.c create mode 100644 src/mappers/mapper078.c create mode 100644 src/mappers/mapper079.c create mode 100644 src/mappers/mapper080.c create mode 100644 src/mappers/mapper081.c create mode 100644 src/mappers/mapper082.c create mode 100644 src/mappers/mapper083.c create mode 100644 src/mappers/mapper085.c create mode 100644 src/mappers/mapper086.c create mode 100644 src/mappers/mapper087.c create mode 100644 src/mappers/mapper088.c create mode 100644 src/mappers/mapper089.c create mode 100644 src/mappers/mapper091.c create mode 100644 src/mappers/mapper093.c create mode 100644 src/mappers/mapper094.c create mode 100644 src/mappers/mapper095.c create mode 100644 src/mappers/mapper096.c create mode 100644 src/mappers/mapper097.c create mode 100644 src/mappers/mapper099.c create mode 100644 src/mappers/mapper100.c create mode 100644 src/mappers/mapper101.c create mode 100644 src/mappers/mapper103.c create mode 100644 src/mappers/mapper104.c create mode 100644 src/mappers/mapper105.c create mode 100644 src/mappers/mapper106.c create mode 100644 src/mappers/mapper107.c create mode 100644 src/mappers/mapper108.c create mode 100644 src/mappers/mapper111.c create mode 100644 src/mappers/mapper112.c create mode 100644 src/mappers/mapper113.c create mode 100644 src/mappers/mapper114.c create mode 100644 src/mappers/mapper115.c create mode 100644 src/mappers/mapper116.c create mode 100644 src/mappers/mapper117.c create mode 100644 src/mappers/mapper118.c create mode 100644 src/mappers/mapper119.c create mode 100644 src/mappers/mapper120.c create mode 100644 src/mappers/mapper121.c create mode 100644 src/mappers/mapper123.c create mode 100644 src/mappers/mapper124.c create mode 100644 src/mappers/mapper125.c create mode 100644 src/mappers/mapper126.c create mode 100644 src/mappers/mapper127.c create mode 100644 src/mappers/mapper128.c create mode 100644 src/mappers/mapper132.c create mode 100644 src/mappers/mapper133.c create mode 100644 src/mappers/mapper134.c create mode 100644 src/mappers/mapper136.c create mode 100644 src/mappers/mapper137.c create mode 100644 src/mappers/mapper138.c create mode 100644 src/mappers/mapper139.c create mode 100644 src/mappers/mapper140.c create mode 100644 src/mappers/mapper141.c create mode 100644 src/mappers/mapper142.c create mode 100644 src/mappers/mapper143.c create mode 100644 src/mappers/mapper144.c create mode 100644 src/mappers/mapper145.c create mode 100644 src/mappers/mapper147.c create mode 100644 src/mappers/mapper148.c create mode 100644 src/mappers/mapper149.c create mode 100644 src/mappers/mapper150.c create mode 100644 src/mappers/mapper152.c create mode 100644 src/mappers/mapper153.c create mode 100644 src/mappers/mapper154.c create mode 100644 src/mappers/mapper155.c create mode 100644 src/mappers/mapper156.c create mode 100644 src/mappers/mapper157.c create mode 100644 src/mappers/mapper159.c create mode 100644 src/mappers/mapper160.c create mode 100644 src/mappers/mapper162.c create mode 100644 src/mappers/mapper163.c create mode 100644 src/mappers/mapper164.c create mode 100644 src/mappers/mapper165.c create mode 100644 src/mappers/mapper166.c create mode 100644 src/mappers/mapper167.c create mode 100644 src/mappers/mapper168.c create mode 100644 src/mappers/mapper170.c create mode 100644 src/mappers/mapper171.c create mode 100644 src/mappers/mapper172.c create mode 100644 src/mappers/mapper173.c create mode 100644 src/mappers/mapper174.c create mode 100644 src/mappers/mapper175.c create mode 100644 src/mappers/mapper176.c create mode 100644 src/mappers/mapper177.c create mode 100644 src/mappers/mapper178.c create mode 100644 src/mappers/mapper180.c create mode 100644 src/mappers/mapper183.c create mode 100644 src/mappers/mapper184.c create mode 100644 src/mappers/mapper185.c create mode 100644 src/mappers/mapper186.c create mode 100644 src/mappers/mapper187.c create mode 100644 src/mappers/mapper188.c create mode 100644 src/mappers/mapper189.c create mode 100644 src/mappers/mapper190.c create mode 100644 src/mappers/mapper191.c create mode 100644 src/mappers/mapper192.c create mode 100644 src/mappers/mapper193.c create mode 100644 src/mappers/mapper194.c create mode 100644 src/mappers/mapper195.c create mode 100644 src/mappers/mapper196.c create mode 100644 src/mappers/mapper197.c create mode 100644 src/mappers/mapper198.c create mode 100644 src/mappers/mapper199.c create mode 100644 src/mappers/mapper200.c create mode 100644 src/mappers/mapper201.c create mode 100644 src/mappers/mapper202.c create mode 100644 src/mappers/mapper203.c create mode 100644 src/mappers/mapper204.c create mode 100644 src/mappers/mapper205.c create mode 100644 src/mappers/mapper206.c create mode 100644 src/mappers/mapper208.c create mode 100644 src/mappers/mapper209.c create mode 100644 src/mappers/mapper210.c create mode 100644 src/mappers/mapper212.c create mode 100644 src/mappers/mapper214.c create mode 100644 src/mappers/mapper215.c create mode 100644 src/mappers/mapper216.c create mode 100644 src/mappers/mapper217.c create mode 100644 src/mappers/mapper218.c create mode 100644 src/mappers/mapper219.c create mode 100644 src/mappers/mapper221.c create mode 100644 src/mappers/mapper222.c create mode 100644 src/mappers/mapper225.c create mode 100644 src/mappers/mapper226.c create mode 100644 src/mappers/mapper227.c create mode 100644 src/mappers/mapper228.c create mode 100644 src/mappers/mapper229.c create mode 100644 src/mappers/mapper230.c create mode 100644 src/mappers/mapper231.c create mode 100644 src/mappers/mapper232.c create mode 100644 src/mappers/mapper233.c create mode 100644 src/mappers/mapper234.c create mode 100644 src/mappers/mapper235.c create mode 100644 src/mappers/mapper236.c create mode 100644 src/mappers/mapper237.c create mode 100644 src/mappers/mapper238.c create mode 100644 src/mappers/mapper240.c create mode 100644 src/mappers/mapper241.c create mode 100644 src/mappers/mapper242.c create mode 100644 src/mappers/mapper244.c create mode 100644 src/mappers/mapper245.c create mode 100644 src/mappers/mapper246.c create mode 100644 src/mappers/mapper249.c create mode 100644 src/mappers/mapper250.c create mode 100644 src/mappers/mapper252.c create mode 100644 src/mappers/mapper254.c create mode 100644 src/mappers/mapper256.c create mode 100644 src/mappers/mapper257.c create mode 100644 src/mappers/mapper259.c create mode 100644 src/mappers/mapper260.c create mode 100644 src/mappers/mapper261.c create mode 100644 src/mappers/mapper262.c create mode 100644 src/mappers/mapper263.c create mode 100644 src/mappers/mapper265.c create mode 100644 src/mappers/mapper266.c create mode 100644 src/mappers/mapper267.c create mode 100644 src/mappers/mapper268.c create mode 100644 src/mappers/mapper269.c create mode 100644 src/mappers/mapper271.c create mode 100644 src/mappers/mapper272.c create mode 100644 src/mappers/mapper274.c create mode 100644 src/mappers/mapper277.c create mode 100644 src/mappers/mapper281.c create mode 100644 src/mappers/mapper282.c create mode 100644 src/mappers/mapper283.c create mode 100644 src/mappers/mapper284.c create mode 100644 src/mappers/mapper285.c create mode 100644 src/mappers/mapper286.c create mode 100644 src/mappers/mapper287.c create mode 100644 src/mappers/mapper288.c create mode 100644 src/mappers/mapper289.c create mode 100644 src/mappers/mapper290.c create mode 100644 src/mappers/mapper291.c create mode 100644 src/mappers/mapper292.c create mode 100644 src/mappers/mapper293.c create mode 100644 src/mappers/mapper294.c create mode 100644 src/mappers/mapper295.c create mode 100644 src/mappers/mapper297.c create mode 100644 src/mappers/mapper298.c create mode 100644 src/mappers/mapper299.c create mode 100644 src/mappers/mapper300.c create mode 100644 src/mappers/mapper301.c create mode 100644 src/mappers/mapper302.c create mode 100644 src/mappers/mapper303.c create mode 100644 src/mappers/mapper304.c create mode 100644 src/mappers/mapper305.c create mode 100644 src/mappers/mapper306.c create mode 100644 src/mappers/mapper307.c create mode 100644 src/mappers/mapper308.c create mode 100644 src/mappers/mapper309.c create mode 100644 src/mappers/mapper310.c create mode 100644 src/mappers/mapper312.c create mode 100644 src/mappers/mapper313.c create mode 100644 src/mappers/mapper314.c create mode 100644 src/mappers/mapper315.c create mode 100644 src/mappers/mapper319.c create mode 100644 src/mappers/mapper320.c create mode 100644 src/mappers/mapper322.c create mode 100644 src/mappers/mapper323.c create mode 100644 src/mappers/mapper324.c create mode 100644 src/mappers/mapper325.c create mode 100644 src/mappers/mapper326.c create mode 100644 src/mappers/mapper327.c create mode 100644 src/mappers/mapper328.c create mode 100644 src/mappers/mapper329.c create mode 100644 src/mappers/mapper330.c create mode 100644 src/mappers/mapper331.c create mode 100644 src/mappers/mapper332.c create mode 100644 src/mappers/mapper333.c create mode 100644 src/mappers/mapper334.c create mode 100644 src/mappers/mapper335.c create mode 100644 src/mappers/mapper336.c create mode 100644 src/mappers/mapper337.c create mode 100644 src/mappers/mapper338.c create mode 100644 src/mappers/mapper339.c create mode 100644 src/mappers/mapper340.c create mode 100644 src/mappers/mapper341.c create mode 100644 src/mappers/mapper342.c create mode 100644 src/mappers/mapper343.c create mode 100644 src/mappers/mapper344.c create mode 100644 src/mappers/mapper345.c create mode 100644 src/mappers/mapper346.c create mode 100644 src/mappers/mapper347.c create mode 100644 src/mappers/mapper348.c create mode 100644 src/mappers/mapper349.c create mode 100644 src/mappers/mapper350.c create mode 100644 src/mappers/mapper351.c create mode 100644 src/mappers/mapper352.c create mode 100644 src/mappers/mapper353.c create mode 100644 src/mappers/mapper354.c create mode 100644 src/mappers/mapper355.c create mode 100644 src/mappers/mapper355.h create mode 100644 src/mappers/mapper356.c create mode 100644 src/mappers/mapper357.c create mode 100644 src/mappers/mapper358.c create mode 100644 src/mappers/mapper359.c create mode 100644 src/mappers/mapper360.c create mode 100644 src/mappers/mapper361.c create mode 100644 src/mappers/mapper362.c create mode 100644 src/mappers/mapper364.c create mode 100644 src/mappers/mapper366.c create mode 100644 src/mappers/mapper368.c create mode 100644 src/mappers/mapper369.c create mode 100644 src/mappers/mapper370.c create mode 100644 src/mappers/mapper372.c create mode 100644 src/mappers/mapper374.c create mode 100644 src/mappers/mapper375.c create mode 100644 src/mappers/mapper376.c create mode 100644 src/mappers/mapper377.c create mode 100644 src/mappers/mapper380.c create mode 100644 src/mappers/mapper381.c create mode 100644 src/mappers/mapper382.c create mode 100644 src/mappers/mapper383.c create mode 100644 src/mappers/mapper385.c create mode 100644 src/mappers/mapper386.c create mode 100644 src/mappers/mapper387.c create mode 100644 src/mappers/mapper388.c create mode 100644 src/mappers/mapper389.c create mode 100644 src/mappers/mapper390.c create mode 100644 src/mappers/mapper391.c create mode 100644 src/mappers/mapper393.c create mode 100644 src/mappers/mapper394.c create mode 100644 src/mappers/mapper395.c create mode 100644 src/mappers/mapper396.c create mode 100644 src/mappers/mapper397.c create mode 100644 src/mappers/mapper398.c create mode 100644 src/mappers/mapper399.c create mode 100644 src/mappers/mapper400.c create mode 100644 src/mappers/mapper401.c create mode 100644 src/mappers/mapper402.c create mode 100644 src/mappers/mapper403.c create mode 100644 src/mappers/mapper404.c create mode 100644 src/mappers/mapper406.c create mode 100644 src/mappers/mapper409.c create mode 100644 src/mappers/mapper410.c create mode 100644 src/mappers/mapper411.c create mode 100644 src/mappers/mapper412.c create mode 100644 src/mappers/mapper413.c create mode 100644 src/mappers/mapper414.c create mode 100644 src/mappers/mapper415.c create mode 100644 src/mappers/mapper416.c create mode 100644 src/mappers/mapper417.c create mode 100644 src/mappers/mapper418.c create mode 100644 src/mappers/mapper420.c create mode 100644 src/mappers/mapper421.c create mode 100644 src/mappers/mapper428.c create mode 100644 src/mappers/mapper429.c create mode 100644 src/mappers/mapper430.c create mode 100644 src/mappers/mapper431.c create mode 100644 src/mappers/mapper432.c create mode 100644 src/mappers/mapper433.c create mode 100644 src/mappers/mapper434.c create mode 100644 src/mappers/mapper435.c create mode 100644 src/mappers/mapper436.c create mode 100644 src/mappers/mapper437.c create mode 100644 src/mappers/mapper438.c create mode 100644 src/mappers/mapper439.c create mode 100644 src/mappers/mapper441.c create mode 100644 src/mappers/mapper443.c create mode 100644 src/mappers/mapper444.c create mode 100644 src/mappers/mapper445.c create mode 100644 src/mappers/mapper446.c create mode 100644 src/mappers/mapper447.c create mode 100644 src/mappers/mapper448.c create mode 100644 src/mappers/mapper449.c create mode 100644 src/mappers/mapper450.c create mode 100644 src/mappers/mapper451.c create mode 100644 src/mappers/mapper452.c create mode 100644 src/mappers/mapper453.c create mode 100644 src/mappers/mapper454.c create mode 100644 src/mappers/mapper455.c create mode 100644 src/mappers/mapper456.c create mode 100644 src/mappers/mapper457.c create mode 100644 src/mappers/mapper458.c create mode 100644 src/mappers/mapper459.c create mode 100644 src/mappers/mapper460.c create mode 100644 src/mappers/mapper461.c create mode 100644 src/mappers/mapper463.c create mode 100644 src/mappers/mapper464.c create mode 100644 src/mappers/mapper465.c create mode 100644 src/mappers/mapper466.c create mode 100644 src/mappers/mapper467.c create mode 100644 src/mappers/mapper471.c create mode 100644 src/mappers/mapper500.c create mode 100644 src/mappers/mapper501.c create mode 100644 src/mappers/mapper502.c create mode 100644 src/mappers/mapper512.c create mode 100644 src/mappers/mapper513.c create mode 100644 src/mappers/mapper514.c create mode 100644 src/mappers/mapper516.c create mode 100644 src/mappers/mapper517.c create mode 100644 src/mappers/mapper518.c create mode 100644 src/mappers/mapper519.c create mode 100644 src/mappers/mapper520.c create mode 100644 src/mappers/mapper521.c create mode 100644 src/mappers/mapper522.c create mode 100644 src/mappers/mapper524.c create mode 100644 src/mappers/mapper525.c create mode 100644 src/mappers/mapper526.c create mode 100644 src/mappers/mapper527.c create mode 100644 src/mappers/mapper528.c create mode 100644 src/mappers/mapper529.c create mode 100644 src/mappers/mapper530.c create mode 100644 src/mappers/mapper533.c create mode 100644 src/mappers/mapper535.c create mode 100644 src/mappers/mapper538.c create mode 100644 src/mappers/mapper539.c create mode 100644 src/mappers/mapper541.c create mode 100644 src/mappers/mapper543.c create mode 100644 src/mappers/mapper544.c create mode 100644 src/mappers/mapper547.c create mode 100644 src/mappers/mapper548.c create mode 100644 src/mappers/mapper549.c create mode 100644 src/mappers/mapper550.c create mode 100644 src/mappers/mapper553.c create mode 100644 src/mappers/mapper554.c create mode 100644 src/mappers/mapper555.c create mode 100644 src/mappers/mapper556.c create mode 100644 src/mappers/mapper557.c create mode 100644 src/mappers/mapper558.c create mode 100644 src/mappers/mapper559.c create mode 100644 src/mappers/mapper561.c create mode 100644 src/mappers/mapper562.c create mode 100644 src/mappers/nsf.c create mode 100644 src/mappers/nsf.h create mode 100644 src/mappers/nsfe.c create mode 100644 src/mappers/nsfe.h create mode 100644 src/mappers/sound/dripsound.c create mode 100644 src/mappers/sound/dripsound.h create mode 100644 src/mappers/sound/emu2149.c create mode 100644 src/mappers/sound/emu2149.h create mode 100644 src/mappers/sound/emu2413.c create mode 100644 src/mappers/sound/emu2413.h create mode 100644 src/mappers/sound/fdssound.c create mode 100644 src/mappers/sound/fdssound.h create mode 100644 src/mappers/sound/mmc5sound.c create mode 100644 src/mappers/sound/mmc5sound.h create mode 100644 src/mappers/sound/n163sound.c create mode 100644 src/mappers/sound/n163sound.h create mode 100644 src/mappers/sound/s5bsound.c create mode 100644 src/mappers/sound/s5bsound.h create mode 100644 src/mappers/sound/vrc6sound.c create mode 100644 src/mappers/sound/vrc6sound.h create mode 100644 src/mappers/sound/vrc7sound.c create mode 100644 src/mappers/sound/vrc7sound.h create mode 100644 src/mappers/unif3Dblock.c create mode 100644 src/mappers/unifEt4320.c create mode 100644 src/mappers/unifFamicombox.c create mode 100644 src/mappers/unifKG256.c create mode 100644 src/mappers/unifT2271.c create mode 100644 src/mappers/unifTransformer.c diff --git a/Makefile.common b/Makefile.common index d0ca21d0a..2c172acc5 100644 --- a/Makefile.common +++ b/Makefile.common @@ -5,7 +5,9 @@ INCFLAGS := \ -I$(LIBRETRO_COMM_DIR)/include \ -I$(CORE_DIR) \ -I$(CORE_DIR)/input \ - -I$(CORE_DIR)/boards + -I$(CORE_DIR)/mappers \ + -I$(CORE_DIR)/mappers/hw \ + -I$(CORE_DIR)/mappers/sound ifneq (,$(findstring msvc2003,$(platform))) INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc @@ -18,7 +20,9 @@ COREDEFINES = \ -DFRONTEND_SUPPORTS_RGB565 FCEU_SRC_DIRS := \ - $(CORE_DIR)/boards \ + $(CORE_DIR)/mappers \ + $(CORE_DIR)/mappers/hw \ + $(CORE_DIR)/mappers/sound \ $(CORE_DIR)/input SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c)) @@ -46,7 +50,6 @@ SOURCES_C += \ $(CORE_DIR)/general.c \ $(CORE_DIR)/input.c \ $(CORE_DIR)/md5.c \ - $(CORE_DIR)/nsf.c \ $(CORE_DIR)/palette.c \ $(CORE_DIR)/ppu.c \ $(CORE_DIR)/sound.c \ diff --git a/fceumm_libretro.info b/fceumm_libretro.info new file mode 100644 index 000000000..7dfd3e40b --- /dev/null +++ b/fceumm_libretro.info @@ -0,0 +1,45 @@ +# Software Information +display_name = "Nintendo - NES / Famicom (FCEUmm)" +authors = "FCEU Team|CaH4e3" +supported_extensions = "fds|nes|unif|unf|nsf|nsfe" +corename = "FCEUmm" +license = "GPLv2" +permissions = "" +display_version = "SVN" +categories = "Emulator" + +# Hardware Information +manufacturer = "Nintendo" +systemname = "Nintendo Entertainment System" +systemid = "nes" + +# Libretro Features +supports_no_game = "false" +savestate = "true" +savestate_features = "deterministic" +cheats = "true" +input_descriptors = "true" +memory_descriptors = "true" +libretro_saves = "true" +core_options = "true" +core_options_version = "1.0" +load_subsystem = "false" +hw_render = "false" +needs_fullpath = "false" +disk_control = "false" +database = "Nintendo - Nintendo Entertainment System|Nintendo - Family Computer Disk System" + +# BIOS / Firmware +firmware_count = 3 +firmware0_desc = "disksys.rom (Family Computer Disk System BIOS)" +firmware0_path = "disksys.rom" +firmware0_opt = "true" +firmware1_desc = "nes.pal (custom NES Palette)" +firmware1_path = "nes.pal" +firmware1_opt = "true" +firmware2_desc = "gamegenie.nes (Game Genie add-on cartridge)" +firmware2_path = "gamegenie.nes" +firmware2_opt = "true" +notes = "(!) disksys.rom (md5): ca30b50f880eb660a320674ed365ef7a|(!) gamegenie.nes (md5): 7f98d77d7a094ad7d069b74bd553ec98|(!) nes.pal must be located in system directory." + +description = "FCEUmm libretro is based on the FCEUmm (mappers modified) fork of the FCEU emulator. It is very fast and supports many mappers, including those for weird, obscure bootleg carts. It is tightly integrated with libretro features, which makes it a good choice for users seeking advanced frontend functionality, such as runahead and rollback netplay. While most NES emulators are lightweight, FCEUmm's particularly low resource requirements make it a good option for mobile, low-power/embedded and console targets." diff --git a/src/cart.h b/src/cart.h index 457340364..397610eb7 100644 --- a/src/cart.h +++ b/src/cart.h @@ -35,8 +35,12 @@ typedef struct { * code, used by mapper/board code, maybe * other code in the future. */ + + int trainer; /* TODO */ } CartInfo; +extern CartInfo iNESCart; + extern uint8 *Page[32], *VPage[8], *MMC5SPRVPage[8], *MMC5BGVPage[8]; void ResetCartMapping(void); diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 843661063..604090561 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -1671,7 +1671,7 @@ void retro_set_environment(retro_environment_t cb) void retro_get_system_info(struct retro_system_info *info) { info->need_fullpath = true; - info->valid_extensions = "fds|nes|unf|unif"; + info->valid_extensions = "fds|nes|unf|unif|nsf|nsfe"; #ifdef GIT_VERSION info->library_version = "(SVN)" GIT_VERSION; #else diff --git a/src/fceu-types.h b/src/fceu-types.h index 0ea2f4b56..ef70b8de8 100644 --- a/src/fceu-types.h +++ b/src/fceu-types.h @@ -75,6 +75,14 @@ typedef long long int64; #define FASTAPASS(x) #endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + typedef void (FP_FASTAPASS(2) *writefunc)(uint32 A, uint8 V); typedef uint8 (FP_FASTAPASS(1) *readfunc)(uint32 A); diff --git a/src/fceu.c b/src/fceu.c index 35c172b4a..296011a2c 100644 --- a/src/fceu.c +++ b/src/fceu.c @@ -314,6 +314,12 @@ int FCEUI_Initialize(void) { FSettings.UsrLastSLine[0] = 231; FSettings.UsrLastSLine[1] = 239; FSettings.SoundVolume = 100; + FSettings.ExpSoundVolume[0] = 256; + FSettings.ExpSoundVolume[1] = 256; + FSettings.ExpSoundVolume[2] = 256; + FSettings.ExpSoundVolume[3] = 256; + FSettings.ExpSoundVolume[4] = 256; + FSettings.ExpSoundVolume[5] = 256; FCEUPPU_Init(); X6502_Init(); return 1; diff --git a/src/fceu.h b/src/fceu.h index 7588e7747..5897ea3b1 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -74,9 +74,20 @@ extern uint8 PAL; #include "driver.h" +enum EXPSOUNDTYPE { + SND_VRC6 = 0, + SND_VRC7 = 1, + SND_FDS = 2, + SND_N163 = 3, + SND_S5B = 4, + SND_MMC5 = 5, + SND_LAST, +}; + typedef struct { int PAL; int SoundVolume; + int ExpSoundVolume[6]; int TriangleVolume; int SquareVolume[2]; int NoiseVolume; diff --git a/src/ines.c b/src/ines.c index 01e7901af..df3462710 100644 --- a/src/ines.c +++ b/src/ines.c @@ -420,6 +420,7 @@ typedef struct { #define INES_BOARD_END() { (uint8_t*)"", 0, NULL} }; #define INES_BOARD(a, b, c) { (uint8_t*)a, b, c }, +#if 0 INES_BOARD_BEGIN() INES_BOARD( "NROM", 0, NROM_Init ) INES_BOARD( "MMC1", 1, Mapper1_Init ) @@ -879,6 +880,492 @@ INES_BOARD_BEGIN() INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "YC-03-09", 558, Mapper558_Init ) INES_BOARD_END() +#endif + +INES_BOARD_BEGIN() + INES_BOARD( "NROM", 0, Mapper000_Init ) + INES_BOARD( "MMC1", 1, Mapper001_Init ) + INES_BOARD( "UNROM", 2, Mapper002_Init ) + INES_BOARD( "CNROM", 3, Mapper003_Init ) + INES_BOARD( "MMC3", 4, Mapper004_Init ) + INES_BOARD( "MMC5", 5, Mapper005_Init ) + INES_BOARD( "FFE Magic Card 1M/2M", 6, Mapper006_Init ) + INES_BOARD( "ANROM", 7, Mapper007_Init ) + INES_BOARD( "FFE Magic Card 1M/2M", 8, Mapper006_Init ) /* mapper 6, submapper 4 */ + INES_BOARD( "MMC2", 9, Mapper009_Init ) + INES_BOARD( "MMC4", 10, Mapper010_Init ) + INES_BOARD( "Color Dreams", 11, Mapper011_Init ) + INES_BOARD( "REX DBZ 5/ FFE Magic Cart 4M", 12, Mapper012_Init ) + INES_BOARD( "CPROM", 13, Mapper013_Init ) + INES_BOARD( "REX SL-1632", 14, Mapper014_Init ) + INES_BOARD( "100-in-1", 15, Mapper015_Init ) + INES_BOARD( "BANDAI 24C02", 16, Mapper016_Init ) + INES_BOARD( "FFE Magic Card", 17, Mapper006_Init ) + INES_BOARD( "JALECO SS880006", 18, Mapper018_Init ) /* JF-NNX (EB89018-30007) boards */ + INES_BOARD( "Namco 129/163", 19, Mapper019_Init ) +/* INES_BOARD( "", 20, Mapper20_Init ) */ + INES_BOARD( "Konami VRC2/VRC4 A", 21, Mapper021_Init ) + INES_BOARD( "Konami VRC2/VRC4 B", 22, Mapper022_Init ) + INES_BOARD( "Konami VRC2/VRC4 C", 23, Mapper023_Init ) + INES_BOARD( "Konami VRC6 Rev. A", 24, Mapper024_Init ) + INES_BOARD( "Konami VRC2/VRC4 D", 25, Mapper025_Init ) + INES_BOARD( "Konami VRC6 Rev. B", 26, Mapper026_Init ) + INES_BOARD( "CC-21 MI HUN CHE", 27, Mapper027_Init ) /* Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards */ + INES_BOARD( "Action 53", 28, Mapper028_Init ) + INES_BOARD( "RET-CUFROM", 29, Mapper029_Init ) + INES_BOARD( "UNROM 512", 30, Mapper030_Init ) + INES_BOARD( "infineteNesLives-NSF", 31, Mapper031_Init ) + INES_BOARD( "IREM G-101", 32, Mapper032_Init ) + INES_BOARD( "Taito TC0190FMC/TC0350FMR", 33, Mapper033_Init ) + INES_BOARD( "BNROM/NINA-001", 34, Mapper034_Init ) + INES_BOARD( "EL870914C", 35, Mapper035_Init ) + INES_BOARD( "TXC Policeman", 36, Mapper036_Init ) + INES_BOARD( "PAL-ZZ SMB/TETRIS/NWC", 37, Mapper037_Init ) + INES_BOARD( "Bit Corp.", 38, Mapper038_Init ) /* Crime Busters */ +/* INES_BOARD( "", 39, Mapper39_Init ) */ + INES_BOARD( "SMB2j FDS", 40, Mapper040_Init ) + INES_BOARD( "CALTRON 6-in-1", 41, Mapper041_Init ) + INES_BOARD( "BIO MIRACLE FDS", 42, Mapper042_Init ) + INES_BOARD( "FDS SMB2j LF36", 43, Mapper043_Init ) + INES_BOARD( "MMC3 BMC PIRATE A", 44, Mapper044_Init ) + INES_BOARD( "MMC3 BMC PIRATE B", 45, Mapper045_Init ) + INES_BOARD( "RUMBLESTATION 15-in-1", 46, Mapper046_Init ) + INES_BOARD( "NES-QJ SSVB/NWC", 47, Mapper047_Init ) + INES_BOARD( "Taito TC0690/TC190+PAL16R4", 48, Mapper048_Init ) + INES_BOARD( "MMC3 BMC PIRATE C", 49, Mapper049_Init ) + INES_BOARD( "SMB2j FDS Rev. A", 50, Mapper050_Init ) + INES_BOARD( "11-in-1 BALL SERIES", 51, Mapper051_Init ) /* 1993 year version */ + INES_BOARD( "MMC3 BMC PIRATE D", 52, Mapper052_Init ) + INES_BOARD( "SUPERVISION 16-in-1", 53, Mapper053_Init ) +/* INES_BOARD( "", 54, Mapper54_Init ) */ + INES_BOARD( "MARIO1-MALEE2", 55, Mapper055_Init ) + INES_BOARD( "UNLKS202", 56, Mapper056_Init ) + INES_BOARD( "SIMBPLE BMC PIRATE A", 57, Mapper057_Init ) + INES_BOARD( "SIMBPLE BMC PIRATE B", 58, Mapper058_Init ) + INES_BOARD( "BMC T3H53/D1038", 59, Mapper059_Init ) + INES_BOARD( "Reset-based NROM-128 ", 60, Mapper060_Init ) + INES_BOARD( "20-in-1 KAISER Rev. A", 61, Mapper061_Init ) + INES_BOARD( "700-in-1", 62, Mapper062_Init ) + INES_BOARD( "Powerful 250-in-1 (NTDEC TH2291)", 63, Mapper063_Init ) + INES_BOARD( "TENGEN RAMBO1", 64, Mapper064_Init ) + INES_BOARD( "IREM-H3001", 65, Mapper065_Init ) + INES_BOARD( "GNROM / MHROM", 66, Mapper066_Init ) + INES_BOARD( "SUNSOFT-FZII", 67, Mapper067_Init ) + INES_BOARD( "Sunsoft Mapper #4", 68, Mapper068_Init ) + INES_BOARD( "SUNSOFT-5/FME-7", 69, Mapper069_Init ) + INES_BOARD( "BA KAMEN DISCRETE", 70, Mapper070_Init ) + INES_BOARD( "CAMERICA BF9093", 71, Mapper071_Init ) + INES_BOARD( "JALECO JF-17", 72, Mapper072_Init ) + INES_BOARD( "KONAMI VRC3", 73, Mapper073_Init ) + INES_BOARD( "TW MMC3+VRAM Rev. A", 74, Mapper074_Init ) + INES_BOARD( "KONAMI VRC1", 75, Mapper075_Init ) + INES_BOARD( "NAMCOT 108 Rev. A", 76, Mapper076_Init ) + INES_BOARD( "IREM LROG017", 77, Mapper077_Init ) + INES_BOARD( "Irem 74HC161/32", 78, Mapper078_Init ) + INES_BOARD( "AVE/C&E/TXC BOARD", 79, Mapper079_Init ) + INES_BOARD( "TAITO X1-005 Rev. A", 80, Mapper080_Init ) + INES_BOARD( "Super Gun (NTDEC N715021)", 81, Mapper081_Init ) + INES_BOARD( "TAITO X1-017", 82, Mapper082_Init ) + INES_BOARD( "YOKO VRC Rev. B", 83, Mapper083_Init ) +/* INES_BOARD( "", 84, Mapper84_Init ) */ + INES_BOARD( "KONAMI VRC7", 85, Mapper085_Init ) + INES_BOARD( "JALECO JF-13", 86, Mapper086_Init ) + INES_BOARD( "74*139/74 DISCRETE", 87, Mapper087_Init ) + INES_BOARD( "NAMCO 3433", 88, Mapper088_Init ) + INES_BOARD( "SUNSOFT-3", 89, Mapper089_Init ) /* SUNSOFT-2 mapper */ + INES_BOARD( "HUMMER/JY BOARD", 90, Mapper090_Init ) + INES_BOARD( "JY830623C/YY840238C/EJ-006-1", 91, Mapper091_Init ) + INES_BOARD( "JALECO JF-19", 92, Mapper072_Init ) + INES_BOARD( "SUNSOFT-3R", 93, Mapper093_Init ) /* SUNSOFT-2 mapper with VRAM, different wiring */ + INES_BOARD( "HVC-UN1ROM", 94, Mapper094_Init ) + INES_BOARD( "NAMCOT 108 Rev. B", 95, Mapper095_Init ) + INES_BOARD( "BANDAI OEKAKIDS", 96, Mapper096_Init ) + INES_BOARD( "IREM TAM-S1", 97, Mapper097_Init ) +/* INES_BOARD( "", 98, Mapper98_Init ) */ + INES_BOARD( "Vs. System", 99, Mapper099_Init ) + INES_BOARD( "Nesticle MMC3", 100, Mapper100_Init ) + INES_BOARD( "", 101, Mapper101_Init ) +/* INES_BOARD( "", 102, Mapper102_Init ) */ + INES_BOARD( "FDS DOKIDOKI FULL", 103, Mapper103_Init ) + INES_BOARD( "CAMERICA GOLDENFIVE", 104, Mapper104_Init ) + INES_BOARD( "NES-EVENT NWC1990", 105, Mapper105_Init ) + INES_BOARD( "SMB3 PIRATE A", 106, Mapper106_Init ) + INES_BOARD( "MAGIC CORP A", 107, Mapper107_Init ) + INES_BOARD( "FDS UNROM BOARD", 108, Mapper108_Init ) +/* INES_BOARD( "", 109, Mapper109_Init ) */ +/* INES_BOARD( "", 110, Mapper110_Init ) */ + INES_BOARD( "Cheapocabra", 111, Mapper111_Init ) + INES_BOARD( "ASDER/NTDEC BOARD", 112, Mapper112_Init ) + INES_BOARD( "HACKER/SACHEN BOARD", 113, Mapper113_Init ) + INES_BOARD( "MMC3 SG PROT. A", 114, Mapper114_Init ) + INES_BOARD( "MMC3 PIRATE A", 115, Mapper115_Init ) + INES_BOARD( "MMC1/MMC3/VRC PIRATE", 116, Mapper116_Init ) + INES_BOARD( "FUTURE MEDIA BOARD", 117, Mapper117_Init ) + INES_BOARD( "TSKROM", 118, Mapper118_Init ) + INES_BOARD( "TQROM", 119, Mapper119_Init ) + INES_BOARD( "FDS TOBIDASE", 120, Mapper120_Init ) + INES_BOARD( "MMC3 PIRATE PROT. A", 121, Mapper121_Init ) +/* INES_BOARD( "", 122, Mapper122_Init ) */ + INES_BOARD( "MMC3 PIRATE H2288", 123, Mapper123_Init ) + INES_BOARD( "Super Game Mega Type III", 124, Mapper124_Init ) + INES_BOARD( "FDS LH32", 125, Mapper125_Init ) + INES_BOARD( "PowerJoy 84-in-1 PJ-008", 126, Mapper126_Init ) + INES_BOARD( "Double Dragon II (Pirate)", 127, Mapper127_Init ) + INES_BOARD( "1994 Super HiK 4-in-1", 128, Mapper128_Init ) +/* INES_BOARD( "", 129, Mapper129_Init ) */ +/* INES_BOARD( "", 130, Mapper130_Init ) */ +/* INES_BOARD( "", 131, Mapper131_Init ) */ + INES_BOARD( "TXC/UNL-22211", 132, Mapper132_Init ) + INES_BOARD( "SA72008", 133, Mapper133_Init ) + INES_BOARD( "MMC3 BMC PIRATE", 134, Mapper134_Init ) +/* INES_BOARD( "", 135, Mapper135_Init ) */ /* Duplicate of 135 */ + INES_BOARD( "Sachen 3011", 136, Mapper136_Init ) + INES_BOARD( "S8259D", 137, Mapper137_Init ) + INES_BOARD( "S8259B", 138, Mapper138_Init ) + INES_BOARD( "S8259C", 139, Mapper139_Init ) + INES_BOARD( "JALECO JF-11/14", 140, Mapper140_Init ) + INES_BOARD( "S8259A", 141, Mapper141_Init ) + INES_BOARD( "UNLKS7032", 142, Mapper142_Init ) + INES_BOARD( "TCA01", 143, Mapper143_Init ) + INES_BOARD( "AGCI 50282", 144, Mapper144_Init ) + INES_BOARD( "SA72007", 145, Mapper145_Init ) +/* INES_BOARD( "", 146, SA0161M_Init ) */ /* moved to mapper 79 */ + INES_BOARD( "Sachen 3018 board", 147, Mapper147_Init ) + INES_BOARD( "SA0037", 148, Mapper148_Init ) + INES_BOARD( "SA0036", 149, Mapper149_Init ) + INES_BOARD( "SA-015/SA-630", 150, Mapper150_Init ) + INES_BOARD( "Vs. Unisystem (Konami)", 151, Mapper151_Init ) /* legacy support. all fixed roms should be using mapper 75 */ + INES_BOARD( "", 152, Mapper152_Init ) + INES_BOARD( "BANDAI SRAM", 153, Mapper153_Init ) /* Bandai board 16 with SRAM instead of EEPROM */ + INES_BOARD( "", 154, Mapper154_Init ) + INES_BOARD( "", 155, Mapper155_Init ) + INES_BOARD( "", 156, Mapper156_Init ) + INES_BOARD( "BANDAI BARCODE", 157, Mapper157_Init ) + INES_BOARD( "TENGEN 800037", 158, Mapper064_Init ) + INES_BOARD( "BANDAI 24C01", 159, Mapper159_Init ) /* Different type of EEPROM on the bandai board */ +/* INES_BOARD( "SA009", 160, Mapper160_Init ) */ +/* INES_BOARD( "", 161, Mapper161_Init ) */ + INES_BOARD( "", 162, Mapper162_Init ) + INES_BOARD( "", 163, Mapper163_Init ) + INES_BOARD( "", 164, Mapper164_Init ) + INES_BOARD( "", 165, Mapper165_Init ) + INES_BOARD( "SUBOR Rev. A", 166, Mapper166_Init ) + INES_BOARD( "SUBOR Rev. B", 167, Mapper167_Init ) + INES_BOARD( "", 168, Mapper168_Init ) +/* INES_BOARD( "", 169, Mapper169_Init ) */ + INES_BOARD( "", 170, Mapper170_Init ) + INES_BOARD( "Kaiser 7058", 171, Mapper171_Init ) + INES_BOARD( "Super Mega P-4070", 172, Mapper172_Init ) + INES_BOARD( "Idea-Tek ET.xx", 173, Mapper173_Init ) + INES_BOARD( "NTDec 5-in-1", 174, Mapper174_Init ) + INES_BOARD( "", 175, Mapper175_Init ) + INES_BOARD( "BMCFK23C", 176, Mapper176_Init ) + INES_BOARD( "Hénggé Diànzǐ", 177, Mapper177_Init ) + INES_BOARD( "FS305/NJ0430", 178, Mapper178_Init ) +/* INES_BOARD( "", 179, Mapper179_Init ) */ + INES_BOARD( "", 180, Mapper180_Init ) +/* INES_BOARD( "", 181, Mapper181_Init ) */ /* fceux' exclusive mapper to handle Seicross V2, now moved to Mapper 185,sub 4 */ +/* INES_BOARD( "", 182, Mapper182_Init ) */ /* Deprecated, dupe of Mapper 114 */ + INES_BOARD( "", 183, Mapper183_Init ) + INES_BOARD( "", 184, Mapper184_Init ) + INES_BOARD( "CNROM+CopyProtection", 185, Mapper185_Init ) + INES_BOARD( "", 186, Mapper186_Init ) + INES_BOARD( "", 187, Mapper187_Init ) + INES_BOARD( "", 188, Mapper188_Init ) + INES_BOARD( "", 189, Mapper189_Init ) + INES_BOARD( "", 190, Mapper190_Init ) + INES_BOARD( "", 191, Mapper191_Init ) + INES_BOARD( "TW MMC3+VRAM Rev. B", 192, Mapper192_Init ) + INES_BOARD( "NTDEC TC-112", 193, Mapper193_Init ) /* War in the Gulf */ + INES_BOARD( "TW MMC3+VRAM Rev. C", 194, Mapper194_Init ) + INES_BOARD( "TW MMC3+VRAM Rev. D", 195, Mapper195_Init ) + INES_BOARD( "", 196, Mapper196_Init ) + INES_BOARD( "", 197, Mapper197_Init ) + INES_BOARD( "TW MMC3+VRAM Rev. E", 198, Mapper198_Init ) + INES_BOARD( "", 199, Mapper199_Init ) + INES_BOARD( "", 200, Mapper200_Init ) + INES_BOARD( "21-in-1", 201, Mapper201_Init ) + INES_BOARD( "", 202, Mapper202_Init ) + INES_BOARD( "", 203, Mapper203_Init ) + INES_BOARD( "", 204, Mapper204_Init ) + INES_BOARD( "BMC 15-in-1/3-in-1", 205, Mapper205_Init ) + INES_BOARD( "NAMCOT 108 Rev. C", 206, Mapper206_Init ) /* Deprecated, Used to be "DEIROM" whatever it means, but actually simple version of MMC3 */ + INES_BOARD( "TAITO X1-005 Rev. B", 207, Mapper207_Init ) + INES_BOARD( "", 208, Mapper208_Init ) + INES_BOARD( "HUMMER/JY BOARD", 209, Mapper209_Init ) + INES_BOARD( "", 210, Mapper210_Init ) + INES_BOARD( "HUMMER/JY BOARD", 211, Mapper211_Init ) + INES_BOARD( "", 212, Mapper212_Init ) + INES_BOARD( "", 213, Mapper058_Init ) /* in mapper 58 */ + INES_BOARD( "", 214, Mapper214_Init ) + INES_BOARD( "UNL-8237", 215, Mapper215_Init ) + INES_BOARD( "Bonza", 216, Mapper216_Init ) + INES_BOARD( "", 217, Mapper217_Init ) /* Redefined to a new Discrete BMC mapper */ + INES_BOARD( "Magic Floor", 218, Mapper218_Init ) + INES_BOARD( "A9746", 219, Mapper219_Init ) +/* INES_BOARD( "Debug Mapper", 220, Mapper220_Init ) */ + INES_BOARD( "UNLN625092", 221, Mapper221_Init ) + INES_BOARD( "", 222, Mapper222_Init ) +/* INES_BOARD( "", 223, Mapper223_Init ) */ + INES_BOARD( "KT-008", 224, MINDKIDS_Init ) /* The KT-008 board contains the MINDKIDS chipset */ + INES_BOARD( "", 225, Mapper225_Init ) + INES_BOARD( "BMC 22+20-in-1", 226, Mapper226_Init ) + INES_BOARD( "", 227, Mapper227_Init ) + INES_BOARD( "", 228, Mapper228_Init ) + INES_BOARD( "", 229, Mapper229_Init ) + INES_BOARD( "BMC Contra+22-in-1", 230, Mapper230_Init ) + INES_BOARD( "20-in-1", 231, Mapper231_Init ) + INES_BOARD( "BMC QUATTRO", 232, Mapper232_Init ) + INES_BOARD( "BMC 22+20-in-1 RST", 233, Mapper233_Init ) + INES_BOARD( "BMC MAXI", 234, Mapper234_Init ) + INES_BOARD( "Golden Game", 235, Mapper235_Init ) + INES_BOARD( "Realtec 8031/8155/8099/8106", 236, Mapper236_Init ) + INES_BOARD( "Teletubbies / Y2K", 237, Mapper237_Init ) + INES_BOARD( "UNL6035052", 238, Mapper238_Init ) +/* INES_BOARD( "", 239, Mapper239_Init ) */ + INES_BOARD( "", 240, Mapper240_Init ) + INES_BOARD( "BxROM+WRAM", 241, Mapper241_Init ) + INES_BOARD( "43272", 242, Mapper242_Init ) + INES_BOARD( "SA-020A", 243, Mapper150_Init ) + INES_BOARD( "DECATHLON", 244, Mapper244_Init ) + INES_BOARD( "", 245, Mapper245_Init ) + INES_BOARD( "FONG SHEN BANG", 246, Mapper246_Init ) +/* INES_BOARD( "", 247, Mapper247_Init ) */ +/* INES_BOARD( "", 248, Mapper248_Init ) */ + INES_BOARD( "", 249, Mapper249_Init ) + INES_BOARD( "", 250, Mapper250_Init ) +/* INES_BOARD( "", 251, Mapper251_Init ) */ /* No good dumps for this mapper, use UNIF version */ + INES_BOARD( "SAN GUO ZHI PIRATE", 252, Mapper252_Init ) + INES_BOARD( "DRAGON BALL PIRATE", 253, Mapper252_Init ) + INES_BOARD( "", 254, Mapper254_Init ) + INES_BOARD( "", 255, Mapper255_Init ) /* Duplicate of M225? */ + + /* NES 2.0 MAPPERS */ + + INES_BOARD( "OneBus", 256, Mapper256_Init ) + INES_BOARD( "158B", 258, Mapper215_Init ) + INES_BOARD( "F-15", 259, Mapper259_Init ) + INES_BOARD( "HPxx / HP2018-A", 260, Mapper260_Init ) + INES_BOARD( "810544-C-A1", 261, Mapper261_Init ) + INES_BOARD( "SHERO", 262, Mapper262_Init ) + INES_BOARD( "KOF97", 263, Mapper263_Init ) + INES_BOARD( "YOKO", 264, Mapper264_Init ) + INES_BOARD( "T-262", 265, Mapper265_Init ) + INES_BOARD( "CITYFIGHT", 266, Mapper266_Init ) + INES_BOARD( "8-in-1 JY-119", 267, Mapper267_Init ) + INES_BOARD( "COOLBOY/MINDKIDS", 268, Mapper268_Init ) /* Submapper distinguishes between COOLBOY and MINDKIDS */ + INES_BOARD( "Games Xplosion 121-in-1", 269, Mapper269_Init ) + INES_BOARD( "MGC-026", 271, Mapper271_Init ) + INES_BOARD( "Akumajō Special: Boku Dracula-kun", 272, Mapper272_Init ) + INES_BOARD( "80013-B", 274, Mapper274_Init ) + INES_BOARD( "", 277, Mapper277_Init ) + INES_BOARD( "YY860417C", 281, Mapper281_Init ) + INES_BOARD( "860224C", 282, Mapper282_Init ) + INES_BOARD( "GS-2004/GS-2013", 283, Mapper283_Init ) + INES_BOARD( "DripGame", 284, Mapper284_Init ) + INES_BOARD( "A65AS", 285, Mapper285_Init ) + INES_BOARD( "BS-5", 286, Mapper286_Init ) + INES_BOARD( "411120-C, 811120-C", 287, Mapper287_Init ) + INES_BOARD( "GKCX1", 288, Mapper288_Init ) + INES_BOARD( "60311C", 289, Mapper289_Init ) + INES_BOARD( "NTD-03", 290, Mapper290_Init ) + INES_BOARD( "Kasheng 2-in-1 ", 291, Mapper291_Init ) + INES_BOARD( "BMW8544", 292, Mapper292_Init ) + INES_BOARD( "NewStar 12-in-1/7-in-1", 293, Mapper293_Init ) + INES_BOARD( "63-1601 ", 294, Mapper294_Init ) + INES_BOARD( "YY860216C", 295, Mapper295_Init ) + INES_BOARD( "TXC 01-22110-000", 297, Mapper297_Init ) + INES_BOARD( "TF1201", 298, Mapper298_Init ) + INES_BOARD( "11160", 299, Mapper299_Init ) + INES_BOARD( "190in1", 300, Mapper300_Init ) + INES_BOARD( "8157", 301, Mapper301_Init ) + INES_BOARD( "KS7057", 302, Mapper302_Init ) + INES_BOARD( "KS7017", 303, Mapper303_Init ) + INES_BOARD( "SMB2J", 304, Mapper304_Init ) + INES_BOARD( "KS7031", 305, Mapper305_Init ) + INES_BOARD( "KS7016", 306, Mapper306_Init ) + INES_BOARD( "KS7037", 307, Mapper307_Init ) + INES_BOARD( "TH2131-1", 308, Mapper308_Init ) + INES_BOARD( "LH51", 309, Mapper309_Init ) + INES_BOARD( "K-1053", 310, Mapper310_Init ) + INES_BOARD( "KS7013B", 312, Mapper312_Init ) + INES_BOARD( "RESET-TXROM", 313, Mapper313_Init ) + INES_BOARD( "64in1NoRepeat", 314, Mapper314_Init ) + INES_BOARD( "830134C", 315, Mapper315_Init ) + INES_BOARD( "HP898F", 319, Mapper319_Init ) + INES_BOARD( "830425C-4391T", 320, Mapper320_Init ) + INES_BOARD( "K-3033", 322, Mapper322_Init ) + INES_BOARD( "FARID_SLROM_8-IN-1", 323, Mapper323_Init ) + INES_BOARD( "FARID_UNROM_8-IN-1", 324, Mapper324_Init ) + INES_BOARD( "MALISB", 325, Mapper325_Init ) + INES_BOARD( "Contra/Gryzor", 326, Mapper326_Init ) + INES_BOARD( "10-24-C-A1", 327, Mapper327_Init ) + INES_BOARD( "RT-01", 328, Mapper328_Init ) + INES_BOARD( "EDU2000", 329, Mapper329_Init ) + INES_BOARD( "Sangokushi II: Haō no Tairiku", 330, Mapper330_Init ) + INES_BOARD( "12-IN-1", 331, Mapper331_Init ) + INES_BOARD( "WS", 332, Mapper332_Init ) + INES_BOARD( "NEWSTAR-GRM070-8IN1", 333, Mapper333_Init ) + INES_BOARD( "821202C", 334, Mapper334_Init ) + INES_BOARD( "CTC-09", 335, Mapper335_Init ) + INES_BOARD( "K-3046", 336, Mapper336_Init ) + INES_BOARD( "CTC-12IN1", 337, Mapper337_Init ) + INES_BOARD( "SA005-A", 338, Mapper338_Init ) + INES_BOARD( "K-3006", 339, Mapper339_Init ) + INES_BOARD( "K-3036", 340, Mapper340_Init ) + INES_BOARD( "TJ-03", 341, Mapper341_Init ) + INES_BOARD( "COOLGIRL", 342, Mapper342_Init ) + INES_BOARD( "RESETNROM-XIN1", 343, Mapper343_Init ) + INES_BOARD( "GN-26", 344, Mapper344_Init ) + INES_BOARD( "L6IN1", 345, Mapper345_Init ) + INES_BOARD( "KS7012", 346, Mapper346_Init ) + INES_BOARD( "KS7030", 347, Mapper347_Init ) + INES_BOARD( "830118C", 348, Mapper348_Init ) + INES_BOARD( "G-146", 349, Mapper349_Init ) + INES_BOARD( "891227", 350, Mapper350_Init ) + INES_BOARD( "Techline XB", 351, Mapper351_Init ) + INES_BOARD( "KS106C", 352, Mapper352_Init ) + INES_BOARD( "Super Mario Family", 353, Mapper353_Init ) + INES_BOARD( "FAM250/810139C/810331C/SCHI-24", 354, Mapper354_Init ) + INES_BOARD( "3D-BLOCK", 355, Mapper355_Init ) + INES_BOARD( "7-in-1 Rockman (JY-208)", 356, Mapper356_Init ) + INES_BOARD( "Bit Corp 4-in-1", 357, Mapper357_Init ) + INES_BOARD( "YY860606C", 358, Mapper358_Init ) + INES_BOARD( "SB-5013/GCL8050/841242C", 359, Mapper359_Init ) + INES_BOARD( "Bitcorp 31-in-1", 360, Mapper360_Init ) + INES_BOARD( "YY841101C (OK-411)", 361, Mapper361_Init ) + INES_BOARD( "830506C", 362, Mapper362_Init ) + INES_BOARD( "JY830832C", 364, Mapper364_Init ) + INES_BOARD( "GN-45", 366, Mapper366_Init ) + INES_BOARD( "Yung-08", 368, Mapper368_Init ) + INES_BOARD( "N49C-300", 369, Mapper369_Init ) + INES_BOARD( "Golden Mario Party II - Around the World 6-in-1", 370, Mapper370_Init ) + INES_BOARD( "MMC3 PIRATE SFC-12", 372, Mapper372_Init ) + INES_BOARD( "95/96 Super HiK 4-in-1", 374, Mapper374_Init ) + INES_BOARD( "135-in-1", 375, Mapper375_Init ) + INES_BOARD( "YY841155C", 376, Mapper376_Init ) + INES_BOARD( "JY-111/JY-112", 377, Mapper377_Init ) + INES_BOARD( "42 to 80,000 (970630C)", 380, Mapper380_Init ) + INES_BOARD( "KN-42", 381, Mapper381_Init ) + INES_BOARD( "830928C", 382, Mapper382_Init ) + INES_BOARD( "YY840708C", 383, Mapper383_Init ) + INES_BOARD( "NTDEC 2779", 385, Mapper385_Init ) + INES_BOARD( "YY860729C", 386, Mapper386_Init ) + INES_BOARD( "YY850735C", 387, Mapper387_Init ) + INES_BOARD( "YY850835C", 388, Mapper388_Init ) + INES_BOARD( "Caltron 9-in-1", 389, Mapper389_Init ) + INES_BOARD( "Realtec 8031", 390, Mapper390_Init ) + INES_BOARD( "BS-110", 391, Mapper391_Init ) + INES_BOARD( "820720C", 393, Mapper393_Init ) + INES_BOARD( "HSK007", 394, Mapper394_Init ) + INES_BOARD( "Realtec 8210", 395, Mapper395_Init ) + INES_BOARD( "YY850437C", 396, Mapper396_Init ) + INES_BOARD( "YY850439C", 397, Mapper397_Init ) + INES_BOARD( "YY840820C", 398, Mapper398_Init ) + INES_BOARD( "Star Versus", 399, Mapper399_Init ) + INES_BOARD( "8-BIT XMAS", 400, Mapper400_Init ) + INES_BOARD( "BMC Super 19-in-1 (VIP19)",401, Mapper401_Init ) + INES_BOARD( "J-2282", 402, Mapper402_Init ) + INES_BOARD( "89433", 403, Mapper403_Init ) + INES_BOARD( "JY012005", 404, Mapper404_Init ) + INES_BOARD( "Haradius Zero", 406, Mapper406_Init ) + INES_BOARD( "retroUSB DPCMcart", 409, Mapper409_Init ) + INES_BOARD( "JY-302", 410, Mapper410_Init ) + INES_BOARD( "A88S-1", 411, Mapper411_Init ) + INES_BOARD( "Intellivision 10-in-1 PnP 2nd Ed.", 412, Mapper412_Init ) + INES_BOARD( "Super Russian Roulette", 413, Mapper413_Init ) + INES_BOARD( "9999999-in-1", 414, Mapper414_Init ) + INES_BOARD( "0353", 415, Mapper415_Init ) + INES_BOARD( "4-in-1/N-32", 416, Mapper416_Init ) + INES_BOARD( "", 417, Mapper417_Init ) + INES_BOARD( "820106-C/821007C/LH42", 418, Mapper418_Init ) + INES_BOARD( "A971210", 420, Mapper420_Init ) + INES_BOARD( "SC871115C", 421, Mapper421_Init ) + INES_BOARD( "BS-400R/BS-4040", 422, Mapper422_Init ) + INES_BOARD( "AB-G1L/WELL-NO-DG450", 428, Mapper428_Init ) + INES_BOARD( "LIKO BBG-235-8-1B", 429, Mapper429_Init ) + INES_BOARD( "831031C/T-308", 430, Mapper430_Init ) + INES_BOARD( "Realtek GN-91B", 431, Mapper431_Init ) + INES_BOARD( "Realtec 8090", 432, Mapper432_Init ) + INES_BOARD( "NC-20MB", 433, Mapper433_Init ) + INES_BOARD( "S-009", 434, Mapper434_Init ) + INES_BOARD( "F-1002", 435, Mapper435_Init ) + INES_BOARD( "820401/T-217", 436, Mapper436_Init ) + INES_BOARD( "NTDEC TH2348", 437, Mapper437_Init ) + INES_BOARD( "K-3071", 438, Mapper438_Init ) + INES_BOARD( "YS2309", 439, Mapper439_Init ) + INES_BOARD( "841026C/850335C ", 441, Mapper441_Init ) + INES_BOARD( "NC-3000M", 443, Mapper443_Init ) + INES_BOARD( "NC-7000M/NC-8000M", 444, Mapper444_Init ) + INES_BOARD( "DG574B", 445, Mapper445_Init ) + INES_BOARD( "SMD172B_FPGA", 446, Mapper446_Init ) + INES_BOARD( "KL-06 multicart", 447, Mapper447_Init ) + INES_BOARD( "830768C", 448, Mapper448_Init ) + INES_BOARD( "Super Games King", 449, Mapper449_Init ) + INES_BOARD( "YY841157C", 450, Mapper450_Init ) + INES_BOARD( "Haratyler HP/MP", 451, Mapper451_Init ) + INES_BOARD( "DS-9-27", 452, Mapper452_Init ) + INES_BOARD( "Realtec 8042", 453, Mapper453_Init ) + INES_BOARD( "100-in-1", 454, Mapper454_Init ) + INES_BOARD( "N625836", 455, Mapper455_Init ) + INES_BOARD( "K6C3001A", 456, Mapper456_Init ) + INES_BOARD( "810431C", 457, Mapper457_Init ) + INES_BOARD( "", 458, Mapper458_Init ) + INES_BOARD( "8-in-1", 459, Mapper459_Init ) + INES_BOARD( "FC-29-40/K-3101", 460, Mapper460_Init ) + INES_BOARD( "0324", 461, Mapper461_Init ) + INES_BOARD( "YH810X1", 463, Mapper463_Init ) + INES_BOARD( "NTDEC 9012", 464, Mapper464_Init ) + INES_BOARD( "ET-120", 465, Mapper465_Init ) + INES_BOARD( "Keybyte Computer", 466, Mapper466_Init ) + INES_BOARD( "47-2", 467, Mapper467_Init ) + INES_BOARD( "Impact Soft IM1", 471, Mapper471_Init ) + INES_BOARD( "Yhc-000", 500, Mapper500_Init ) + INES_BOARD( "Yhc-001", 501, Mapper501_Init ) + INES_BOARD( "Yhc-002", 502, Mapper502_Init ) + INES_BOARD( "", 512, Mapper512_Init ) + INES_BOARD( "SA-9602B", 513, Mapper513_Init ) + INES_BOARD( "Subor Karaoke", 514, Mapper514_Init ) + INES_BOARD( "Brilliant Com Cocoma Pack", 516, Mapper516_Init ) + INES_BOARD( "Kkachi-wa Nolae Chingu", 517, Mapper517_Init ) /* Korean Karaoke */ + INES_BOARD( "DANCE2000", 518, Mapper518_Init ) + INES_BOARD( "EH8813A", 519, Mapper519_Init ) + INES_BOARD( "Datach DBZ/Yu Yu Hakusho", 520, Mapper520_Init ) + INES_BOARD( "DREAMTECH01", 521, Mapper521_Init ) + INES_BOARD( "LH10", 522, Mapper522_Init ) + INES_BOARD( "Jncota KT-???", 523, Mapper523_Init ) + INES_BOARD( "900218", 524, Mapper524_Init ) + INES_BOARD( "KS7021A", 525, Mapper525_Init ) + INES_BOARD( "BJ-56", 526, Mapper526_Init ) + INES_BOARD( "AX-40G", 527, Mapper527_Init ) + INES_BOARD( "831128C", 528, Mapper528_Init ) + INES_BOARD( "YY0807/J-2148/T-230", 529, Mapper529_Init ) + INES_BOARD( "AX5705", 530, Mapper530_Init ) + INES_BOARD( "Sachen 3014", 533, Mapper533_Init ) + INES_BOARD( "NJ064", 534, Mapper534_Init ) + INES_BOARD( "LH53", 535, Mapper535_Init ) + INES_BOARD( "60-1064-16L (FDS)", 538, Mapper538_Init ) + INES_BOARD( "Kid Ikarus (FDS)", 539, Mapper539_Init ) + INES_BOARD( "82112C", 540, Mapper540_Init ) + INES_BOARD( "LittleCom 160-in-1", 541, Mapper541_Init ) + INES_BOARD( "5-in-1 (CH-501)", 543, Mapper543_Init ) + INES_BOARD( "Waixing FS306", 544, Mapper544_Init ) + INES_BOARD( "KONAMI-QTAI", 547, Mapper547_Init ) + INES_BOARD( "CTC-15", 548, Mapper548_Init ) + INES_BOARD( "KS-701B (Kaiser FDS)", 549, Mapper549_Init ) + INES_BOARD( "", 551, Mapper178_Init ) + INES_BOARD( "TAITO X1-017", 552, Mapper552_Init ) + INES_BOARD( "SACHEN 3013", 553, Mapper553_Init ) + INES_BOARD( "KS-7010", 554, Mapper554_Init ) + INES_BOARD( "JY-215", 556, Mapper556_Init ) + INES_BOARD( "JY820845C", 550, Mapper550_Init ) + INES_BOARD( "NES-EVENT2", 555, Mapper555_Init ) + INES_BOARD( "", 557, Mapper557_Init ) + INES_BOARD( "YC-03-09", 558, Mapper558_Init ) + INES_BOARD( "Subor 0102", 559, Mapper559_Init ) + INES_BOARD( "Bung Super Game Doctor 2M/4M", 561, Mapper561_Init ) + INES_BOARD( "Venus Turbo Game Doctor 4+/6+/6M", 562, Mapper562_Init ) +INES_BOARD_END() static uint32 iNES_get_mapper_id(void) { @@ -1128,6 +1615,10 @@ int iNESLoad(const char *name, FCEUFILE *fp) if (VROM_size) SetupCartCHRMapping(0, VROM, vrom_size_pow2, 0); + /* VS mapper uses 4-screen mirroring */ + if (iNESCart.mapper == 151 && iNESCart.mirror != 2) + iNESCart.mirror = 2; + if (iNESCart.mirror == 2) { ExtraNTARAM = (uint8*)FCEU_gmalloc(2048); diff --git a/src/ines.h b/src/ines.h index a5e72e932..afd9d0361 100644 --- a/src/ines.h +++ b/src/ines.h @@ -50,89 +50,102 @@ void NSFAY_Init(void); void NSFN106_Init(void); void NSFVRC7_Init(void); -void Mapper1_Init(CartInfo *); -void Mapper4_Init(CartInfo *); -void Mapper5_Init(CartInfo *); -void Mapper6_Init(CartInfo *); -void Mapper8_Init(CartInfo *); -void Mapper9_Init(CartInfo *); -void Mapper10_Init(CartInfo *); -void Mapper11_Init(CartInfo *); -void Mapper12_Init(CartInfo *); -void Mapper15_Init(CartInfo *); -void Mapper16_Init(CartInfo *); -void Mapper17_Init(CartInfo *); -void Mapper18_Init(CartInfo *); -void Mapper19_Init(CartInfo *); -void Mapper21_Init(CartInfo *); -void Mapper22_Init(CartInfo *); -void Mapper23_Init(CartInfo *); -void Mapper24_Init(CartInfo *); -void Mapper25_Init(CartInfo *); -void Mapper26_Init(CartInfo *); -void Mapper28_Init(CartInfo *); -void Mapper29_Init(CartInfo *); -void Mapper31_Init(CartInfo *); -void Mapper32_Init(CartInfo *); -void Mapper33_Init(CartInfo *); -void Mapper34_Init(CartInfo *); -void Mapper35_Init(CartInfo *); -void Mapper36_Init(CartInfo *); -void Mapper37_Init(CartInfo *); -void Mapper38_Init(CartInfo *); -void Mapper40_Init(CartInfo *); -void Mapper41_Init(CartInfo *); -void Mapper42_Init(CartInfo *); -void Mapper43_Init(CartInfo *); -void Mapper44_Init(CartInfo *); -void Mapper45_Init(CartInfo *); -void Mapper46_Init(CartInfo *); -void Mapper47_Init(CartInfo *); -void Mapper48_Init(CartInfo *); -void Mapper49_Init(CartInfo *); -void Mapper50_Init(CartInfo *); -void Mapper51_Init(CartInfo *); -void Mapper52_Init(CartInfo *); -void Mapper57_Init(CartInfo *); -void Mapper58_Init(CartInfo *); -void Mapper59_Init(CartInfo *); -void Mapper60_Init(CartInfo *); -void Mapper61_Init(CartInfo *); -void Mapper62_Init(CartInfo *); -void Mapper63_Init(CartInfo *); -void Mapper64_Init(CartInfo *); -void Mapper65_Init(CartInfo *); -void Mapper67_Init(CartInfo *); -void Mapper68_Init(CartInfo *); -void Mapper69_Init(CartInfo *); -void Mapper70_Init(CartInfo *); -void Mapper71_Init(CartInfo *); -void Mapper72_Init(CartInfo *); -void Mapper73_Init(CartInfo *); -void Mapper74_Init(CartInfo *); -void Mapper75_Init(CartInfo *); -void Mapper76_Init(CartInfo *); -void Mapper77_Init(CartInfo *); -void Mapper78_Init(CartInfo *); -void Mapper79_Init(CartInfo *); -void Mapper80_Init(CartInfo *); -void Mapper81_Init(CartInfo *); -void Mapper82_Init(CartInfo *); -void Mapper83_Init(CartInfo *); -void Mapper85_Init(CartInfo *); -void Mapper86_Init(CartInfo *); -void Mapper87_Init(CartInfo *); -void Mapper88_Init(CartInfo *); -void Mapper89_Init(CartInfo *); -void Mapper90_Init(CartInfo *); -void Mapper91_Init(CartInfo *); -void Mapper92_Init(CartInfo *); -void Mapper93_Init(CartInfo *); -void Mapper94_Init(CartInfo *); -void Mapper95_Init(CartInfo *); -void Mapper96_Init(CartInfo *); -void Mapper97_Init(CartInfo *); -void Mapper99_Init(CartInfo *); +void Mapper000_Init(CartInfo *); +void Mapper001_Init(CartInfo *); +void Mapper002_Init(CartInfo *); +void Mapper003_Init(CartInfo *); +void Mapper004_Init(CartInfo *); +void Mapper005_Init(CartInfo *); +void Mapper006_Init(CartInfo *); +void Mapper007_Init(CartInfo *); +/* void Mapper008_Init(CartInfo *);*/ +void Mapper009_Init(CartInfo *); +void Mapper010_Init(CartInfo *); +void Mapper011_Init(CartInfo *); +void Mapper012_Init(CartInfo *); +void Mapper013_Init(CartInfo *); +void Mapper014_Init(CartInfo *); +void Mapper015_Init(CartInfo *); +void Mapper016_Init(CartInfo *); +/* void Mapper017_Init(CartInfo *); */ +void Mapper018_Init(CartInfo *); +void Mapper019_Init(CartInfo *); +void Mapper021_Init(CartInfo *); +void Mapper022_Init(CartInfo *); +void Mapper023_Init(CartInfo *); +void Mapper024_Init(CartInfo *); +void Mapper025_Init(CartInfo *); +void Mapper026_Init(CartInfo *); +void Mapper027_Init(CartInfo *); +void Mapper028_Init(CartInfo *); +void Mapper029_Init(CartInfo *); +void Mapper030_Init(CartInfo *); +void Mapper031_Init(CartInfo *); +void Mapper032_Init(CartInfo *); +void Mapper033_Init(CartInfo *); +void Mapper034_Init(CartInfo *); +void Mapper035_Init(CartInfo *); +void Mapper036_Init(CartInfo *); +void Mapper037_Init(CartInfo *); +void Mapper038_Init(CartInfo *); +void Mapper040_Init(CartInfo *); +void Mapper041_Init(CartInfo *); +void Mapper042_Init(CartInfo *); +void Mapper043_Init(CartInfo *); +void Mapper044_Init(CartInfo *); +void Mapper045_Init(CartInfo *); +void Mapper046_Init(CartInfo *); +void Mapper047_Init(CartInfo *); +void Mapper048_Init(CartInfo *); +void Mapper049_Init(CartInfo *); +void Mapper050_Init(CartInfo *); +void Mapper051_Init(CartInfo *); +void Mapper052_Init(CartInfo *); +void Mapper053_Init(CartInfo *); +void Mapper055_Init(CartInfo *); +void Mapper056_Init(CartInfo *); +void Mapper057_Init(CartInfo *); +void Mapper058_Init(CartInfo *); +void Mapper059_Init(CartInfo *); +void Mapper060_Init(CartInfo *); +void Mapper061_Init(CartInfo *); +void Mapper062_Init(CartInfo *); +void Mapper063_Init(CartInfo *); +void Mapper064_Init(CartInfo *); +void Mapper065_Init(CartInfo *); +void Mapper066_Init(CartInfo *); +void Mapper067_Init(CartInfo *); +void Mapper068_Init(CartInfo *); +void Mapper069_Init(CartInfo *); +void Mapper070_Init(CartInfo *); +void Mapper071_Init(CartInfo *); +void Mapper072_Init(CartInfo *); +void Mapper073_Init(CartInfo *); +void Mapper074_Init(CartInfo *); +void Mapper075_Init(CartInfo *); +void Mapper076_Init(CartInfo *); +void Mapper077_Init(CartInfo *); +void Mapper078_Init(CartInfo *); +void Mapper079_Init(CartInfo *); +void Mapper080_Init(CartInfo *); +void Mapper081_Init(CartInfo *); +void Mapper082_Init(CartInfo *); +void Mapper083_Init(CartInfo *); +void Mapper085_Init(CartInfo *); +void Mapper086_Init(CartInfo *); +void Mapper087_Init(CartInfo *); +void Mapper088_Init(CartInfo *); +void Mapper089_Init(CartInfo *); +void Mapper090_Init(CartInfo *); +void Mapper091_Init(CartInfo *); +/* void Mapper092_Init(CartInfo *); */ +void Mapper093_Init(CartInfo *); +void Mapper094_Init(CartInfo *); +void Mapper095_Init(CartInfo *); +void Mapper096_Init(CartInfo *); +void Mapper097_Init(CartInfo *); +void Mapper099_Init(CartInfo *); +void Mapper100_Init(CartInfo *); void Mapper101_Init(CartInfo *); void Mapper103_Init(CartInfo *); void Mapper104_Init(CartInfo *); @@ -147,18 +160,33 @@ void Mapper114_Init(CartInfo *); void Mapper115_Init(CartInfo *); void Mapper116_Init(CartInfo *); void Mapper117_Init(CartInfo *); +void Mapper118_Init(CartInfo *); void Mapper119_Init(CartInfo *); void Mapper120_Init(CartInfo *); void Mapper121_Init(CartInfo *); +void Mapper123_Init(CartInfo *); +void Mapper124_Init(CartInfo *); void Mapper125_Init(CartInfo *); void Mapper126_Init(CartInfo *); +void Mapper127_Init(CartInfo *); void Mapper128_Init(CartInfo *); void Mapper132_Init(CartInfo *); +void Mapper133_Init(CartInfo *); void Mapper134_Init(CartInfo *); void Mapper136_Init(CartInfo *); +void Mapper137_Init(CartInfo *); +void Mapper138_Init(CartInfo *); +void Mapper139_Init(CartInfo *); void Mapper140_Init(CartInfo *); +void Mapper141_Init(CartInfo *); +void Mapper142_Init(CartInfo *); +void Mapper143_Init(CartInfo *); void Mapper144_Init(CartInfo *); +void Mapper145_Init(CartInfo *); void Mapper147_Init(CartInfo *); +void Mapper148_Init(CartInfo *); +void Mapper149_Init(CartInfo *); +void Mapper150_Init(CartInfo *); void Mapper151_Init(CartInfo *); void Mapper152_Init(CartInfo *); void Mapper153_Init(CartInfo *); @@ -166,7 +194,6 @@ void Mapper154_Init(CartInfo *); void Mapper155_Init(CartInfo *); void Mapper156_Init(CartInfo *); void Mapper157_Init(CartInfo *); -void Mapper158_Init(CartInfo *); void Mapper159_Init(CartInfo *); void Mapper162_Init(CartInfo *); void Mapper163_Init(CartInfo *); @@ -176,7 +203,7 @@ void Mapper166_Init(CartInfo *); void Mapper167_Init(CartInfo *); void Mapper168_Init(CartInfo *); void Mapper170_Init(CartInfo *); -void Mapper171_Init(CartInfo *); +void Mapper171_Init(CartInfo *); /* Kaiser 7058 */ void Mapper172_Init(CartInfo *); void Mapper173_Init(CartInfo *); void Mapper174_Init(CartInfo *); @@ -185,7 +212,6 @@ void Mapper176_Init(CartInfo *); void Mapper177_Init(CartInfo *); void Mapper178_Init(CartInfo *); void Mapper180_Init(CartInfo *); -void Mapper181_Init(CartInfo *); void Mapper183_Init(CartInfo *); void Mapper184_Init(CartInfo *); void Mapper185_Init(CartInfo *); @@ -193,6 +219,7 @@ void Mapper186_Init(CartInfo *); void Mapper187_Init(CartInfo *); void Mapper188_Init(CartInfo *); void Mapper189_Init(CartInfo *); +void Mapper190_Init(CartInfo *); void Mapper191_Init(CartInfo *); void Mapper192_Init(CartInfo *); void Mapper193_Init(CartInfo *); @@ -217,10 +244,13 @@ void Mapper211_Init(CartInfo *); void Mapper212_Init(CartInfo *); void Mapper213_Init(CartInfo *); void Mapper214_Init(CartInfo *); +void Mapper215_Init(CartInfo *); void Mapper216_Init(CartInfo *); void Mapper217_Init(CartInfo *); void Mapper218_Init(CartInfo *); +void Mapper219_Init(CartInfo *); void Mapper220_Init(CartInfo *); +void Mapper221_Init(CartInfo *); void Mapper222_Init(CartInfo *); void Mapper224_Init(CartInfo *); void Mapper225_Init(CartInfo *); @@ -236,6 +266,7 @@ void Mapper234_Init(CartInfo *); void Mapper235_Init(CartInfo *); void Mapper236_Init(CartInfo *); void Mapper237_Init(CartInfo *); +void Mapper238_Init(CartInfo *); void Mapper240_Init(CartInfo *); void Mapper241_Init(CartInfo *); void Mapper242_Init(CartInfo *); @@ -248,42 +279,101 @@ void Mapper252_Init(CartInfo *); void Mapper253_Init(CartInfo *); void Mapper254_Init(CartInfo *); void Mapper255_Init(CartInfo *); - -void GN45_Init(CartInfo *info); /* m361, m366 */ -void Mapper272_Init(CartInfo *); -void Mapper277_Init(CartInfo *); -void Mapper281_Init(CartInfo *); -void Mapper282_Init(CartInfo *); -void Mapper283_Init(CartInfo *); -void Mapper291_Init(CartInfo *); -void Mapper295_Init(CartInfo *); - -void J2282_Init(CartInfo *); - +void Mapper256_Init(CartInfo *); +void Mapper257_Init(CartInfo *); +void Mapper259_Init(CartInfo *); +void Mapper260_Init(CartInfo *); +void Mapper261_Init(CartInfo *); +void Mapper262_Init(CartInfo *); +void Mapper263_Init(CartInfo *); +void Mapper264_Init(CartInfo *); void Mapper265_Init(CartInfo *); +void Mapper266_Init(CartInfo *); void Mapper267_Init(CartInfo *); void Mapper268_Init(CartInfo *); void Mapper269_Init(CartInfo *); void Mapper271_Init(CartInfo *); +void Mapper272_Init(CartInfo *); +void Mapper274_Init(CartInfo *); +void Mapper277_Init(CartInfo *); +void Mapper281_Init(CartInfo *); +void Mapper282_Init(CartInfo *); +void Mapper283_Init(CartInfo *); +void Mapper284_Init(CartInfo *); +void Mapper285_Init(CartInfo *); +void Mapper286_Init(CartInfo *); +void Mapper287_Init(CartInfo *); void Mapper288_Init(CartInfo *); +void Mapper289_Init(CartInfo *); +void Mapper290_Init(CartInfo *); +void Mapper291_Init(CartInfo *); +void Mapper292_Init(CartInfo *); void Mapper293_Init(CartInfo *); void Mapper294_Init(CartInfo *); +void Mapper295_Init(CartInfo *); void Mapper297_Init(CartInfo *); +void Mapper298_Init(CartInfo *); +void Mapper299_Init(CartInfo *); +void Mapper300_Init(CartInfo *); +void Mapper301_Init(CartInfo *); +void Mapper302_Init(CartInfo *); +void Mapper303_Init(CartInfo *); +void Mapper304_Init(CartInfo *); +void Mapper305_Init(CartInfo *); +void Mapper306_Init(CartInfo *); +void Mapper307_Init(CartInfo *); +void Mapper308_Init(CartInfo *); +void Mapper309_Init(CartInfo *); void Mapper310_Init(CartInfo *); +void Mapper312_Init(CartInfo *); +void Mapper313_Init(CartInfo *); +void Mapper314_Init(CartInfo *); +void Mapper315_Init(CartInfo *); void Mapper319_Init(CartInfo *); +void Mapper320_Init(CartInfo *); +void Mapper322_Init(CartInfo *); +void Mapper323_Init(CartInfo *); +void Mapper324_Init(CartInfo *); +void Mapper325_Init(CartInfo *); void Mapper326_Init(CartInfo *); +void Mapper327_Init(CartInfo *); +void Mapper328_Init(CartInfo *); +void Mapper329_Init(CartInfo *); void Mapper330_Init(CartInfo *); +void Mapper331_Init(CartInfo *); +void Mapper332_Init(CartInfo *); +void Mapper333_Init(CartInfo *); void Mapper334_Init(CartInfo *); +void Mapper335_Init(CartInfo *); +void Mapper336_Init(CartInfo *); +void Mapper337_Init(CartInfo *); +void Mapper338_Init(CartInfo *); +void Mapper339_Init(CartInfo *); +void Mapper340_Init(CartInfo *); +void Mapper341_Init(CartInfo *); +void Mapper342_Init(CartInfo *); +void Mapper343_Init(CartInfo *); +void Mapper344_Init(CartInfo *); +void Mapper345_Init(CartInfo *); +void Mapper346_Init(CartInfo *); +void Mapper347_Init(CartInfo *); +void Mapper348_Init(CartInfo *); +void Mapper349_Init(CartInfo *); +void Mapper350_Init(CartInfo *); void Mapper351_Init(CartInfo *); +void Mapper352_Init(CartInfo *); void Mapper353_Init(CartInfo *); void Mapper354_Init(CartInfo *); +void Mapper355_Init(CartInfo *); void Mapper356_Init(CartInfo *); void Mapper357_Init(CartInfo *); void Mapper358_Init(CartInfo *); void Mapper359_Init(CartInfo *); void Mapper360_Init(CartInfo *); +void Mapper361_Init(CartInfo *); void Mapper362_Init(CartInfo *); void Mapper364_Init(CartInfo *); +void Mapper366_Init(CartInfo *); void Mapper368_Init(CartInfo *); void Mapper369_Init(CartInfo *); void Mapper370_Init(CartInfo *); @@ -309,17 +399,23 @@ void Mapper395_Init(CartInfo *); void Mapper396_Init(CartInfo *); void Mapper397_Init(CartInfo *); void Mapper398_Init(CartInfo *); +void Mapper399_Init(CartInfo *); +void Mapper400_Init(CartInfo *); void Mapper401_Init(CartInfo *); +void Mapper402_Init(CartInfo *); void Mapper403_Init(CartInfo *); void Mapper404_Init(CartInfo *); +void Mapper406_Init(CartInfo *); void Mapper409_Init(CartInfo *); void Mapper410_Init(CartInfo *); void Mapper411_Init(CartInfo *); void Mapper412_Init(CartInfo *); +void Mapper413_Init(CartInfo *); void Mapper414_Init(CartInfo *); void Mapper415_Init(CartInfo *); void Mapper416_Init(CartInfo *); void Mapper417_Init(CartInfo *); +void Mapper418_Init(CartInfo *); void Mapper420_Init(CartInfo *); void Mapper421_Init(CartInfo *); void Mapper422_Init(CartInfo *); @@ -338,8 +434,13 @@ void Mapper439_Init(CartInfo *); void Mapper441_Init(CartInfo *); void Mapper443_Init(CartInfo *); void Mapper444_Init(CartInfo *); +void Mapper445_Init(CartInfo *); +void Mapper446_Init(CartInfo *); +void Mapper447_Init(CartInfo *); void Mapper448_Init(CartInfo *); void Mapper449_Init(CartInfo *); +void Mapper450_Init(CartInfo *); +void Mapper451_Init(CartInfo *); void Mapper452_Init(CartInfo *); void Mapper453_Init(CartInfo *); void Mapper454_Init(CartInfo *); @@ -355,26 +456,50 @@ void Mapper464_Init(CartInfo *); void Mapper465_Init(CartInfo *); void Mapper466_Init(CartInfo *); void Mapper467_Init(CartInfo *); -void Mapper468_Init(CartInfo *); -void INX_007T_Init(CartInfo* info); /* Mapper 470 */ +void Mapper471_Init(CartInfo *); void Mapper500_Init(CartInfo *); void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); +void Mapper512_Init(CartInfo *); +void Mapper513_Init(CartInfo *); +void Mapper514_Init(CartInfo *); void Mapper516_Init(CartInfo *); +void Mapper517_Init(CartInfo *); +void Mapper518_Init(CartInfo *); +void Mapper519_Init(CartInfo *); +void Mapper520_Init(CartInfo *); +void Mapper521_Init(CartInfo *); +void Mapper522_Init(CartInfo *); void Mapper523_Init(CartInfo *); +void Mapper524_Init(CartInfo *); +void Mapper525_Init(CartInfo *); +void Mapper526_Init(CartInfo *); +void Mapper527_Init(CartInfo *); void Mapper528_Init(CartInfo *); +void Mapper529_Init(CartInfo *); +void Mapper530_Init(CartInfo *); void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); +void Mapper535_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); void Mapper540_Init(CartInfo *); void Mapper541_Init(CartInfo *); void Mapper543_Init(CartInfo *); +void Mapper544_Init(CartInfo *); +void Mapper547_Init(CartInfo *); +void Mapper548_Init(CartInfo *); +void Mapper549_Init(CartInfo *); void Mapper550_Init(CartInfo *); +void Mapper552_Init(CartInfo *); void Mapper553_Init(CartInfo *); void Mapper554_Init(CartInfo *); void Mapper555_Init(CartInfo *); void Mapper556_Init(CartInfo *); +void Mapper557_Init(CartInfo *); void Mapper558_Init(CartInfo *); +void Mapper559_Init(CartInfo *); +void Mapper561_Init(CartInfo *); +void Mapper562_Init(CartInfo *); #endif diff --git a/src/input.c b/src/input.c index fa52f8c0c..70d921314 100644 --- a/src/input.c +++ b/src/input.c @@ -33,6 +33,8 @@ #include "vsuni.h" #include "fds.h" +#include "cart.h" + extern INPUTC *FCEU_InitZapper(int w); extern INPUTC *FCEU_InitMouse(int w); extern INPUTC *FCEU_InitPowerpadA(int w); @@ -220,7 +222,7 @@ void FCEU_UpdateInput(void) if (FCExp && FCExp->Update) FCExp->Update(InputDataPtrFC, JPAttribFC); - if (GameInfo && GameInfo->type == GIT_VSUNI) + if (GameInfo && GameInfo->type == GIT_VSUNI || iNESCart.mapper == 124) if (coinon) coinon--; if (GameInfo->type == GIT_VSUNI) diff --git a/src/mappers/hw/bandai.c b/src/mappers/hw/bandai.c new file mode 100644 index 000000000..687abd5cc --- /dev/null +++ b/src/mappers/hw/bandai.c @@ -0,0 +1,231 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2011 FCEUX team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * INES Mapper 016 + * iNES Mapper 016 is used for some of the Bandai FCG boards, namely, boards with + * the FCG-1 ASIC that supports no EEPROM, and the LZ93D50 ASIC with no or 256 bytes of EEPROM. + * + * INES Mapper 016 submapper table + * Submapper # Meaning Note + * 0 Unspecified Emulate both FCG-1/2 and LZ93D50 chips in their respective CPU address ranges. + * 1 LZ93D50 with 128 byte serial EEPROM (24C01) Deprecated, use INES Mapper 159 instead. + * 2 Datach Joint ROM System Deprecated, use INES Mapper 157 instead. + * 3 8 KiB of WRAM instead of serial EEPROM Deprecated, use INES Mapper 153 instead. + * 4 FCG-1/2 Responds only in the CPU $6000-$7FFF address range; IRQ counter is not latched. + * 5 LZ93D50 with no or 256-byte serial EEPROM (24C02) Responds only in the CPU $8000-$FFFF address range; IRQ counter is latched. + * + */ + +#include "mapinc.h" +#include "eeprom_x24c0x.h" +#include "bandai.h" + +EEPROM_TYPE eeprom_type = EEPROM_NONE; + +static uint8 prg; +static uint8 chr[8]; +static uint8 mirr; +static uint8 IRQa; +static int16 IRQCount, IRQLatch; + +static uint8 isFCG12 = 0; + +static uint8 eeprom[256]; + +void (*BANDAI_pwrap)(uint16 A, uint16 V); +void (*BANDAI_cwrap)(uint16 A, uint16 V); + +static SFORMAT StateRegs[] = +{ + { chr, 8, "CRGS" }, + { &prg, 1, "PREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, /* need for Famicom Jump II - Saikyou no 7 Nin (J) [!] */ + { 0 } +}; + +static void GENPWRAP(uint16 A, uint16 V) { + setprg16(A, V & 0x0F); +} + +static void GENCWRAP(uint16 A, uint16 V) { + setchr1(A, V); +} + +void BANDAI_FixPRG(void) { + BANDAI_pwrap(0x8000, prg); + BANDAI_pwrap(0xC000, ~0); +} + +void BANDAI_FixCHR(void) { + BANDAI_cwrap(0x0000, chr[0]); + BANDAI_cwrap(0x0400, chr[1]); + BANDAI_cwrap(0x0800, chr[2]); + BANDAI_cwrap(0x0C00, chr[3]); + BANDAI_cwrap(0x1000, chr[4]); + BANDAI_cwrap(0x1400, chr[5]); + BANDAI_cwrap(0x1800, chr[6]); + BANDAI_cwrap(0x1C00, chr[7]); +} + +void BANDAI_FixMIR(void) { + switch (mirr & 0x03) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +static DECLFR(BANDAI_Read) { + if (eeprom_type == EEPROM_X24C01) { + return (CPU_OPENBUS & ~0x010) | (x24c01_read() << 4); + } + return (CPU_OPENBUS & ~0x010) | (x24c02_read() << 4); +} + +DECLFW(BANDAI_Write) { + switch (A & 0x0F) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + chr[A & 0x07] = V; + BANDAI_FixCHR(); + break; + case 0x08: + prg = V; + BANDAI_FixPRG(); + break; + case 0x09: + mirr = V; + BANDAI_FixMIR(); + break; + case 0x0A: + IRQa = V & 1; + IRQCount = IRQLatch; + if (IRQa && !IRQLatch) { + X6502_IRQBegin(FCEU_IQEXT); + } else { + X6502_IRQEnd(FCEU_IQEXT); + } + break; + case 0x0B: + IRQLatch &= 0xFF00; + IRQLatch |= V; + break; + case 0x0C: + IRQLatch &= 0x00FF; + IRQLatch |= V << 8; + break; + case 0x0D: + if (eeprom_type == EEPROM_X24C02) { + x24c02_write(V); + } else if (eeprom_type == EEPROM_X24C01) { + x24c01_write(V); + } + break; + } +} + +void BANDAI_IRQHook(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount < 0) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +void BANDAI_Reset(void) { + int x; + + prg = 0x00; + for (x = 0; x < 8; x++) { + chr[x] = x; + } + IRQCount = 0; + IRQLatch = 0; + IRQa = FALSE; + + BANDAI_FixPRG(); + BANDAI_FixCHR(); + BANDAI_FixMIR(); +} + +static void StateRestore(int version) { + BANDAI_FixPRG(); + BANDAI_FixCHR(); + BANDAI_FixMIR(); +} + +void BANDAI_Power(void) { + BANDAI_Reset(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, BANDAI_Write); + if (isFCG12) { + /* submapper 4 */ + SetWriteHandler(0x6000, 0x7FFF, BANDAI_Write); + } + + if (eeprom_type != EEPROM_NONE) { + SetReadHandler(0x6000, 0x7FFF, BANDAI_Read); + if (eeprom_type == EEPROM_X24C02) { + x24c02_init(eeprom); + } else if (eeprom_type == EEPROM_X24C01) { + x24c01_init(eeprom); + } + } +} + +void BANDAI_Init(CartInfo *info, EEPROM_TYPE _eeprom_type, int _isFCG) { + BANDAI_pwrap = GENPWRAP; + BANDAI_cwrap = GENCWRAP; + + eeprom_type = _eeprom_type; + isFCG12 = _isFCG; + + info->Power = BANDAI_Power; + MapIRQHook = BANDAI_IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + if (eeprom_type != EEPROM_NONE) { + info->battery = 1; + memset(eeprom, 0, sizeof(eeprom)); + if (eeprom_type == EEPROM_X24C02) { + info->SaveGame[0] = eeprom; + info->SaveGameLen[0] = 256; + AddExState(&x24c02_StateRegs, ~0, 0, 0); + } else if (eeprom_type == EEPROM_X24C01) { + info->SaveGame[0] = eeprom; + info->SaveGameLen[0] = 128; + AddExState(&x24c01_StateRegs, ~0, 0, 0); + } + } +} diff --git a/src/mappers/hw/bandai.h b/src/mappers/hw/bandai.h new file mode 100644 index 000000000..10bec3f96 --- /dev/null +++ b/src/mappers/hw/bandai.h @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BANDAI_H +#define _BANDAI_H + +DECLFW(BANDAI_Write); + +void BANDAI_Power(void); +void BANDAI_IRQHook(int a); +void BANDAI_Reset(void); + +void BANDAI_Init(CartInfo *info, EEPROM_TYPE _eeprom_type, int _isFCG); + +void BANDAI_FixPRG(void); +void BANDAI_FixCHR(void); +void BANDAI_FixMIR(void); + +extern void (*BANDAI_pwrap)(uint16 A, uint16 V); +extern void (*BANDAI_cwrap)(uint16 A, uint16 V); + +#endif /* _BANDAI_H */ diff --git a/src/mappers/hw/eeprom_93Cx6.c b/src/mappers/hw/eeprom_93Cx6.c new file mode 100644 index 000000000..85f01a5ce --- /dev/null +++ b/src/mappers/hw/eeprom_93Cx6.c @@ -0,0 +1,173 @@ +#include "mapinc.h" +#include "eeprom_93Cx6.h" + +struct EEPROM_93Cx6 { + uint8 *storage; + uint8 opcode; + uint16 data; + uint16 address; + uint8 state; + uint8 lastCLK; + uint8 writeEnabled; + uint8 output; + uint8 capacity; + uint8 wordsize; + uint8 state_address; + uint8 state_data; +} EEPROM_93Cx6; + +#define OPCODE_MISC 0 +#define OPCODE_WRITE 1 +#define OPCODE_READ 2 +#define OPCODE_ERASE 3 +#define OPCODE_WRITEDISABLE 10 +#define OPCODE_WRITEALL 11 +#define OPCODE_ERASEALL 12 +#define OPCODE_WRITEENABLE 13 + +#define STATE_STANDBY 0 +#define STATE_STARTBIT 1 +#define STATE_OPCODE 3 +#define STATE_ADDRESS8 12 +#define STATE_DATA8 20 +#define STATE_ADDRESS16 11 +#define STATE_DATA16 27 +#define STATE_FINISHED 99 + +static struct EEPROM_93Cx6 eeprom_93Cx6 = { 0 }; + +void eeprom_93Cx6_init(uint8 *data, uint32 capacity, uint8 wordsize) { + eeprom_93Cx6.storage = data; + eeprom_93Cx6.address = 0; + eeprom_93Cx6.state = STATE_STANDBY; + eeprom_93Cx6.lastCLK = FALSE; + eeprom_93Cx6.writeEnabled = FALSE; + eeprom_93Cx6.capacity = capacity; + eeprom_93Cx6.wordsize = wordsize; + + eeprom_93Cx6.state_address = (wordsize == 16) ? STATE_ADDRESS16 : STATE_ADDRESS8; + eeprom_93Cx6.state_data = (wordsize == 16) ? STATE_DATA16 : STATE_DATA8; +} + +uint8 eeprom_93Cx6_read(void) { + return eeprom_93Cx6.output; +} + +void eeprom_93Cx6_write(uint8 CS, uint8 CLK, uint8 DAT) { + if (!CS && (eeprom_93Cx6.state <= eeprom_93Cx6.state_address)) { + eeprom_93Cx6.state = STATE_STANDBY; + } else if ((eeprom_93Cx6.state == STATE_STANDBY) && CS && CLK && !eeprom_93Cx6.lastCLK) { + eeprom_93Cx6.state = STATE_STARTBIT; + eeprom_93Cx6.opcode = 0; + eeprom_93Cx6.address = 0; + eeprom_93Cx6.output = TRUE; + } else if (CLK && !eeprom_93Cx6.lastCLK) { + if ((eeprom_93Cx6.state >= STATE_STARTBIT) && (eeprom_93Cx6.state < STATE_OPCODE)) { + eeprom_93Cx6.opcode = (eeprom_93Cx6.opcode << 1) | (DAT ? 1 : 0); + } else if ((eeprom_93Cx6.state >= STATE_OPCODE) && (eeprom_93Cx6.state < eeprom_93Cx6.state_address)) { + eeprom_93Cx6.address = (eeprom_93Cx6.address << 1) | (DAT ? 1 : 0); + } else if ((eeprom_93Cx6.state >= eeprom_93Cx6.state_address) && (eeprom_93Cx6.state < eeprom_93Cx6.state_data)) { + if ((eeprom_93Cx6.opcode == OPCODE_WRITE) || (eeprom_93Cx6.opcode == OPCODE_WRITEALL)) { + eeprom_93Cx6.data = (eeprom_93Cx6.data << 1) | (DAT ? 1 : 0); + } else if (eeprom_93Cx6.opcode == OPCODE_READ) { + if (eeprom_93Cx6.wordsize == 16) { + eeprom_93Cx6.output = (eeprom_93Cx6.data & 0x8000) != 0; + } else { + eeprom_93Cx6.output = (eeprom_93Cx6.data & 0x80) != 0; + } + eeprom_93Cx6.data = eeprom_93Cx6.data << 1; + } + } + + eeprom_93Cx6.state++; + if (eeprom_93Cx6.state == eeprom_93Cx6.state_address) { + switch (eeprom_93Cx6.opcode) { + case OPCODE_MISC: + if (eeprom_93Cx6.wordsize == 16) { + eeprom_93Cx6.opcode = (eeprom_93Cx6.address >> 6) + 10; + } else { + eeprom_93Cx6.opcode = (eeprom_93Cx6.address >> 7) + 10; + } + switch (eeprom_93Cx6.opcode) { + case OPCODE_WRITEDISABLE: + eeprom_93Cx6.writeEnabled = FALSE; + eeprom_93Cx6.state = STATE_FINISHED; + break; + case OPCODE_WRITEENABLE: + eeprom_93Cx6.writeEnabled = TRUE; + eeprom_93Cx6.state = STATE_FINISHED; + break; + case OPCODE_ERASEALL: + if (eeprom_93Cx6.writeEnabled) { + int i; + + for (i = 0; i < eeprom_93Cx6.capacity; i++) { + eeprom_93Cx6.storage[i] = 0xFF; + } + } + eeprom_93Cx6.state = STATE_FINISHED; + break; + case OPCODE_WRITEALL: + eeprom_93Cx6.address = 0; + break; + } + break; + case OPCODE_ERASE: + if (eeprom_93Cx6.writeEnabled) { + if (eeprom_93Cx6.wordsize == 16) { + eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0] = 0xFF; + eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] = 0xFF; + } else { + eeprom_93Cx6.storage[eeprom_93Cx6.address] = 0xFF; + } + } + eeprom_93Cx6.state = STATE_FINISHED; + break; + case OPCODE_READ: + if (eeprom_93Cx6.wordsize == 16) { + eeprom_93Cx6.data = eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0]; + eeprom_93Cx6.data |= (eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] << 8); + eeprom_93Cx6.address++; + } else { + eeprom_93Cx6.data = eeprom_93Cx6.storage[eeprom_93Cx6.address++]; + } + break; + } + } else if (eeprom_93Cx6.state == eeprom_93Cx6.state_data) { + if (eeprom_93Cx6.opcode == OPCODE_WRITE) { + if (eeprom_93Cx6.wordsize == 16) { + eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0] = eeprom_93Cx6.data & 0xFF; + eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] = eeprom_93Cx6.data >> 8; + eeprom_93Cx6.address++; + } else { + eeprom_93Cx6.storage[eeprom_93Cx6.address++] = eeprom_93Cx6.data; + } + eeprom_93Cx6.state = STATE_FINISHED; + } else if (eeprom_93Cx6.opcode == OPCODE_WRITEALL) { + if (eeprom_93Cx6.wordsize == 16) { + eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0] = eeprom_93Cx6.data & 0xFF; + eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] = eeprom_93Cx6.data >> 8; + eeprom_93Cx6.address++; + } else { + eeprom_93Cx6.storage[eeprom_93Cx6.address++] = eeprom_93Cx6.data; + } + eeprom_93Cx6.state = (CS && (eeprom_93Cx6.address < eeprom_93Cx6.capacity)) ? eeprom_93Cx6.state_address : STATE_FINISHED; + } else if (eeprom_93Cx6.opcode == OPCODE_READ) { + if (eeprom_93Cx6.address < eeprom_93Cx6.capacity) { + if (eeprom_93Cx6.wordsize == 16) { + eeprom_93Cx6.data = eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0]; + eeprom_93Cx6.data |= (eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] << 8); + } else { + eeprom_93Cx6.data = eeprom_93Cx6.storage[eeprom_93Cx6.address]; + } + } + eeprom_93Cx6.state = (CS && (++eeprom_93Cx6.address <= eeprom_93Cx6.capacity)) ? eeprom_93Cx6.state_address : STATE_FINISHED; + } + } + if (eeprom_93Cx6.state == STATE_FINISHED) { + eeprom_93Cx6.output = FALSE; + eeprom_93Cx6.state = STATE_STANDBY; + } + } + eeprom_93Cx6.lastCLK = CLK; +} diff --git a/src/mappers/hw/eeprom_93Cx6.h b/src/mappers/hw/eeprom_93Cx6.h new file mode 100644 index 000000000..439f4d025 --- /dev/null +++ b/src/mappers/hw/eeprom_93Cx6.h @@ -0,0 +1,28 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _EEPROM_93Cx6_H +#define _EEPROM_93Cx6_H + +void eeprom_93Cx6_init (uint8 *data, uint32 capacity, uint8 wordsize); +uint8 eeprom_93Cx6_read (void); +void eeprom_93Cx6_write (uint8 CS, uint8 CLK, uint8 DAT); + +#endif diff --git a/src/mappers/hw/eeprom_x24c0x.c b/src/mappers/hw/eeprom_x24c0x.c new file mode 100644 index 000000000..e0cf591a5 --- /dev/null +++ b/src/mappers/hw/eeprom_x24c0x.c @@ -0,0 +1,251 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2011 FCEUX team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* x24C0x interface */ + +#include "mapinc.h" +#include "eeprom_x24c0x.h" + +#define X24C0X_STANDBY 0 +#define X24C0X_ADDRESS 1 +#define X24C0X_WORD 2 +#define X24C0X_READ 3 +#define X24C0X_WRITE 4 + +struct X24C0XP { + uint8 *data; + uint8 state; + uint8 addr; + uint8 word; + uint8 latch; + uint8 bitcount; + uint8 sda; + uint8 scl; + uint8 out; +} X24C0XP; + +static struct X24C0XP x24c01; +static struct X24C0XP x24c02; + +SFORMAT x24c01_StateRegs[] = { + { &x24c01.addr, 1, "ADDR" }, + { &x24c01.word, 1, "WORD" }, + { &x24c01.latch, 1, "LATC" }, + { &x24c01.bitcount, 1, "BITC" }, + { &x24c01.sda, 1, "SDA" }, + { &x24c01.scl, 1, "SCL" }, + { &x24c01.out, 1, "OUT" }, + { &x24c01.state, 1, "STAT" }, + { 0 } +}; + +SFORMAT x24c02_StateRegs[] = { + { &x24c02.addr, 1, "ADDR" }, + { &x24c02.word, 1, "WORD" }, + { &x24c02.latch, 1, "LATC" }, + { &x24c02.bitcount, 1, "BITC" }, + { &x24c02.sda, 1, "SDA" }, + { &x24c02.scl, 1, "SCL" }, + { &x24c02.out, 1, "OUT" }, + { &x24c02.state, 1, "STAT" }, + { 0 }, +}; + +void x24c01_init(uint8 *data) { + x24c01.data = data; + x24c01.addr = 0; + x24c01.word = 0; + x24c01.latch = 0; + x24c01.bitcount = 0; + x24c01.sda = 0; + x24c01.scl = 0; + x24c01.state = X24C0X_STANDBY; +} + +void x24c02_init(uint8 *data) { + x24c02.data = data; + x24c02.addr = 0; + x24c02.word = 0; + x24c02.latch = 0; + x24c02.bitcount = 0; + x24c02.sda = 0; + x24c02.scl = 0; + x24c02.state = X24C0X_STANDBY; +} + +uint8 x24c01_read(void) { + return x24c01.out; +} + +void x24c01_write(uint8 V) { + uint8 scl = (V >> 5) & 1; + uint8 sda = (V >> 6) & 1; + + if (x24c01.scl && scl) { + if (x24c01.sda && !sda) { /* START */ + x24c01.state = X24C0X_ADDRESS; + x24c01.bitcount = 0; + x24c01.addr = 0; + } else if (!x24c01.sda && sda) { /* STOP */ + x24c01.state = X24C0X_STANDBY; + } + } else if (!x24c01.scl && scl) { /* RISING EDGE */ + switch (x24c01.state) { + case X24C0X_ADDRESS: + if (x24c01.bitcount < 7) { + x24c01.addr <<= 1; + x24c01.addr |= sda; + } else { + x24c01.word = x24c01.addr; + if (sda) { /* READ COMMAND */ + x24c01.state = X24C0X_READ; + } else { /* WRITE COMMAND */ + x24c01.state = X24C0X_WRITE; + } + } + x24c01.bitcount++; + break; + case X24C0X_READ: + if (x24c01.bitcount == 8) { /* ACK */ + x24c01.out = 0; + x24c01.latch = x24c01.data[x24c01.word]; + x24c01.bitcount = 0; + } else { /* REAL OUTPUT */ + x24c01.out = x24c01.latch >> 7; + x24c01.latch <<= 1; + x24c01.bitcount++; + if (x24c01.bitcount == 8) { + x24c01.word++; + x24c01.word &= 0xff; + } + } + break; + case X24C0X_WRITE: + if (x24c01.bitcount == 8) { /* ACK */ + x24c01.out = 0; + x24c01.latch = 0; + x24c01.bitcount = 0; + } else { /* REAL INPUT */ + x24c01.latch <<= 1; + x24c01.latch |= sda; + x24c01.bitcount++; + if (x24c01.bitcount == 8) { + x24c01.data[x24c01.word] = x24c01.latch; + x24c01.word++; + x24c01.word &= 0xff; + } + } + break; + } + } + + x24c01.sda = sda; + x24c01.scl = scl; +} + +uint8 x24c02_read(void) { + return x24c02.out; +} + +void x24c02_write(uint8 V) { + uint8 scl = (V >> 5) & 1; + uint8 sda = (V >> 6) & 1; + + if (x24c02.scl && scl) { + if (x24c02.sda && !sda) { /* START */ + x24c02.state = X24C0X_ADDRESS; + x24c02.bitcount = 0; + x24c02.addr = 0; + } else if (!x24c02.sda && sda) { /* STOP */ + x24c02.state = X24C0X_STANDBY; + } + } else if (!x24c02.scl && scl) { /* RISING EDGE */ + switch (x24c02.state) { + case X24C0X_ADDRESS: + if (x24c02.bitcount < 7) { + x24c02.addr <<= 1; + x24c02.addr |= sda; + } else { + if ((x24c02.addr & 0x78) == 0x50) { + if (sda) { /* READ COMMAND */ + x24c02.state = X24C0X_READ; + } else { /* WRITE COMMAND */ + x24c02.state = X24C0X_WORD; + } + } else { /* invalid device address */ + x24c02.state = X24C0X_STANDBY; + x24c02.out = 1; + } + } + x24c02.bitcount++; + break; + case X24C0X_WORD: + if (x24c02.bitcount == 8) { /* ACK */ + x24c02.word = 0; + x24c02.out = 0; + } else { /* WORD ADDRESS INPUT */ + x24c02.word <<= 1; + x24c02.word |= sda; + if (x24c02.bitcount == 16) { /* END OF ADDRESS INPUT */ + x24c02.bitcount = 7; + x24c02.state = X24C0X_WRITE; + } + } + x24c02.bitcount++; + break; + case X24C0X_READ: + if (x24c02.bitcount == 8) { /* ACK */ + x24c02.out = 0; + x24c02.latch = x24c02.data[x24c02.word]; + x24c02.bitcount = 0; + } else { /* REAL OUTPUT */ + x24c02.out = x24c02.latch >> 7; + x24c02.latch <<= 1; + x24c02.bitcount++; + if (x24c02.bitcount == 8) { + x24c02.word++; + x24c02.word &= 0xff; + } + } + break; + case X24C0X_WRITE: + if (x24c02.bitcount == 8) { /* ACK */ + x24c02.out = 0; + x24c02.latch = 0; + x24c02.bitcount = 0; + } else { /* REAL INPUT */ + x24c02.latch <<= 1; + x24c02.latch |= sda; + x24c02.bitcount++; + if (x24c02.bitcount == 8) { + x24c02.data[x24c02.word] = x24c02.latch; + x24c02.word++; + x24c02.word &= 0xff; + } + } + break; + } + } + + x24c02.sda = sda; + x24c02.scl = scl; +} diff --git a/src/mappers/hw/eeprom_x24c0x.h b/src/mappers/hw/eeprom_x24c0x.h new file mode 100644 index 000000000..4567e208e --- /dev/null +++ b/src/mappers/hw/eeprom_x24c0x.h @@ -0,0 +1,40 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _EEPROM_X24C0X_H +#define _EEPROM_X24C0X_H + +typedef enum { + EEPROM_NONE = 0, + EEPROM_X24C01, + EEPROM_X24C02 +} EEPROM_TYPE; + +void x24c01_init(uint8 *data); +void x24c01_write(uint8 V); +uint8 x24c01_read(void); +extern SFORMAT x24c01_StateRegs[9]; + +void x24c02_init(uint8 *data); +void x24c02_write(uint8 V); +uint8 x24c02_read(void); +extern SFORMAT x24c02_StateRegs[9]; + +#endif /* _EEPROM_X24C0X_H */ diff --git a/src/mappers/hw/flashrom.c b/src/mappers/hw/flashrom.c new file mode 100644 index 000000000..b9a00c963 --- /dev/null +++ b/src/mappers/hw/flashrom.c @@ -0,0 +1,135 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "flashrom.h" + +static uint8 *flash_data; +static uint32 flash_size; + +static uint8 flash_id[2]; +static uint8 flash_state; +static uint32 flash_addr1; +static uint32 flash_addr2; +static uint32 flash_sect_size; +static int32 time_out; + +static SFORMAT FlashStateRegs[] = { + { &flash_state, 1, "STAT" }, + { &time_out, 4, "TIME" }, + { 0 } +}; + +#define PRG_OFFSET(A) (&Page[(A) >> 11][(A)] - flash_data) + +DECLFR(FlashROM_Read) { + if (flash_state == 0x90) { + /* 0: manufacturer id */ + /* 1: model id */ + return flash_id[A & 1]; + } else if (time_out > 0) { + return ((flash_data[PRG_OFFSET(A)] ^ ((time_out & 1) << 6)) & 0x77); + } + return flash_data[PRG_OFFSET(A)]; +} + +DECLFW(FlashROM_Write) { + uint32 chip_address = PRG_OFFSET(A); + uint32 cmd = chip_address & 0x7FFF; + + switch (flash_state) { + default: + case 0x80: + if ((cmd == flash_addr1) && (V == 0xAA)) { + flash_state++; + } + break; + case 0x01: + case 0x81: + if ((cmd == flash_addr2) && (V == 0x55)) { + flash_state++; + } + break; + case 0x02: + if (cmd == flash_addr1) { + flash_state = V; + } + break; + case 0x82: + /* sector or chip erase */ + if (V == 0x30) { + /* sector erase */ + if (chip_address < flash_size) { + uint32 i; + chip_address &= ~(flash_sect_size - 1); + for (i = 0; i < flash_sect_size; i++) { + flash_data[chip_address + i] = 0xFF; + } + FCEU_printf("Flash sector #%d is erased (0x%08x - 0x%08x).\n", chip_address / flash_sect_size, chip_address, chip_address + flash_sect_size); + time_out = flash_sect_size; + } + } else if ((cmd == flash_addr1) && (V == 0x10)) { + int i; + /* chip erase */ + for (i = 0; i <= (int)flash_size; i++) { + flash_data[i] = 0xFF; + } + FCEU_printf("Flash chip erased.\n"); + time_out = flash_size; + } else if (V == 0xF0) { + flash_state = 0; + } + break; + case 0x90: + /* software id */ + if (V == 0xF0) { + flash_state = 0; + } + break; + case 0xA0: + /* byte program */ + flash_data[chip_address] = V; + flash_state = 0; + break; + } + + /* FCEU_printf("%04x:%02x cmd:%04x state:%02x addr1:%04x addr2:%04x\n", A, V, cmd, flash_state, flash_addr1, flash_addr2); */ +} + +void FlashROM_CPUCyle(int a) { + if (time_out > 0) { + time_out -= a; + if (time_out <= 0) { + flash_state = 0; + } + } +} + +void FlashROM_Init(uint8 *data, uint32 size, uint8 manufacter_id, uint8 model_id, uint32 sector_size, uint32 adr1, uint32 adr2) { + flash_data = data; + flash_size = size; + flash_id[0] = manufacter_id; + flash_id[1] = model_id; + flash_addr1 = adr1; + flash_addr2 = adr2; + flash_sect_size = sector_size; + + AddExState(FlashStateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/hw/flashrom.h b/src/mappers/hw/flashrom.h new file mode 100644 index 000000000..19e6c50cb --- /dev/null +++ b/src/mappers/hw/flashrom.h @@ -0,0 +1,30 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FLASHROM_H +#define FLASHROM_H + +DECLFW(FlashROM_Write); +DECLFR(FlashROM_Read); + +void FlashROM_Init(uint8 *data, uint32 size, uint8 manufacter_id, uint8 model_id, uint32 sector_size, uint32 adr1, uint32 adr2); +void FlashROM_CPUCyle(int a); + +#endif /* FLASHROM_H */ diff --git a/src/mappers/hw/fme7.c b/src/mappers/hw/fme7.c new file mode 100644 index 000000000..8d252e930 --- /dev/null +++ b/src/mappers/hw/fme7.c @@ -0,0 +1,236 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "fme7.h" +#include "s5bsound.h" + +static uint8 IRQa; +static int32 IRQCount; + +FME7 fme7; + +void (*FME7_pwrap)(uint16 A, uint16 V); +void (*FME7_cwrap)(uint16 A, uint16 V); + +void (*FME7_FixWRAM)(void); +void (*FME7_FixPRG)(void); +void (*FME7_FixCHR)(void); +void (*FME7_FixMIR)(void); + +static SFORMAT StateRegs[] = { + { fme7.prg, 4, "PREG" }, + { fme7.chr, 8, "CREG" }, + { &fme7.cmd, 1, "CMDR" }, + { &fme7.mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void GENPWRAP(uint16 A, uint16 V) { + setprg8(A, V); +} + +static void GENCWRAP(uint16 A, uint16 V) { + setchr1(A, V); +} + +static void GENFIXWRAM(void) { + if (fme7.prg[0] & 0x40) { + setprg8r(0x10, 0x6000, fme7.prg[0] & 0x3F); + } else { + setprg8(0x6000, fme7.prg[0] & 0x3F); + } +} + +static void GENFIXPRG(void) { + FME7_pwrap(0x8000, fme7.prg[1]); + FME7_pwrap(0xA000, fme7.prg[2]); + FME7_pwrap(0xC000, fme7.prg[3]); + FME7_pwrap(0xE000, ~0); +} + +static void GENFIXCHR(void) { + FME7_cwrap(0x0000, fme7.chr[0]); + FME7_cwrap(0x0400, fme7.chr[1]); + FME7_cwrap(0x0800, fme7.chr[2]); + FME7_cwrap(0x0C00, fme7.chr[3]); + FME7_cwrap(0x1000, fme7.chr[4]); + FME7_cwrap(0x1400, fme7.chr[5]); + FME7_cwrap(0x1800, fme7.chr[6]); + FME7_cwrap(0x1C00, fme7.chr[7]); +} + +static void GENFIXMIR(void) { + switch (fme7.mirr & 0x03) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +static DECLFW(FME7_WRAMWrite) { + if ((fme7.prg[0] & 0xC0) == 0xC0) { + CartBW(A, V); + } +} + +static DECLFR(FME7_WRAMRead) { + if ((fme7.prg[0] & 0xC0) == 0x40) { + return CPU_OPENBUS; + } + return CartBR(A); + +} + +DECLFW(FME7_WriteIndex) { + fme7.cmd = V; +} + +DECLFW(FME7_WriteReg) { + switch (fme7.cmd & 0x0F) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + fme7.chr[fme7.cmd] = V; + FME7_FixCHR(); + break; + case 0x08: case 0x09: case 0x0A: case 0x0B: + fme7.prg[fme7.cmd & 0x03] = V; + FME7_FixPRG(); + FME7_FixWRAM(); + break; + case 0x0C: + fme7.mirr = V; + FME7_FixMIR(); + break; + case 0x0D: + IRQa = V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x0E: + IRQCount = (IRQCount & 0xFF00) | (V & 0xFF); + break; + case 0x0F: + IRQCount = (IRQCount & 0x00FF) | (V << 8); + break; + } +} + +void FME7_Reset(void) { + fme7.prg[0] = 0; + fme7.prg[1] = 0; + fme7.prg[2] = 1; + fme7.prg[3] = ~1; + fme7.chr[0] = 0; + fme7.chr[1] = 1; + fme7.chr[2] = 2; + fme7.chr[3] = 3; + fme7.chr[4] = 4; + fme7.chr[5] = 5; + fme7.chr[6] = 6; + fme7.chr[7] = 7; + fme7.cmd = 0; + IRQCount = ~0; + IRQa = 0; + + FME7_FixPRG(); + FME7_FixCHR(); + FME7_FixMIR(); + FME7_FixWRAM(); +} + +void FME7_Power(void) { + SetReadHandler(0x8000, 0xFFFF, CartBR); + + SetWriteHandler(0x8000, 0x9FFF, FME7_WriteIndex); + SetWriteHandler(0xA000, 0xBFFF, FME7_WriteReg); + + SetReadHandler(0x6000, 0x7FFF, FME7_WRAMRead); + SetWriteHandler(0x6000, 0x7FFF, FME7_WRAMWrite); + + SetWriteHandler(0xC000, 0xDFFF, S5BSound_Write); + SetWriteHandler(0xE000, 0xFFFF, S5BSound_Write); + + if (WRAM) { + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } + + FME7_Reset(); +} + +static void FME7_Close(void) { +} + +static void FME7_IRQHook(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + IRQCount = 0xFFFF; + } + } +} + +static void StateRestore(int version) { + FME7_FixWRAM(); + FME7_FixPRG(); + FME7_FixCHR(); + FME7_FixMIR(); +} + +void FME7_Init(CartInfo *info, int wram, int battery) { + FME7_FixPRG = GENFIXPRG; + FME7_FixCHR = GENFIXCHR; + FME7_FixMIR = GENFIXMIR; + FME7_FixWRAM = GENFIXWRAM; + + FME7_pwrap = GENPWRAP; + FME7_cwrap = GENCWRAP; + + if (wram) { + WRAMSIZE = 8192; + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } + + info->Power = FME7_Power; + info->Close = FME7_Close; + MapIRQHook = FME7_IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + S5BSound_ESI(); + S5BSound_AddStateInfo(); +} diff --git a/src/mappers/hw/fme7.h b/src/mappers/hw/fme7.h new file mode 100644 index 000000000..dd40c13da --- /dev/null +++ b/src/mappers/hw/fme7.h @@ -0,0 +1,47 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FME7_H +#define _FME7_H +typedef struct __FME7 { + uint8 prg[4]; + uint8 chr[8]; + uint8 cmd; + uint8 mirr; +} FME7; + +extern FME7 fme7; + +DECLFW(FME7_WriteIndex); +DECLFW(FME7_WriteReg); + +void FME7_Init(CartInfo *info, int wram, int battery); +void FME7_Power(void); +void FME7_Reset(void); + +extern void (*FME7_FixPRG)(void); +extern void (*FME7_FixCHR)(void); +extern void (*FME7_FixMIR)(void); +extern void (*FME7_FixWRAM)(void); + +extern void (*FME7_pwrap)(uint16 A, uint16 V); +extern void (*FME7_cwrap)(uint16 A, uint16 V); + +#endif /* _FME7_H */ diff --git a/src/mappers/hw/jv001.c b/src/mappers/hw/jv001.c new file mode 100644 index 000000000..7291293a5 --- /dev/null +++ b/src/mappers/hw/jv001.c @@ -0,0 +1,134 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * TXC/Micro Genius simplified mapper + * updated 06-2019 http://wiki.nesdev.com/w/index.php/INES_Mapper_036 + * + * Known games: + * - Strike Wolf (Asia) (Unl) + * - Policeman (Gluk Video) (unl) + * - F-15 City War (Spain) (Gluk Video) (Unl) + * + * TXC mappers, originally much complex banksitching + * + * 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang + * 01-22110-000 (52S ) - MGC-002 2-in-1 Gun + * 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block + * (079 ) - MGC-012 Poke Block + * 01-22110-200 (05-00002-010) (036 ) - MGC-014 Strike Wolf + * 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman + * 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior + * 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1 + * 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom + * 01-22200-400 (------------) (079 ) - ET.03 F-15 City War + * (172 ) - 1991 Du Ma Racing + * + */ + +/* added 2020-2-16 + * Updated based on latest source + * Mappers 36, 132, 173 + * Mappers 136, 147, 172 + */ + +#include "mapinc.h" +#include "jv001.h" + +JV001 jv001; + +static void Dummyfunc(void) { } +static void (*WSync)(void) = Dummyfunc; + +static SFORMAT StateRegs[] = +{ + { &jv001.accumulator, 1, "ACC0" }, + { &jv001.inverter, 1, "INVR" }, + { &jv001.staging, 1, "STG0" }, + { &jv001.output, 1, "OUT0" }, + { &jv001.increase, 1, "INC0" }, + { &jv001.X, 1, "XFLG" }, + { &jv001.invert, 1, "INVT" }, + { 0 } +}; + +DECLFR(JV001_Read) { + uint8 ret = CPU_OPENBUS; + if ((A & 0x103) == 0x100) { + ret = ((jv001.accumulator & 0x0F) | ((jv001.inverter ^ jv001.invert) & ~0x0F)); + WSync(); + } + return ret; +} + +DECLFW(JV001_Write) { + if (A & 0x8000) { + jv001.output = (jv001.accumulator & 0x0F) | (jv001.inverter & 0xF0); + } else { + switch (A & 0x103) { + case 0x100: + if (jv001.increase) { + jv001.accumulator++; + } else { + jv001.accumulator = ((jv001.accumulator & ~0x0F) | ((jv001.staging ^ jv001.invert) & 0x0F)); + } + break; + case 0x101: + jv001.invert = (V & 0x01) ? 0xFF : 0x00; + break; + case 0x102: + jv001.staging = V & 0x0F; + jv001.inverter = V & ~0x0F; + break; + case 0x103: + jv001.increase = ((V & 0x01) != 0); + break; + } + } + jv001.X = jv001.invert ? jv001.A : jv001.B; + WSync(); +} + +void JV001_Reset(void) { + WSync(); +} + +void JV001_Power(void) { + jv001.output = 0; + jv001.accumulator = 0; + jv001.inverter = 0; + jv001.staging = 0; + jv001.increase = 0; + jv001.invert = 0xFF; + jv001.X = 0; + jv001.A = 0; + jv001.B = 1; + JV001_Reset(); +} + +static void StateRestore(int version) { + WSync(); +} + +void JV001_Init(CartInfo *info, void (*proc)(void)) { + WSync = proc; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/hw/jv001.h b/src/mappers/hw/jv001.h new file mode 100644 index 000000000..a2c0476bd --- /dev/null +++ b/src/mappers/hw/jv001.h @@ -0,0 +1,46 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _JV001_H +#define _JV001_H + +typedef struct __JV001 { + uint8 accumulator; + uint8 inverter; + uint8 staging; + uint8 output; + uint8 increase; + uint8 invert; + uint8 A; + uint8 B; + uint8 X; +} JV001; + +extern JV001 jv001; + +void JV001_Power(void); +void JV001_Reset(void); + +void JV001_Init(CartInfo *info, void (*proc)(void)); + +DECLFR(JV001_Read); +DECLFW(JV001_Write); + +#endif /* _JV001_H */ diff --git a/src/mappers/hw/jyasic.c b/src/mappers/hw/jyasic.c new file mode 100644 index 000000000..185ee251a --- /dev/null +++ b/src/mappers/hw/jyasic.c @@ -0,0 +1,520 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +JYASIC jyasic = { 0 }; + +static uint8 dipSwitch; +static uint8 allow_extended_mirroring; +static uint32 lastPPUAddress; + +uint8 JYASIC_CPUWriteHandlersSet; +writefunc JYASIC_cpuWrite[0x10000]; /* Actual write handlers for CPU write trapping as a method fo IRQ clocking */ + +void (*JYASIC_pwrap)(uint16 A, uint16 V); +void (*JYASIC_wwrap)(uint16 A, uint16 V); +void (*JYASIC_cwrap)(uint16 A, uint16 V); + +uint32 (*JYASIC_GetPRGBank)(uint32 V); +uint32 (*JYASIC_GetCHRBank)(uint32 V); + +static SFORMAT JYASIC_StateRegs[] = { + { jyasic.mode, 4, "TKCO" }, + { jyasic.prg, 4, "PRGB" }, + { jyasic.mul, 2, "MUL" }, + { jyasic.latch, 2, "CLTC" }, + { jyasic.chr, 16, "CHRB" }, + { jyasic.nt, 8, "NMS0" }, + { &jyasic.adder, 1, "ADDE" }, + { &jyasic.test, 1, "REGI" }, + { &jyasic.irq.control, 1, "IRQM" }, + { &jyasic.irq.prescaler, 1, "IRQP" }, + { &jyasic.irq.counter, 1, "IRQC" }, + { &jyasic.irq.xor, 1, "IRQX" }, + { &jyasic.irq.enable, 1, "IRQA" }, + { 0 } +}; + +static uint8 rev(uint8 val) { + return ( + ((val << 6) & 0x40) | + ((val << 4) & 0x20) | + ((val << 2) & 0x10) | + ((val << 0) & 0x08) | + ((val >> 2) & 0x04) | + ((val >> 4) & 0x02) | + ((val >> 6) & 0x01)); +} + +static uint32 GENPRGBANK(uint32 V) { return 0; } +static uint32 GENCHRBANK(uint32 V) { return 0; } + +static void GENPWRAP(uint16 A, uint16 V) { + uint32 bank = JYASIC_GetPRGBank(V); + setprg8(A, bank); +} + +static void GENCWRAP(uint16 A, uint16 V) { + uint32 bank = JYASIC_GetCHRBank(V); + setchr1(A, bank); +} + +static void GENWWRAP(uint16 A, uint16 V) { + uint32 bank = JYASIC_GetPRGBank(V); + setprg8(A, bank); +} + +void JYASIC_FixPRG(void) { + uint8 prgLast = (jyasic.mode[0] & 0x04) ? jyasic.prg[3] : 0xFF; + uint8 prg6000 = 0; + + switch (jyasic.mode[0] & 0x03) { + case 0: + JYASIC_pwrap(0x8000, (prgLast << 2) | 0); + JYASIC_pwrap(0xA000, (prgLast << 2) | 1); + JYASIC_pwrap(0xC000, (prgLast << 2) | 2); + JYASIC_pwrap(0xE000, (prgLast << 2) | 3); + prg6000 = (jyasic.prg[3] << 2) | 3; + break; + case 1: + JYASIC_pwrap(0x8000, (jyasic.prg[1] << 1) | 0); + JYASIC_pwrap(0xA000, (jyasic.prg[1] << 1) | 1); + JYASIC_pwrap(0xC000, (prgLast << 1) | 0); + JYASIC_pwrap(0xE000, (prgLast << 1) | 1); + prg6000 = (jyasic.prg[3] << 1) | 1; + break; + case 2: + JYASIC_pwrap(0x8000, jyasic.prg[0]); + JYASIC_pwrap(0xA000, jyasic.prg[1]); + JYASIC_pwrap(0xC000, jyasic.prg[2]); + JYASIC_pwrap(0xE000, prgLast); + prg6000 = jyasic.prg[3]; + break; + case 3: + JYASIC_pwrap(0x8000, rev(jyasic.prg[0])); + JYASIC_pwrap(0xA000, rev(jyasic.prg[1])); + JYASIC_pwrap(0xC000, rev(jyasic.prg[2])); + JYASIC_pwrap(0xE000, rev(prgLast)); + prg6000 = rev(jyasic.prg[3]); + break; + } + if (jyasic.mode[0] & 0x80) { /* Map ROM */ + JYASIC_wwrap(0x6000, prg6000); + } else if (WRAMSIZE) { /* Otherwise map WRAM if it exists */ + setprg8r(0x10, 0x6000, 0); + } +} + +void JYASIC_FixCHR(void) { + /* MMC4 jyasic.mode[0] with 4 KiB CHR jyasic.mode[0] */ + if (jyasic.mode[3] & 0x80 && (jyasic.mode[0] & 0x18) == 0x08) { + JYASIC_cwrap(0x0000, (jyasic.chr[(jyasic.latch[0] & 2) | 0] << 2) | 0); + JYASIC_cwrap(0x0400, (jyasic.chr[(jyasic.latch[0] & 2) | 0] << 2) | 1); + JYASIC_cwrap(0x0800, (jyasic.chr[(jyasic.latch[0] & 2) | 0] << 2) | 2); + JYASIC_cwrap(0x0C00, (jyasic.chr[(jyasic.latch[0] & 2) | 0] << 2) | 3); + JYASIC_cwrap(0x1000, (jyasic.chr[(jyasic.latch[1] & 2) | 4] << 2) | 0); + JYASIC_cwrap(0x1400, (jyasic.chr[(jyasic.latch[1] & 2) | 4] << 2) | 1); + JYASIC_cwrap(0x1800, (jyasic.chr[(jyasic.latch[1] & 2) | 4] << 2) | 2); + JYASIC_cwrap(0x1C00, (jyasic.chr[(jyasic.latch[1] & 2) | 4] << 2) | 3); + } else { + switch (jyasic.mode[0] & 0x18) { + case 0x00: /* 8 KiB CHR mode */ + JYASIC_cwrap(0x0000, (jyasic.chr[0] << 3) | 0); + JYASIC_cwrap(0x0400, (jyasic.chr[0] << 3) | 1); + JYASIC_cwrap(0x0800, (jyasic.chr[0] << 3) | 2); + JYASIC_cwrap(0x0C00, (jyasic.chr[0] << 3) | 3); + JYASIC_cwrap(0x1000, (jyasic.chr[0] << 3) | 4); + JYASIC_cwrap(0x1400, (jyasic.chr[0] << 3) | 5); + JYASIC_cwrap(0x1800, (jyasic.chr[0] << 3) | 6); + JYASIC_cwrap(0x1C00, (jyasic.chr[0] << 3) | 7); + break; + case 0x08: /* 4 KiB CHR mode */ + JYASIC_cwrap(0x0000, (jyasic.chr[0] << 2) | 0); + JYASIC_cwrap(0x0400, (jyasic.chr[0] << 2) | 1); + JYASIC_cwrap(0x0800, (jyasic.chr[0] << 2) | 2); + JYASIC_cwrap(0x0C00, (jyasic.chr[0] << 2) | 3); + JYASIC_cwrap(0x1000, (jyasic.chr[4] << 2) | 0); + JYASIC_cwrap(0x1400, (jyasic.chr[4] << 2) | 1); + JYASIC_cwrap(0x1800, (jyasic.chr[4] << 2) | 2); + JYASIC_cwrap(0x1C00, (jyasic.chr[4] << 2) | 3); + break; + case 0x10: /* 2 KiB CHR mode */ + JYASIC_cwrap(0x0000, (jyasic.chr[0] << 1) | 0); + JYASIC_cwrap(0x0400, (jyasic.chr[0] << 1) | 1); + JYASIC_cwrap(0x0800, (jyasic.chr[2] << 1) | 0); + JYASIC_cwrap(0x0C00, (jyasic.chr[2] << 1) | 1); + JYASIC_cwrap(0x1000, (jyasic.chr[4] << 1) | 0); + JYASIC_cwrap(0x1400, (jyasic.chr[4] << 1) | 1); + JYASIC_cwrap(0x1800, (jyasic.chr[6] << 1) | 0); + JYASIC_cwrap(0x1C00, (jyasic.chr[6] << 1) | 1); + break; + case 0x18: /* 1 KiB CHR mode */ + JYASIC_cwrap(0x0000, jyasic.chr[0]); + JYASIC_cwrap(0x0400, jyasic.chr[1]); + JYASIC_cwrap(0x0800, jyasic.chr[2]); + JYASIC_cwrap(0x0C00, jyasic.chr[3]); + JYASIC_cwrap(0x1000, jyasic.chr[4]); + JYASIC_cwrap(0x1400, jyasic.chr[5]); + JYASIC_cwrap(0x1800, jyasic.chr[6]); + JYASIC_cwrap(0x1C00, jyasic.chr[7]); + break; + } + } + + PPUCHRRAM = (jyasic.mode[2] & 0x40) ? 0xFF : 0x00; /* Write-protect or write-enable CHR-RAM */ +} + +void JYASIC_FixMIR(void) { + if (jyasic.mode[0] & 0x20 || jyasic.mode[1] & 0x08) { + /* ROM nametables or extended mirroring */ + /* First, set normal CIRAM pages using extended registers ... */ + setmirrorw(jyasic.nt[0] & 1, jyasic.nt[1] & 1, jyasic.nt[2] & 1, jyasic.nt[3] & 1); + + if (jyasic.mode[0] & 0x20) { + int i; + for (i = 0; i < 4; i++) { + /* Then replace with ROM nametables if such are generally enabled */ + /* ROM nametables are used either when globally enabled via + * D000.6 or per-bank via B00x.7 vs. D002.7 */ + if (((jyasic.nt[i] & 0x80) ^ (jyasic.mode[2] & 0x80)) | (jyasic.mode[0] & 0x40)) { + setntamem(CHRptr[0] + 0x400 * (JYASIC_GetCHRBank(jyasic.nt[i]) & CHRmask1[0]), 0, i); + } + } + } + } else { + switch (jyasic.mode[1] & 0x03) { + /* Regularly mirrored CIRAM */ + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } + } +} + +static void clockIRQ(void) { + uint8 mask = jyasic.irq.control & 0x04 ? 0x07 : 0xFF; + uint8 prescaler = jyasic.irq.prescaler & mask; + uint8 clockIrqCounter = FALSE; + + if (jyasic.irq.enable) { + switch (jyasic.irq.control & 0xC0) { + case 0x40: + prescaler++; + if ((prescaler & mask) == 0) { + clockIrqCounter = TRUE; + } + break; + case 0x80: + if (--prescaler == 0) { + clockIrqCounter = TRUE; + } + break; + } + + jyasic.irq.prescaler = (jyasic.irq.prescaler & ~mask) | (prescaler & mask); + + if (clockIrqCounter) { + switch (jyasic.irq.control & 0xC0) { + case 0x40: + if ((jyasic.irq.control & 0x08) == 0) { + jyasic.irq.counter++; + } + if (jyasic.irq.counter == 0x00) { + X6502_IRQBegin(FCEU_IQEXT); + } + break; + case 0x80: + if ((jyasic.irq.control & 0x08) == 0) { + jyasic.irq.counter--; + } + if (jyasic.irq.counter == 0xFF) { + X6502_IRQBegin(FCEU_IQEXT); + } + break; + } + } + } +} + +DECLFW(JYASIC_trapCPUWrite) { + if ((jyasic.irq.control & 0x03) == 0x03) { + clockIRQ(); /* Clock IRQ counter on CPU writes */ + } + JYASIC_cpuWrite[A](A, V); +} + +static void trapPPUAddressChange(uint32 A) { + if (((jyasic.irq.control & 0x03) == 0x02) && (lastPPUAddress != A)) { + int i; + for (i = 0; i < 2; i++) { + clockIRQ(); /* Clock IRQ counter on PPU "reads" */ + } + } + if ((jyasic.mode[3] & 0x80) && ((jyasic.mode[0] & 0x18) == 0x08) && (((A & 0x2FF0) == 0xFD0) || ((A & 0x2FF0) == 0xFE0))) { + /* If MMC4 jyasic.mode[0] is enabled, and CHR jyasic.mode[0] is 4 KiB, and tile FD or FE is being fetched ... */ + jyasic.latch[(A >> 12) & 1] = ((A >> 10) & 4) | ((A >> 4) & 2); /* switch the left or right pattern table's latch to 0 (FD) or 2 (FE), + * being used as an offset for the CHR register index. */ + JYASIC_FixCHR(); + } + lastPPUAddress = A; +} + +static void ppuScanline(void) { + if ((jyasic.irq.control & 0x03) == 0x01) { + int i; + for (i = 0; i < 8; i++) { + clockIRQ(); /* Clock IRQ counter on A12 rises (eight per scanline). This should be done in + trapPPUAddressChange, but would require more accurate PPU emulation for that. */ + } + } +} + +static void cpuCycle(int a) { + if ((jyasic.irq.control & 0x03) == 0x00) { + while (a--) { + clockIRQ(); /* Clock IRQ counter on M2 cycles */ + } + } +} + +DECLFR(JYASIC_ReadALU_DIP) { + if ((A & 0x3FF) == 0 && + A != 0x5800) { /* 5000, 5400, 5C00: read solder pad setting */ + return dipSwitch | (CPU_OPENBUS & 0x3F); + } + + if (A & 0x800) { + switch (A & 3) { + /* 5800-5FFF: read ALU */ + case 0: return (jyasic.mul[0] * jyasic.mul[1]) & 0xFF; + case 1: return (jyasic.mul[0] * jyasic.mul[1]) >> 8; + case 2: return jyasic.adder; + case 3: return jyasic.test; + } + } + /* all others */ + return CPU_OPENBUS; +} + +DECLFW(JYASIC_WriteALU) { + switch (A & 3) { + case 0: jyasic.mul[0] = V; break; + case 1: jyasic.mul[1] = V; break; + case 2: jyasic.adder += V; break; + case 3: jyasic.test = V; jyasic.adder = 0; break; + } +} + +DECLFW(JYASIC_WritePRG) { + jyasic.prg[A & 3] = V; + JYASIC_FixPRG(); +} + +DECLFW(JYASIC_WriteCHRLow) { + jyasic.chr[A & 7] = (jyasic.chr[A & 7] & 0xFF00) | V; + JYASIC_FixCHR(); +} + +DECLFW(JYASIC_WriteCHRHigh) { + jyasic.chr[A & 7] = (jyasic.chr[A & 7] & 0x00FF) | V << 8; + JYASIC_FixCHR(); +} + +DECLFW(JYASIC_WriteNT) { + if (~A & 4) { + jyasic.nt[A & 3] = (jyasic.nt[A & 3] & 0xFF00) | V; + } else { + jyasic.nt[A & 3] = (jyasic.nt[A & 3] & 0x00FF) | V << 8; + } + JYASIC_FixMIR(); +} + +DECLFW(JYASIC_WriteIRQ) { + switch (A & 7) { + case 0: + jyasic.irq.enable = !!(V & 1); + if (!jyasic.irq.enable) { + jyasic.irq.prescaler = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + break; + case 1: + jyasic.irq.control = V; + break; + case 2: + jyasic.irq.enable = 0; + jyasic.irq.prescaler = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 3: + jyasic.irq.enable = 1; + break; + case 4: + jyasic.irq.prescaler = V ^ jyasic.irq.xor; + break; + case 5: + jyasic.irq.counter = V ^ jyasic.irq.xor; + break; + case 6: + jyasic.irq.xor = V; + break; + } +} + +DECLFW(JYASIC_WriteMode) { + switch (A & 3) { + case 0: + jyasic.mode[0] = V; + if (!allow_extended_mirroring) { + jyasic.mode[0] &= ~0x20; + } + break; + case 1: + jyasic.mode[1] = V; + if (!allow_extended_mirroring) { + jyasic.mode[1] &= ~0x08; + } + break; + case 2: + jyasic.mode[2] = V; + break; + case 3: + jyasic.mode[3] = V; + break; + } + JYASIC_FixPRG(); + JYASIC_FixCHR(); + JYASIC_FixMIR(); +} + +void JYASIC_restoreWriteHandlers(void) { + int i; + if (JYASIC_CPUWriteHandlersSet) { + for (i = 0; i < 0x10000; i++) { + SetWriteHandler(i, i, JYASIC_cpuWrite[i]); + } + JYASIC_CPUWriteHandlersSet = 0; + } +} + +void JYASIC_RegReset(void) { + memset(jyasic.mode, 0, sizeof(jyasic.mode)); + memset(jyasic.prg, 0, sizeof(jyasic.prg)); + memset(jyasic.chr, 0, sizeof(jyasic.chr)); + memset(jyasic.nt, 0, sizeof(jyasic.nt)); + memset(jyasic.mul, 0, sizeof(jyasic.mul)); + + jyasic.adder = jyasic.test = dipSwitch = 0; + jyasic.irq.control = jyasic.irq.enable = 0; + jyasic.irq.prescaler = jyasic.irq.counter = 0; + jyasic.irq.xor = lastPPUAddress = 0; + + jyasic.latch[0] = 0; + jyasic.latch[1] = 4; + + JYASIC_FixPRG(); + JYASIC_FixCHR(); + JYASIC_FixMIR(); +} + +void JYASIC_Power(void) { + int i; + + SetWriteHandler(0x5000, 0x5FFF, JYASIC_WriteALU); + SetWriteHandler(0x6000, 0x7fff, CartBW); + SetWriteHandler(0x8000, 0x87FF, JYASIC_WritePRG); /* 8800-8FFF ignored */ + SetWriteHandler(0x9000, 0x97FF, JYASIC_WriteCHRLow); /* 9800-9FFF ignored */ + SetWriteHandler(0xA000, 0xA7FF, JYASIC_WriteCHRHigh); /* A800-AFFF ignored */ + SetWriteHandler(0xB000, 0xB7FF, JYASIC_WriteNT); /* B800-BFFF ignored */ + SetWriteHandler(0xC000, 0xCFFF, JYASIC_WriteIRQ); + SetWriteHandler(0xD000, 0xD7FF, JYASIC_WriteMode); /* D800-DFFF ignored */ + + JYASIC_restoreWriteHandlers(); + for (i = 0; i < 0x10000; i++) { + JYASIC_cpuWrite[i] = GetWriteHandler(i); + } + SetWriteHandler(0x0000, 0xFFFF, JYASIC_trapCPUWrite); /* Trap all CPU writes for IRQ clocking purposes */ + JYASIC_CPUWriteHandlersSet = 1; + + SetReadHandler(0x5000, 0x5FFF, JYASIC_ReadALU_DIP); + SetReadHandler(0x6000, 0xFFFF, CartBR); + + JYASIC_RegReset(); +} + +void JYASIC_Reset(void) { + dipSwitch = (dipSwitch + 0x40) & 0xC0; + JYASIC_FixPRG(); + JYASIC_FixCHR(); + JYASIC_FixMIR(); +} + +void JYASIC_Close(void) { +} + +static void StateRestore(int version) { + JYASIC_FixPRG(); + JYASIC_FixCHR(); + JYASIC_FixMIR(); +} + +void JYASIC_Init(CartInfo *info, int extended_mirr) { + JYASIC_pwrap = GENPWRAP; + JYASIC_wwrap = GENWWRAP; + JYASIC_cwrap = GENCWRAP; + + JYASIC_GetPRGBank = GENPRGBANK; + JYASIC_GetCHRBank = GENCHRBANK; + + allow_extended_mirroring = extended_mirr; + + JYASIC_CPUWriteHandlersSet = 0; + info->Reset = JYASIC_Reset; + info->Power = JYASIC_Power; + info->Close = JYASIC_Close; + + PPU_hook = trapPPUAddressChange; + MapIRQHook = cpuCycle; + GameHBIRQHook2 = ppuScanline; + + AddExState(JYASIC_StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; + + /* WRAM is present only in iNES mapper 35, or in mappers with numbers above 255 that require NES 2.0, which + * explicitly denotes WRAM size */ + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } else { + WRAMSIZE = info->mapper == 35 ? 8192 : 0; + } + + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } +} diff --git a/src/mappers/hw/jyasic.h b/src/mappers/hw/jyasic.h new file mode 100644 index 000000000..2b43f0761 --- /dev/null +++ b/src/mappers/hw/jyasic.h @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _JYASIC_H +#define _JYASIC_H + +typedef struct __JYASIC { + uint8 mode[4]; + uint8 prg[4]; + uint8 mul[2]; + uint8 adder; + uint8 test; + uint8 latch[2]; + uint16 chr[8]; + uint16 nt[4]; + struct irq { + uint8 control; + uint8 enable; + uint8 prescaler; + uint8 counter; + uint8 xor; + } irq; +} JYASIC; + +extern JYASIC jyasic; + +extern uint8 JYASIC_CPUWriteHandlersSet; +extern writefunc JYASIC_cpuWrite[0x10000]; + +DECLFR(JYASIC_ReadALU_DIP); +DECLFW(JYASIC_trapCPUWrite); +DECLFW(JYASIC_WriteALU); +DECLFW(JYASIC_WritePRG); +DECLFW(JYASIC_WriteCHRLow); +DECLFW(JYASIC_WriteCHRHigh); +DECLFW(JYASIC_WriteNT); +DECLFW(JYASIC_WriteIRQ); +DECLFW(JYASIC_WriteMode); + +void JYASIC_restoreWriteHandlers(void); +void JYASIC_RegReset(void); +void JYASIC_Reset(void); +void JYASIC_Close(void); +void JYASIC_Power(void); +void JYASIC_Init(CartInfo * info, int extended_mirr); + +void JYASIC_FixPRG(void); +void JYASIC_FixCHR(void); +void JYASIC_FixMIR(void); + +extern void (*JYASIC_pwrap)(uint16 A, uint16 V); +extern void (*JYASIC_wwrap)(uint16 A, uint16 V); +extern void (*JYASIC_cwrap)(uint16 A, uint16 V); + +extern uint32 (*JYASIC_GetPRGBank)(uint32 V); +extern uint32 (*JYASIC_GetCHRBank)(uint32 V); + +#endif /* _JYASIC_H */ diff --git a/src/mappers/hw/ks202.c b/src/mappers/hw/ks202.c new file mode 100644 index 000000000..d72f161bd --- /dev/null +++ b/src/mappers/hw/ks202.c @@ -0,0 +1,137 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * KS202 Asic, used for Mapper 142, and Mapper 56 with extra PAL chip + * + */ + +#include "mapinc.h" +#include "ks202.h" + +static uint8 IRQa = 0; +static int32 IRQCount, IRQLatch; + +static void (*WSync)(void); + +KS202 ks202 = { 0 }; + +static SFORMAT StateRegs[] = +{ + { &ks202.cmd, 1, "CMD" }, + { ks202.reg, 8, "REGS" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +DECLFW(KS202_Write) { +/* FCEU_printf("bs %04x %02x\n",A,V); */ + switch (A & 0xF000) { + case 0x8000: + IRQLatch = (IRQLatch & 0xFFF0) | (V & 0x0F); + break; + case 0x9000: + IRQLatch = (IRQLatch & 0xFF0F) | ((V & 0x0F) << 4); + break; + case 0xA000: + IRQLatch = (IRQLatch & 0xF0FF) | ((V & 0x0F) << 8); + break; + case 0xB000: + IRQLatch = (IRQLatch & 0x0FFF) | (V << 12); + break; + case 0xC000: + IRQa = (V & 0xF); + if (IRQa) { + IRQCount = IRQLatch; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xD000: + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xE000: + ks202.cmd = V & 7; + break; + case 0xF000: + ks202.reg[ks202.cmd] = V; + WSync(); + break; + } +} + +static void KS202IRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount >= 0xFFFF) { + IRQa = 0; + IRQCount = IRQLatch; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +void KS202_Power(void) { + KS202_Reset(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, KS202_Write); + if (WRAMSIZE) { + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } +} + +void KS202_Reset(void) { + ks202.reg[0] = ks202.reg[1] = ks202.reg[2] = ks202.reg[3] = 0; + ks202.reg[4] = ks202.reg[5] = ks202.reg[6] = ks202.reg[7] = 0; + ks202.cmd = 0; + IRQa = IRQCount = IRQLatch = 0; + WSync(); +} + +void KS202_Close(void) { +} + +void KS202_Restore(int version) { + WSync(); +} + +void KS202_Init(CartInfo *info, void (*proc)(void), int wram, int battery) { + WSync = proc; + + info->Power = KS202_Power; + info->Close = KS202_Close; + MapIRQHook = KS202IRQHook; + GameStateRestore = KS202_Restore; + + AddExState(StateRegs, ~0, 0, NULL); + + if (wram) { + WRAMSIZE = 8 * 1024; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } +} diff --git a/src/mappers/hw/ks202.h b/src/mappers/hw/ks202.h new file mode 100644 index 000000000..f06c352d5 --- /dev/null +++ b/src/mappers/hw/ks202.h @@ -0,0 +1,40 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _KS202_H +#define _KS202_H + +typedef struct __KS202 { + uint8 reg[8]; + uint8 cmd; +} KS202; + +extern KS202 ks202; + +DECLFW(KS202_Write); + +void KS202_Power(void); +void KS202_Close(void); +void KS202_Reset(void); +void KS202_Restore(int version); + +void KS202_Init(CartInfo *info, void (*proc)(void), int wram, int battery); + +#endif /* _KS202_H */ diff --git a/src/mappers/hw/latch.c b/src/mappers/hw/latch.c new file mode 100644 index 000000000..63cc7454c --- /dev/null +++ b/src/mappers/hw/latch.c @@ -0,0 +1,92 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 bus_conflict; +static void (*WSync)(void); +static readfunc defread; + +LATCH latch; + +DECLFW(Latch_Write) { + /* FCEU_printf("bs %04x %02x\n",A,V); */ + if (bus_conflict) { + V &= CartBR(A); + } + latch.addr = A; + latch.data = V; + WSync(); +} + +void Latch_RegReset(void) { + latch.addr = 0; + latch.data = 0; + WSync(); +} + +void Latch_Power(void) { + Latch_RegReset(); + if (WRAM) { + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } + SetReadHandler(0x8000, 0xFFFF, defread); + SetWriteHandler(0x8000, 0xFFFF, Latch_Write); +} + +void Latch_Close(void) { +} + +static void LatchReset(void) { + WSync(); +} + +static void StateRestore(int version) { + WSync(); +} + +void Latch_Init(CartInfo *info, void (*proc)(void), readfunc func, + uint8 wram, uint8 busc) { + bus_conflict = busc; + WSync = proc; + if (func != NULL) + defread = func; + else + defread = CartBROB; + info->Power = Latch_Power; + info->Close = Latch_Close; + info->Reset = LatchReset; + GameStateRestore = StateRestore; + if (wram) { + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + AddExState(&latch.addr, 2, 0, "ADDR"); + AddExState(&latch.data, 1, 0, "DATA"); +} diff --git a/src/mappers/hw/latch.h b/src/mappers/hw/latch.h new file mode 100644 index 000000000..22b36f6d3 --- /dev/null +++ b/src/mappers/hw/latch.h @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FCEU_LATCH_H +#define _FCEU_LATCH_H + +typedef struct __LATCH { + uint16 addr; + uint8 data; +} LATCH; + +extern LATCH latch; + +DECLFW(Latch_Write); + +void Latch_Power(void); +void Latch_Close(void); +void Latch_RegReset(void); + +void Latch_Init(CartInfo *info, void (*proc)(void), readfunc func, uint8 wram, uint8 busc); + +#endif /* _FCEU_LATCH_H */ diff --git a/src/mappers/hw/mmc1.c b/src/mappers/hw/mmc1.c new file mode 100644 index 000000000..d13186d66 --- /dev/null +++ b/src/mappers/hw/mmc1.c @@ -0,0 +1,280 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 1998 BERO + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc1.h" + + /* size of non-battery-backed portion of WRAM */ + /* serves as starting offset for actual save ram from total wram size */ + /* returns 0 if entire work ram is battery backed ram */ +static uint32 NONSaveRAMSIZE = 0; + +MMC1Type mmc1_type = MMC1B; + +void (*MMC1_pwrap)(uint16 A, uint16 V); +void (*MMC1_cwrap)(uint16 A, uint16 V); +void (*MMC1_mwrap)(uint8 V); +void (*MMC1_wwrap)(void); + +MMC1 mmc1; + +static void GENWRAMWRAP(void) { + uint8 bank = 0; + + if (!WRAMSIZE) { + return; + } + if (WRAMSIZE > 8192) { + if (WRAMSIZE > 16384) { + bank = (mmc1.reg[1] >> 2) & 3; + } else { + bank = (mmc1.reg[1] >> 3) & 1; + } + } + setprg8r(0x10, 0x6000, bank); +} + +static void GENPWRAP(uint16 A, uint16 V) { + setprg16(A, V & 0x0F); +} + +static void GENCWRAP(uint16 A, uint16 V) { + setchr4(A, V & 0x1F); +} + +static uint8 MMC1WRAMEnabled(void) { + if ((mmc1.reg[3] & 0x10) && (mmc1_type == MMC1B)) { + return FALSE; + } + + return TRUE; +} + +static DECLFW(MBWRAM) { + if (MMC1WRAMEnabled()) { + /* WRAM is enabled. */ + CartBW(A, V); + } +} + +static DECLFR(MAWRAM) { + if (!MMC1WRAMEnabled()) { + /* WRAM is disabled */ + return CPU_OPENBUS; + } + + return CartBR(A); +} + +uint32 MMC1_GetPRGBank(int index) { + uint32 bank; + uint8 prg = mmc1.reg[3]; + + switch (mmc1.reg[0] & 0xC) { + case 0xC: + bank = prg | (index * 0x0F); + break; + case 0x8: + bank = (prg & (index * 0x0F)); + break; + case 0x0: + case 0x4: + default: + bank = (prg & ~1) | index; + break; + } + + if ((mmc1.reg[3] & 0x10) && (mmc1_type == MMC1A)) { + return ((bank & 0x07) | (mmc1.reg[3] & 0x08)); + } + + return (bank & 0x0F); +} + +uint32 MMC1_GetCHRBank(int index) { + if (mmc1.reg[0] & 0x10) { + return (mmc1.reg[1 + index]); + } + + return ((mmc1.reg[1] & ~1) | index); +} + +void MMC1_FixCHR(void) { + if (MMC1_wwrap) { + MMC1_wwrap(); + } + + MMC1_cwrap(0x0000, MMC1_GetCHRBank(0)); + MMC1_cwrap(0x1000, MMC1_GetCHRBank(1)); +} + +void MMC1_FixPRG(void) { + MMC1_pwrap(0x8000, MMC1_GetPRGBank(0)); + MMC1_pwrap(0xC000, MMC1_GetPRGBank(1)); +} + +void MMC1_FixMIR(void) { + switch (mmc1.reg[0] & 3) { + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_H); break; + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_1); break; + } +} + +static uint64 lreset; +DECLFW(MMC1_Write) { + int n = (A >> 13) - 4; + + /* The MMC1 is busy so ignore the write. */ + /* As of version FCE Ultra 0.81, the timestamp is only + increased before each instruction is executed(in other words + precision isn't that great), but this should still work to + deal with 2 writes in a row from a single RMW instruction. + */ + if ((timestampbase + timestamp) < (lreset + 2)) { + return; + } + + /* FCEU_printf("Write %04x:%02x\n",A,V); */ + if (V & 0x80) { + mmc1.reg[0] |= 0xC; + mmc1.shift = mmc1.buffer = 0; + MMC1_FixPRG(); + lreset = timestampbase + timestamp; + return; + } + + mmc1.buffer |= (V & 1) << (mmc1.shift++); + + if (mmc1.shift == 5) { + /* FCEU_printf("REG[%d]=%02x\n",n,mmc1.buffer); */ + mmc1.reg[n] = mmc1.buffer; + mmc1.shift = mmc1.buffer = 0; + switch (n) { + case 0: + MMC1_FixMIR(); + MMC1_FixCHR(); + MMC1_FixPRG(); + break; + case 1: + MMC1_FixCHR(); + MMC1_FixPRG(); + break; + case 2: + MMC1_FixCHR(); + break; + case 3: + MMC1_FixPRG(); + break; + } + } +} + +void MMC1_Restore(int version) { + MMC1_FixMIR(); + MMC1_FixCHR(); + MMC1_FixPRG(); + lreset = 0; /* timestamp(base) is not stored in save states. */ +} + +void MMC1_Reset(void) { + mmc1.reg[0] = 0x0C; + mmc1.reg[1] = 0; + mmc1.reg[2] = 0; + mmc1.reg[3] = 0; + + mmc1.buffer = mmc1.shift = 0; + + MMC1_FixPRG(); + MMC1_FixCHR(); + MMC1_FixMIR(); + + lreset = 0; +} + +void MMC1_Power(void) { + lreset = 0; + SetWriteHandler(0x8000, 0xFFFF, MMC1_Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + if (WRAMSIZE) { + FCEU_CheatAddRAM(8, 0x6000, WRAM); + + /* clear non-battery-backed portion of WRAM */ + if (NONSaveRAMSIZE) { + FCEU_MemoryRand(WRAM, NONSaveRAMSIZE); + } + + SetReadHandler(0x6000, 0x7FFF, MAWRAM); + SetWriteHandler(0x6000, 0x7FFF, MBWRAM); + setprg8r(0x10, 0x6000, 0); + } + + MMC1_Reset(); +} + +void MMC1_Close(void) { +} + +void MMC1_Init(CartInfo *info, int wram, int saveram) { + MMC1_pwrap = GENPWRAP; + MMC1_cwrap = GENCWRAP; + MMC1_wwrap = GENWRAMWRAP; + + WRAMSIZE = wram * 1024; + NONSaveRAMSIZE = (wram - saveram) * 1024; + + if (WRAMSIZE) { + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (saveram) { + info->SaveGame[0] = WRAM + NONSaveRAMSIZE; + info->SaveGameLen[0] = saveram * 1024; + } + } + + AddExState(mmc1.reg, 4, 0, "DREG"); + + info->Power = MMC1_Power; + info->Close = MMC1_Close; + GameStateRestore = MMC1_Restore; + AddExState(&mmc1.buffer, 1, 0, "BFFR"); + AddExState(&mmc1.shift, 1, 0, "BFRS"); +} + +void SAROM_Init(CartInfo *info) { + MMC1_Init(info, 8, info->battery ? 8 : 0); +} + +void SKROM_Init(CartInfo *info) { + MMC1_Init(info, 8, info->battery ? 8 : 0); +} + +void SNROM_Init(CartInfo *info) { + MMC1_Init(info, 8, info->battery ? 8 : 0); +} + +void SOROM_Init(CartInfo *info) { + MMC1_Init(info, 16, info->battery ? 8 : 0); +} diff --git a/src/mappers/hw/mmc1.h b/src/mappers/hw/mmc1.h new file mode 100644 index 000000000..9970cb9db --- /dev/null +++ b/src/mappers/hw/mmc1.h @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _MMC1_H +#define _MMC1_H + +typedef enum { + MMC1A, + MMC1B +} MMC1Type; + +typedef struct __MMC1 { + uint8 reg[4]; + uint8 buffer; + uint8 shift; +} MMC1; + +extern MMC1 mmc1; +extern MMC1Type mmc1_type; + +uint32 MMC1_GetPRGBank(int index); +uint32 MMC1_GetCHRBank(int index); + +DECLFW(MMC1_Write); + +void MMC1_Power(void); +void MMC1_Close(void); +void MMC1_Restore(int version); +void MMC1_Reset(void); + +void MMC1_Init(CartInfo *info, int wram, int saveram); + +void MMC1_FixPRG(void); +void MMC1_FixCHR(void); +void MMC1_FixMIR(void); + +extern void (*MMC1_pwrap)(uint16 A, uint16 V); +extern void (*MMC1_cwrap)(uint16 A, uint16 V); +extern void (*MMC1_mwrap)(uint8 V); +extern void (*MMC1_wwrap)(void); + +#endif /* _MMC1_H */ diff --git a/src/mappers/hw/mmc2.c b/src/mappers/hw/mmc2.c new file mode 100644 index 000000000..4a2023ba7 --- /dev/null +++ b/src/mappers/hw/mmc2.c @@ -0,0 +1,150 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "mmc2.h" + +void (*MMC2_pwrap)(uint16 A, uint16 V); +void (*MMC2_cwrap)(uint16 A, uint16 V); +void (*MMC2_mwrap)(uint8 V); + +MMC2 mmc2; + +static SFORMAT StateRegs[] = +{ + { mmc2.chr, 4, "CREG" }, + { mmc2.latch, 2, "PPUL" }, + { &mmc2.prg, 1, "PREG" }, + { &mmc2.mirr, 1, "MIRR" }, + { 0 } +}; + +static void GENPWRAP(uint16 A, uint16 V) { + setprg8(A, V); +} + +static void GENCWRAP(uint16 A, uint16 V) { + setchr4(A, V); +} + +static void GENMWRAP(uint8 V) { + mmc2.mirr = V; + setmirror((mmc2.mirr & 1) ^ 1); +} + +void MMC2_FixPRG(void) { + MMC2_pwrap(0x8000, mmc2.prg); + MMC2_pwrap(0xA000, ~2); + MMC2_pwrap(0xC000, ~1); + MMC2_pwrap(0xE000, ~0); +} + +void MMC2_FixCHR(void) { + MMC2_cwrap(0x0000, mmc2.chr[mmc2.latch[0] | 0]); + MMC2_cwrap(0x1000, mmc2.chr[mmc2.latch[1] | 2]); + + if (MMC2_mwrap) { + MMC2_mwrap(mmc2.mirr); + } +} + +DECLFW(MMC2_Write) { + switch (A & 0xF000) { + case 0xA000: + mmc2.prg = V; + MMC2_FixPRG(); + break; + case 0xB000: + case 0xC000: + case 0xD000: + case 0xE000: + mmc2.chr[(A - 0xB000) >> 12] = V; + MMC2_FixCHR(); + break; + case 0xF000: + if (MMC2_mwrap) { + MMC2_mwrap(V); + } + break; + } +} + +static void MMC2PPUHook(uint32 A) { + uint8 bank = (A >> 12) & 0x01; + if ((A & 0x2000) || (((A & 0xFF0) != 0xFD0) && ((A & 0xFF0) != 0xFE0))) { + return; + } + mmc2.latch[bank] = (A >> 5) & 0x01; + MMC2_FixCHR(); +} + +void MMC2_Reset(void) { + mmc2.prg = mmc2.mirr = 0; + mmc2.latch[0] = mmc2.latch[1] = 0; + MMC2_FixPRG(); + MMC2_FixCHR(); +} + +void MMC2_Power(void) { + MMC2_Reset(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xA000, 0xFFFF, MMC2_Write); + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } +} + +void MMC2_Restore(int version) { + MMC2_FixPRG(); + MMC2_FixCHR(); +} + +void MMC2_Close(void) { +} + +void MMC2_Init(CartInfo *info, int wram, int battery) { + MMC2_pwrap = GENPWRAP; + MMC2_cwrap = GENCWRAP; + MMC2_mwrap = GENMWRAP; + + info->Power = MMC2_Power; + info->Close = MMC2_Close; + PPU_hook = MMC2PPUHook; + + GameStateRestore = MMC2_Restore; + AddExState(StateRegs, ~0, 0, NULL); + + if (wram) { + WRAMSIZE = wram * 1024; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } +} diff --git a/src/mappers/hw/mmc2.h b/src/mappers/hw/mmc2.h new file mode 100644 index 000000000..43f8b6fbd --- /dev/null +++ b/src/mappers/hw/mmc2.h @@ -0,0 +1,48 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _MMC2_H +#define _MMC2_H + +typedef struct __MMC2 { + uint8 prg; + uint8 chr[4]; + uint8 latch[2]; + uint8 mirr; +} MMC2; + +extern MMC2 mmc2; + +DECLFW(MMC2_Write); + +void MMC2_Power(void); +void MMC2_Close(void); +void MMC2_Reset(void); +void MMC2_Restore(int version); +void MMC2_Init(CartInfo *info, int wram, int battery); + +void MMC2_FixPRG(void); +void MMC2_FixCHR(void); + +extern void (*MMC2_pwrap)(uint16 A, uint16 V); +extern void (*MMC2_cwrap)(uint16 A, uint16 V); +extern void (*MMC2_mwrap)(uint8 V); + +#endif /* _MMC2_H */ diff --git a/src/mappers/hw/mmc3.c b/src/mappers/hw/mmc3.c new file mode 100644 index 000000000..5cc2acf8b --- /dev/null +++ b/src/mappers/hw/mmc3.c @@ -0,0 +1,337 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 1998 BERO + * Copyright (C) 2003 Xodnizel + * Mapper 12 code Copyright (C) 2003 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Code for emulating iNES mappers 4,12,44,45,47,49,52,74,114,115,116,118, + 119,165,205,245,249,250,254 +*/ + +#include "mapinc.h" +#include "mmc3.h" + +MMC3 mmc3; + +static uint8 IRQCount, IRQLatch, IRQa; +static uint8 IRQReload; + +static SFORMAT MMC3_StateRegs[] = +{ + { mmc3.reg, 8, "REGS" }, + { &mmc3.cmd, 1, "CMD" }, + { &mmc3.mirr, 1, "A000" }, + { &mmc3.wram, 1, "A001" }, + { &IRQReload, 1, "IRQR" }, + { &IRQCount, 1, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void GENFIXPRG(void); +static void GENFIXCHR(void); + +static void GENPWRAP(uint16 A, uint16 V); +static void GENCWRAP(uint16 A, uint16 V); + +int isRevB = 1; + +void (*MMC3_FixPRG)(void); +void (*MMC3_FixCHR)(void); +void (*MMC3_FixMIR)(void); + +void (*MMC3_pwrap)(uint16 A, uint16 V); +void (*MMC3_cwrap)(uint16 A, uint16 V); + +static void GENCWRAP(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +static void GENPWRAP(uint16 A, uint16 V) { + setprg8(A, (V & 0x7F)); +} + +/* ---------------------------------------------------------------------- + * ------------------------- Generic MM3 Code --------------------------- + * ---------------------------------------------------------------------- + */ + +uint8 MMC3_GetPRGBank(int V) { + if ((~V & 0x01) && (mmc3.cmd & 0x40)) { + V ^= 0x02; + } + if (V & 0x02) { + return (0xFE | (V & 0x01)); + } + return mmc3.reg[6 | (V & 0x01)]; +} + +uint8 MMC3_GetCHRBank(int V) { + if (mmc3.cmd & 0x80) { + V ^= 0x04; + } + if (V & 0x04) { + return mmc3.reg[V - 2]; + } + return ((mmc3.reg[V >> 1] & ~0x01) | (V & 0x01)); +} + +int MMC3_WramIsWritable(void) { + return ((mmc3.wram & 0x80) && !(mmc3.wram & 0x40)) ? TRUE : FALSE; +} + +static void GENFIXPRG(void) { + MMC3_pwrap(0x8000, MMC3_GetPRGBank(0)); + MMC3_pwrap(0xA000, MMC3_GetPRGBank(1)); + MMC3_pwrap(0xC000, MMC3_GetPRGBank(2)); + MMC3_pwrap(0xE000, MMC3_GetPRGBank(3)); +} + +static void GENFIXCHR(void) { + MMC3_cwrap(0x0000, MMC3_GetCHRBank(0)); + MMC3_cwrap(0x0400, MMC3_GetCHRBank(1)); + MMC3_cwrap(0x0800, MMC3_GetCHRBank(2)); + MMC3_cwrap(0x0C00, MMC3_GetCHRBank(3)); + + MMC3_cwrap(0x1000, MMC3_GetCHRBank(4)); + MMC3_cwrap(0x1400, MMC3_GetCHRBank(5)); + MMC3_cwrap(0x1800, MMC3_GetCHRBank(6)); + MMC3_cwrap(0x1C00, MMC3_GetCHRBank(7)); +} + +static void GENFIXMIR(void) { + setmirror((mmc3.mirr & 0x01) ^ 0x01); +} + +void MMC3_Reset(void) { + IRQCount = IRQLatch = IRQa = mmc3.cmd = 0; + mmc3.mirr = mmc3.wram = 0; + + mmc3.reg[0] = 0; + mmc3.reg[1] = 2; + mmc3.reg[2] = 4; + mmc3.reg[3] = 5; + mmc3.reg[4] = 6; + mmc3.reg[5] = 7; + mmc3.reg[6] = 0; + mmc3.reg[7] = 1; + + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); +} + +DECLFW(MMC3_CMDWrite) { + uint8 oldcmd = mmc3.cmd; + /* FCEU_printf("bs %04x %02x\n",A,V); */ + switch (A & 0xE001) { + case 0x8000: + mmc3.cmd = V; + if ((oldcmd & 0x40) != (mmc3.cmd & 0x40)) { + MMC3_FixPRG(); + } + if ((oldcmd & 0x80) != (mmc3.cmd & 0x80)) { + MMC3_FixCHR(); + } + break; + case 0x8001: { + int cbase = (mmc3.cmd & 0x80) << 5; + mmc3.reg[mmc3.cmd & 0x7] = V; + switch (mmc3.cmd & 0x07) { + case 0: + MMC3_cwrap((cbase ^ 0x000), V & (~1)); + MMC3_cwrap((cbase ^ 0x400), V | 1); + break; + case 1: + MMC3_cwrap((cbase ^ 0x800), V & (~1)); + MMC3_cwrap((cbase ^ 0xC00), V | 1); + break; + case 2: + MMC3_cwrap(cbase ^ 0x1000, V); + break; + case 3: + MMC3_cwrap(cbase ^ 0x1400, V); + break; + case 4: + MMC3_cwrap(cbase ^ 0x1800, V); + break; + case 5: + MMC3_cwrap(cbase ^ 0x1C00, V); + break; + case 6: + if (mmc3.cmd & 0x40) { + MMC3_pwrap(0xC000, V); + } else { + MMC3_pwrap(0x8000, V); + } + break; + case 7: + MMC3_pwrap(0xA000, V); + break; + } + break; + } + case 0xA000: + mmc3.mirr = V; + MMC3_FixMIR(); + break; + case 0xA001: + mmc3.wram = V; + break; + } +} + +DECLFW(MMC3_IRQWrite) { + /* FCEU_printf("%04x:%04x\n",A,V); */ + switch (A & 0xE001) { + case 0xC000: + IRQLatch = V; + break; + case 0xC001: + IRQCount = 0; + IRQReload = 1; + break; + case 0xE000: + X6502_IRQEnd(FCEU_IQEXT); + IRQa = 0; + break; + case 0xE001: + IRQa = 1; + break; + } +} + +DECLFW(MMC3_Write) { + /* FCEU_printf("bs %04x %02x\n",A,V); */ + switch (A & 0xE000) { + case 0x8000: + case 0xA000: + MMC3_CMDWrite(A, V); + break; + case 0xC000: + case 0xE000: + MMC3_IRQWrite(A, V); + break; + } +} + +void MMC3_IRQHBHook(void) { + int count = IRQCount; + if (!count || IRQReload) { + IRQCount = IRQLatch; + IRQReload = 0; + } else { + IRQCount--; + } + if ((count | isRevB) && !IRQCount && IRQa) { + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void MMC3_hb(void) { + MMC3_IRQHBHook(); +} + +static void MMC3_hb_KickMasterHack(void) { + if (scanline == 238) { + MMC3_IRQHBHook(); + } + MMC3_IRQHBHook(); +} + +static void MMC3_hb_PALStarWarsHack(void) { + if (scanline == 240) { + MMC3_IRQHBHook(); + } + MMC3_IRQHBHook(); +} + +static void StateRestore(int version) { + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); +} + +void MMC3_Power(void) { + if (!CHR_ROM_SIZE_8K) { + setchr8(0); + } + + SetWriteHandler(0x8000, 0xBFFF, MMC3_CMDWrite); + SetWriteHandler(0xC000, 0xFFFF, MMC3_IRQWrite); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + setmirror(1); + if (mmc3.opts & 1) { + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + SetWriteHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBW); + SetReadHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBR); + setprg8r(0x10, 0x6000, 0); + if (!(mmc3.opts & 2)) { + FCEU_MemoryRand(WRAM, WRAMSIZE); + } + } + MMC3_Reset(); +} + +void MMC3_Close(void) { +} + +void MMC3_Init(CartInfo *info, int wram, int battery) { + MMC3_FixPRG = GENFIXPRG; + MMC3_FixCHR = GENFIXCHR; + MMC3_FixMIR = GENFIXMIR; + + MMC3_pwrap = GENPWRAP; + MMC3_cwrap = GENCWRAP; + + WRAMSIZE = wram << 10; + + if (wram) { + mmc3.opts |= 1; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + + if (battery) { + mmc3.opts |= 2; + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(MMC3_StateRegs, ~0, 0, 0); + + info->Power = MMC3_Power; + info->Reset = MMC3_Reset; + info->Close = MMC3_Close; + + if (info->CRC32 == 0x5104833e) { /* Kick Master */ + GameHBIRQHook = MMC3_hb_KickMasterHack; + } else if (info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20) { /* Shougi Meikan '92/'93 */ + GameHBIRQHook = MMC3_hb_KickMasterHack; + } else if (info->CRC32 == 0xfcd772eb) { /* PAL Star Wars, similar problem as Kick Master. */ + GameHBIRQHook = MMC3_hb_PALStarWarsHack; + } else { + GameHBIRQHook = MMC3_hb; + } + GameStateRestore = StateRestore; +} diff --git a/src/mappers/hw/mmc3.h b/src/mappers/hw/mmc3.h new file mode 100644 index 000000000..ae113b4b8 --- /dev/null +++ b/src/mappers/hw/mmc3.h @@ -0,0 +1,56 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _MMC3_H +#define _MMC3_H + +typedef struct __MMC3 { + uint8 cmd; + uint8 opts; + uint8 mirr; + uint8 wram; + uint8 reg[8]; +} MMC3; + +extern MMC3 mmc3; +extern int isRevB; + +uint8 MMC3_GetPRGBank(int V); +uint8 MMC3_GetCHRBank(int V); + +DECLFW(MMC3_CMDWrite); /* $ 0x8000 - 0xBFFF */ +DECLFW(MMC3_IRQWrite); /* $ 0xC000 - 0xFFFF */ +DECLFW(MMC3_Write); /* $ 0x8000 - 0xFFFF */ + +void MMC3_Power(void); +void MMC3_Reset(void); +void MMC3_Close(void); +void MMC3_IRQHBHook(void); +int MMC3_WramIsWritable(void); +void MMC3_Init(CartInfo *info, int wram, int battery); + +extern void (*MMC3_FixPRG)(void); +extern void (*MMC3_FixCHR)(void); +extern void (*MMC3_FixMIR)(void); + +extern void (*MMC3_pwrap)(uint16 A, uint16 V); +extern void (*MMC3_cwrap)(uint16 A, uint16 V); + +#endif /* _MMC3_H */ diff --git a/src/mappers/hw/mmc4.c b/src/mappers/hw/mmc4.c new file mode 100644 index 000000000..86615dee3 --- /dev/null +++ b/src/mappers/hw/mmc4.c @@ -0,0 +1,148 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "mmc4.h" + +void (*MMC4_pwrap)(uint16 A, uint16 V); +void (*MMC4_cwrap)(uint16 A, uint16 V); +void (*MMC4_mwrap)(uint8 V); + +MMC4 mmc4; + +static SFORMAT StateRegs[] = +{ + { mmc4.chr, 4, "CREG" }, + { mmc4.latch, 2, "PPUL" }, + { &mmc4.prg, 1, "PREG" }, + { &mmc4.mirr, 1, "MIRR" }, + { 0 } +}; + +static void GENPWRAP(uint16 A, uint16 V) { + setprg16(A, V); +} + +static void GENCWRAP(uint16 A, uint16 V) { + setchr4(A, V); +} + +static void GENMWRAP(uint8 V) { + mmc4.mirr = V; + setmirror((mmc4.mirr & 1) ^ 1); +} + +void MMC4_FixPRG(void) { + MMC4_pwrap(0x8000, mmc4.prg); + MMC4_pwrap(0xC000, ~0); +} + +void MMC4_FixCHR(void) { + MMC4_cwrap(0x0000, mmc4.chr[mmc4.latch[0] | 0]); + MMC4_cwrap(0x1000, mmc4.chr[mmc4.latch[1] | 2]); + + if (MMC4_mwrap) { + MMC4_mwrap(mmc4.mirr); + } +} + +DECLFW(MMC4_Write) { + switch (A & 0xF000) { + case 0xA000: + mmc4.prg = V; + MMC4_FixPRG(); + break; + case 0xB000: + case 0xC000: + case 0xD000: + case 0xE000: + mmc4.chr[(A - 0xB000) >> 12] = V; + MMC4_FixCHR(); + break; + case 0xF000: + if (MMC4_mwrap) { + MMC4_mwrap(V); + } + break; + } +} + +static void MMC4PPUHook(uint32 A) { + uint8 bank = (A >> 12) & 0x01; + if ((A & 0x2000) || (((A & 0xFF0) != 0xFD0) && ((A & 0xFF0) != 0xFE0))) { + return; + } + mmc4.latch[bank] = (A >> 5) & 0x01; + MMC4_FixCHR(); +} + +void MMC4_Reset(void) { + mmc4.prg = mmc4.mirr = 0; + mmc4.latch[0] = mmc4.latch[1] = 0; + MMC4_FixPRG(); + MMC4_FixCHR(); +} + +void MMC4_Power(void) { + MMC4_Reset(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xA000, 0xFFFF, MMC4_Write); + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } +} + +void MMC4_Restore(int version) { + MMC4_FixPRG(); + MMC4_FixCHR(); +} + +void MMC4_Close(void) { +} + +void MMC4_Init(CartInfo *info, int wram, int battery) { + MMC4_pwrap = GENPWRAP; + MMC4_cwrap = GENCWRAP; + MMC4_mwrap = GENMWRAP; + + info->Power = MMC4_Power; + info->Close = MMC4_Close; + PPU_hook = MMC4PPUHook; + + GameStateRestore = MMC4_Restore; + AddExState(StateRegs, ~0, 0, NULL); + + if (wram) { + WRAMSIZE = wram * 1024; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } +} diff --git a/src/mappers/hw/mmc4.h b/src/mappers/hw/mmc4.h new file mode 100644 index 000000000..6b72ecb8b --- /dev/null +++ b/src/mappers/hw/mmc4.h @@ -0,0 +1,48 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _MMC4_H +#define _MMC4_H + +typedef struct __MMC4 { + uint8 prg; + uint8 chr[4]; + uint8 latch[2]; + uint8 mirr; +} MMC4; + +extern MMC4 mmc4; + +DECLFW(MMC4_Write); + +void MMC4_Power(void); +void MMC4_Close(void); +void MMC4_Reset(void); +void MMC4_Restore(int version); +void MMC4_Init(CartInfo *info, int wram, int battery); + +void MMC4_FixPRG(void); +void MMC4_FixCHR(void); + +extern void (*MMC4_pwrap)(uint16 A, uint16 V); +extern void (*MMC4_cwrap)(uint16 A, uint16 V); +extern void (*MMC4_mwrap)(uint8 V); + +#endif /* _MMC4_H */ diff --git a/src/mappers/hw/mmc6.c b/src/mappers/hw/mmc6.c new file mode 100644 index 000000000..d9b2848ca --- /dev/null +++ b/src/mappers/hw/mmc6.c @@ -0,0 +1,285 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc6.h" + +typedef struct __MMC6 { + uint8 cmd; + uint8 opts; + uint8 mirr; + uint8 wram; + uint8 reg[8]; +} MMC6; + +static MMC6 mmc6; + +static uint8 IRQCount, IRQLatch, IRQa; +static uint8 IRQReload; + +static SFORMAT MMC6_StateRegs[] = +{ + { mmc6.reg, 8, "REGS" }, + { &mmc6.cmd, 1, "CMD" }, + { &mmc6.mirr, 1, "A000" }, + { &mmc6.wram, 1, "A001" }, + { &IRQReload, 1, "IRQR" }, + { &IRQCount, 1, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void MMC6_FixPRG(void) { + if (!(mmc6.cmd & 0x40)) { + setprg8(0x8000, mmc6.reg[6]); + setprg8(0xA000, mmc6.reg[7]); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + } else { + setprg8(0x8000, ~1); + setprg8(0xA000, mmc6.reg[7]); + setprg8(0xC000, mmc6.reg[6]); + setprg8(0xE000, ~0); + } +} + +static void MMC6_FixCHR(void) { + if (!(mmc6.cmd & 0x80)) { + setchr1(0x0000, mmc6.reg[0] & 0xFE); + setchr1(0x0400, mmc6.reg[0] | 0x01); + setchr1(0x0800, mmc6.reg[1] & 0xFE); + setchr1(0x0C00, mmc6.reg[1] | 0x01); + + setchr1(0x1000, mmc6.reg[2]); + setchr1(0x1400, mmc6.reg[3]); + setchr1(0x1800, mmc6.reg[4]); + setchr1(0x1C00, mmc6.reg[5]); + } else { + setchr1(0x0000, mmc6.reg[2]); + setchr1(0x0400, mmc6.reg[3]); + setchr1(0x0800, mmc6.reg[4]); + setchr1(0x0C00, mmc6.reg[5]); + + setchr1(0x1000, mmc6.reg[0] & 0xFE); + setchr1(0x1400, mmc6.reg[0] | 0x01); + setchr1(0x1800, mmc6.reg[1] & 0xFE); + setchr1(0x1C00, mmc6.reg[1] | 0x01); + } +} + +static void MMC6_FixMIR(void) { + setmirror((mmc6.mirr & 0x01) ^ 0x01); +} + +static void MMC6_Reset(void) { + IRQCount = IRQLatch = IRQa = mmc6.cmd = 0; + mmc6.mirr = mmc6.wram = 0; + + mmc6.reg[0] = 0; + mmc6.reg[1] = 2; + mmc6.reg[2] = 4; + mmc6.reg[3] = 5; + mmc6.reg[4] = 6; + mmc6.reg[5] = 7; + mmc6.reg[6] = 0; + mmc6.reg[7] = 1; + + MMC6_FixPRG(); + MMC6_FixCHR(); + MMC6_FixMIR(); +} + + +static DECLFW(MBWRAMMMC6) { + if (!(mmc6.cmd & 0x20)) { + /* wram disabled */ + return; + } + + A &= 0x3FF; + if (!(A & 0x200)) { + /* 1st bank writes are disabled */ + if ((mmc6.wram & 0x30) == 0x30) WRAM[A] = V; + } else { + /* 2nd bank writes are disabled */ + if ((mmc6.wram & 0xC0) == 0xC0) WRAM[A] = V; + } +} + +static DECLFR(MAWRAMMMC6) { + if (!(mmc6.cmd & 0x20)) { + /* wram disabled */ + return CPU_OPENBUS; + } + + A &= 0x3FF; + if (!(A & 0x200)) { + /* 1st bank */ + if (mmc6.wram & 0x20) return WRAM[A]; + if (mmc6.wram & 0x80) return 0x00; + } else { + /* 2nd bank */ + if (mmc6.wram & 0x80) return WRAM[A]; + if (mmc6.wram & 0x20) return 0x00; + } + return CPU_OPENBUS; +} + +static DECLFW(MMC6_CMDWrite) { + uint8 oldcmd = mmc6.cmd; + /* FCEU_printf("bs %04x %02x\n",A,V); */ + switch (A & 0xE001) { + case 0x8000: + mmc6.cmd = V; + if ((oldcmd & 0x40) != (mmc6.cmd & 0x40)) + MMC6_FixPRG(); + if ((oldcmd & 0x80) != (mmc6.cmd & 0x80)) + MMC6_FixCHR(); + break; + case 0x8001: { + int cbase = (mmc6.cmd & 0x80) << 5; + mmc6.reg[mmc6.cmd & 0x7] = V; + switch (mmc6.cmd & 0x07) { + case 0: + setchr1((cbase ^ 0x000), V & (~1)); + setchr1((cbase ^ 0x400), V | 1); + break; + case 1: + setchr1((cbase ^ 0x800), V & (~1)); + setchr1((cbase ^ 0xC00), V | 1); + break; + case 2: + setchr1(cbase ^ 0x1000, V); + break; + case 3: + setchr1(cbase ^ 0x1400, V); + break; + case 4: + setchr1(cbase ^ 0x1800, V); + break; + case 5: + setchr1(cbase ^ 0x1C00, V); + break; + case 6: + if (mmc6.cmd & 0x40) + setprg8(0xC000, V); + else + setprg8(0x8000, V); + break; + case 7: + setprg8(0xA000, V); + break; + } + break; + } + case 0xA000: + mmc6.mirr = V; + MMC6_FixMIR(); + break; + case 0xA001: + mmc6.wram = V; + break; + } +} + +static DECLFW(MMC6_IRQWrite) { + /* FCEU_printf("%04x:%04x\n",A,V); */ + switch (A & 0xE001) { + case 0xC000: + IRQLatch = V; + break; + case 0xC001: + IRQReload = 1; + break; + case 0xE000: + X6502_IRQEnd(FCEU_IQEXT); + IRQa = 0; + break; + case 0xE001: + IRQa = 1; + break; + } +} + +static void MMC6_IRQHBHook(void) { + int count = IRQCount; + + if (!count || IRQReload) { + IRQCount = IRQLatch; + IRQReload = 0; + } else + IRQCount--; + if (!IRQCount && IRQa) { + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void StateRestore(int version) { + MMC6_FixPRG(); + MMC6_FixCHR(); + MMC6_FixMIR(); +} + +static void MMC6_Power(void) { + if (!CHR_ROM_SIZE_8K) { + setchr8(0); + } + + SetWriteHandler(0x8000, 0xBFFF, MMC6_CMDWrite); + SetWriteHandler(0xC000, 0xFFFF, MMC6_IRQWrite); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + setmirror(1); + + FCEU_CheatAddRAM(1, 0x7000, WRAM); + SetReadHandler(0x7000, 0x7FFF, MAWRAMMMC6); + SetWriteHandler(0x7000, 0x7FFF, MBWRAMMMC6); + if (!(mmc6.opts & 2)) { + FCEU_MemoryRand(WRAM, WRAMSIZE); + } + + MMC6_Reset(); +} + +static void MMC6_Close(void) { +} + +void MMC6_Init(CartInfo *info) { + WRAMSIZE = 1024; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + mmc6.opts |= 2; + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(MMC6_StateRegs, ~0, 0, 0); + + info->Power = MMC6_Power; + info->Reset = MMC6_Reset; + info->Close = MMC6_Close; + + GameHBIRQHook = MMC6_IRQHBHook; + GameStateRestore = StateRestore; +} diff --git a/src/mappers/hw/mmc6.h b/src/mappers/hw/mmc6.h new file mode 100644 index 000000000..adf0cd54f --- /dev/null +++ b/src/mappers/hw/mmc6.h @@ -0,0 +1,26 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _MMC6_H +#define _MMC6_H + +void MMC6_Init(CartInfo *info); + +#endif /* _MMC6_H */ diff --git a/src/mappers/hw/n118.c b/src/mappers/hw/n118.c new file mode 100644 index 000000000..6e63ef294 --- /dev/null +++ b/src/mappers/hw/n118.c @@ -0,0 +1,127 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "n118.h" + +void (*N118_FixPRG)(void); +void (*N118_FixCHR)(void); + +void (*N118_pwrap)(uint16 A, uint16 V); +void (*N118_cwrap)(uint16 A, uint16 V); + +N118 n118; + +static SFORMAT StateRegs[] = { + { n118.reg, 8, "REGS" }, + { &n118.cmd, 1, "CMD0" }, + { 0 } +}; + +static void GENCWRAP(uint16 A, uint16 V) { + setchr1(A, V & 0x3F); +} + +static void GENPWRAP(uint16 A, uint16 V) { + setprg8(A, V & 0x0F); +} + +static void GENFIXCHR(void) { + N118_cwrap(0x0000, n118.reg[0] & (~1)); + N118_cwrap(0x0400, n118.reg[0] | 1); + N118_cwrap(0x0800, n118.reg[1] & (~1)); + N118_cwrap(0x0C00, n118.reg[1] | 1); + N118_cwrap(0x1000, n118.reg[2]); + N118_cwrap(0x1400, n118.reg[3]); + N118_cwrap(0x1800, n118.reg[4]); + N118_cwrap(0x1C00, n118.reg[5]); +} + +static void GENFIXPRG(void) { + N118_pwrap(0x8000, n118.reg[6]); + N118_pwrap(0xA000, n118.reg[7]); + N118_pwrap(0xC000, ~1); + N118_pwrap(0xE000, ~0); +} + +DECLFW(N118_Write) { + if (A & 0x01) { + n118.reg[n118.cmd & 0x07] = V; + } else { + n118.cmd = V; + } + N118_FixPRG(); + N118_FixCHR(); +} + +void N118_Power(void) { + n118.reg[0] = 0; + n118.reg[1] = 2; + n118.reg[2] = 4; + n118.reg[3] = 5; + n118.reg[4] = 6; + n118.reg[5] = 7; + n118.reg[6] = 0; + n118.reg[7] = 1; + n118.cmd = 0; + + N118_FixPRG(); + N118_FixCHR(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x9FFF, N118_Write); + + if (WRAM) { + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } +} + +static void StateRestore(int version) { + N118_FixPRG(); + N118_FixCHR(); +} + +void N118_Init(CartInfo *info, int wsize, int battery) { + N118_FixPRG = GENFIXPRG; + N118_FixCHR = GENFIXCHR; + + N118_pwrap = GENPWRAP; + N118_cwrap = GENCWRAP; + + WRAMSIZE = wsize * 1024; + + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } + + info->Power = N118_Power; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/hw/n118.h b/src/mappers/hw/n118.h new file mode 100644 index 000000000..0bfb456bc --- /dev/null +++ b/src/mappers/hw/n118.h @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _N118_H +#define _N118_H + +typedef struct __N118 { + uint8 reg[8]; + uint8 cmd; +} N118; + +extern N118 n118; + +DECLFW(N118_Write); + +void N118_Close(void); +void N118_Power(void); + +void N118_Init(CartInfo *info, int wsize, int battery); + +extern void (*N118_FixPRG)(void); +extern void (*N118_FixCHR)(void); + +extern void (*N118_pwrap)(uint16 A, uint16 V); +extern void (*N118_cwrap)(uint16 A, uint16 V); + +#endif /* _N118_H */ diff --git a/src/mappers/hw/pic16c5x.c b/src/mappers/hw/pic16c5x.c new file mode 100644 index 000000000..c5a79e6be --- /dev/null +++ b/src/mappers/hw/pic16c5x.c @@ -0,0 +1,1001 @@ +/* license:BSD-3-Clause + copyright-holders:Tony La Porta */ + /**************************************************************************\ + * Microchip PIC16C5x Emulator * + * * + * Copyright Tony La Porta * + * Originally written for the MAME project. * + * * + * * + * Addressing architecture is based on the Harvard addressing scheme. * + * * + * * + * **** Change Log **** * + * TLP (06-Apr-2003) * + * - First Public release. * + * BO (07-Apr-2003) Ver 1.01 * + * - Renamed 'sleep' function to 'sleepic' to avoid C conflicts. * + * TLP (09-Apr-2003) Ver 1.10 * + * - Fixed modification of file register $03 (Status). * + * - Corrected support for 7FFh (12-bit) size ROMs. * + * - The 'call' and 'goto' instructions weren't correctly handling the * + * STATUS page info correctly. * + * - The FSR register was incorrectly oring the data with 0xe0 when read. * + * - Prescaler masking information was set to 3 instead of 7. * + * - Prescaler assign bit was set to 4 instead of 8. * + * - Timer source and edge select flags/masks were wrong. * + * - Corrected the memory bank selection in GET/SET_REGFILE and also the * + * indirect register addressing. * + * BMP (18-May-2003) Ver 1.11 * + * - PIC16C5x_get_reg functions were missing 'returns'. * + * TLP (27-May-2003) Ver 1.12 * + * - Fixed the WatchDog timer count. * + * - The Prescaler rate was incorrectly being zeroed, instead of the * + * actual Prescaler counter in the CLRWDT and SLEEP instructions. * + * - Added masking to the FSR register. Upper unused bits are always 1. * + * TLP (27-Aug-2009) Ver 1.13 * + * - Indirect addressing was not taking into account special purpose * + * memory mapped locations. * + * - 'iorlw' instruction was saving the result to memory instead of * + * the W register. * + * - 'tris' instruction no longer modifies Port-C on PIC models that * + * do not have Port-C implemented. * + * TLP (07-Sep-2009) Ver 1.14 * + * - Edge sense control for the T0 count input was incorrectly reversed * + * LE (05-Feb-2017) Ver 1.15 * + * - Allow writing all bits of the status register except TO and PD. * + * This enables e.g. bcf, bsf or clrf to change the flags when the * + * status register is the destination. * + * - Changed rlf and rrf to update the carry flag in the last step. * + * Fixes the case where the status register is the destination. * + * hap (12-Feb-2017) Ver 1.16 * + * - Added basic support for the old GI PIC1650 and PIC1655. * + * - Made RTCC(aka T0CKI) pin an inputline handler. * + * * + * * + * **** Notes: **** * + * PIC WatchDog Timer has a separate internal clock. For the moment, we're * + * basing the count on a 4MHz input clock, since 4MHz is the typical * + * input frequency (but by no means always). * + * A single scaler is available for the Counter/Timer or WatchDog Timer. * + * When connected to the Counter/Timer, it functions as a Prescaler, * + * hence prescale overflows, tick the Counter/Timer. * + * When connected to the WatchDog Timer, it functions as a Postscaler * + * hence WatchDog Timer overflows, tick the Postscaler. This scenario * + * means that the WatchDog timeout occurs when the Postscaler has * + * reached the scaler rate value, not when the WatchDog reaches zero. * + * CLRWDT should prevent the WatchDog Timer from timing out and generating * + * a device reset, but how is not known. The manual also mentions that * + * the WatchDog Timer can only be disabled during ROM programming, and * + * no other means seem to exist??? * + * * + \**************************************************************************/ + +#include +#include "pic16c5x.h" + +/******************** CPU Internal Registers *******************/ +static uint16 m_PC; +static uint16 m_PREVPC; /* previous program counter */ +static uint8 m_W; +static uint8 m_OPTION; +static uint16 m_CONFIG; +static uint8 m_ALU; +static uint16 m_WDT; +static uint8 m_TRISA; +static uint8 m_TRISB; +static uint8 m_TRISC; +static uint16 m_STACK[2]; +static uint16 m_prescaler; /* Note: this is really an 8-bit register */ +static uint16 m_opcode; +static uint8 m_internalram[128]; +static uint8 *m_rom; + +static int m_icount; +static int m_picmodel; +static int m_delay_timer; +static uint16 m_temp_config; +static int m_rtcc; +static uint8 m_count_pending; /* boolean type */ +static int8 m_old_data; +static uint8 m_picRAMmask; +static uint16 m_picROMmask; +static int m_inst_cycles; +static int m_clock2cycle; + +/*address_space *m_program; +memory_access_cache<1, -1, ENDIANNESS_LITTLE> *m_cache; +address_space *m_data;*/ + +/* i/o handlers */ +static pic16c5x_readfunc m_read; +static pic16c5x_writefunc m_write; + +static void PIC16C5x(int program_width, int data_width, int picmodel, uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) +{ + m_rom = rom; + m_picmodel = picmodel; + m_temp_config = 0; + m_picRAMmask = ((1 << data_width) - 1); + m_picROMmask = ((1 << program_width) - 1); + m_read = _rd; + m_write = _wr; + m_PC = 0; + m_PREVPC = 0; + m_W = 0; + m_OPTION = 0; + m_CONFIG = 0; + m_ALU = 0; + m_WDT = 0; + m_TRISA = 0; + m_TRISB = 0; + m_TRISC = 0; + m_prescaler = 0; + m_icount = 0; + m_delay_timer = 0; + m_rtcc = 0; + m_count_pending = 0; + m_old_data = 0; + m_inst_cycles = 0; + m_clock2cycle = 0; +} + +void pic16c54_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x( 9, 5, 0x16C54, rom, _rd, _wr); } +void pic16c55_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x( 9, 5, 0x16C55, rom, _rd, _wr); } +void pic16c56_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x(10, 5, 0x16C56, rom, _rd, _wr); } +void pic16c57_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x(11, 7, 0x16C57, rom, _rd, _wr); } +void pic16c58_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x(11, 7, 0x16C58, rom, _rd, _wr); } +void pic1650_init (uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x( 9, 5, 0x1650, rom, _rd, _wr); } +void pic1655_init (uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x( 9, 5, 0x1655, rom, _rd, _wr); } + +#define M_OPCODE_B0 (m_opcode & 0xFF) +#define M_OPCODE_B1 ((m_opcode >> 8) & 0xFF) +#define M_OPCODE_S0 m_opcode + +#define M_RDRAM(A) m_internalram[A &m_picRAMmask] +#define M_WRTRAM(A,V) m_internalram[A &m_picRAMmask] =(V) +#define M_RDOP(A) m_rom[(A &m_picROMmask) <<1 |0] | m_rom[(A &m_picROMmask) <<1 |1] <<8 +#define ADDR_MASK 0x7ff + +#define TMR0 m_internalram[1] +#define PCL m_internalram[2] +#define STATUS m_internalram[3] +#define FSR m_internalram[4] +#define PORTA m_internalram[5] +#define PORTB m_internalram[6] +#define PORTC m_internalram[7] +#define PORTD m_internalram[8] +#define INDF M_RDRAM(FSR) + +#define ADDR (M_OPCODE_B0 & 0x1f) + + +/******** The following is the Status Flag register definition. *********/ + /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */ + /* | PA | TO | PD | Z | DC | C | */ +#define PA_REG 0xe0 /* PA Program Page Preselect - bit 8 is unused here */ +#define TO_FLAG 0x10 /* TO Time Out flag (WatchDog) */ +#define PD_FLAG 0x08 /* PD Power Down flag */ +#define Z_FLAG 0x04 /* Z Zero Flag */ +#define DC_FLAG 0x02 /* DC Digit Carry/Borrow flag (Nibble) */ +#define C_FLAG 0x01 /* C Carry/Borrow Flag (Byte) */ + +#define PA (STATUS & PA_REG) +#define TO (STATUS & TO_FLAG) +#define PD (STATUS & PD_FLAG) +#define ZERO (STATUS & Z_FLAG) +#define DC (STATUS & DC_FLAG) +#define CARRY (STATUS & C_FLAG) + + +/******** The following is the Option Flag register definition. *********/ + /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */ + /* | 0 | 0 | TOCS | TOSE | PSA | PS | */ +#define T0CS_FLAG 0x20 /* TOCS Timer 0 clock source select */ +#define T0SE_FLAG 0x10 /* TOSE Timer 0 clock source edge select */ +#define PSA_FLAG 0x08 /* PSA Prescaler Assignment bit */ +#define PS_REG 0x07 /* PS Prescaler Rate select */ + +#define T0CS (m_OPTION & T0CS_FLAG) +#define T0SE (m_OPTION & T0SE_FLAG) +#define PSA (m_OPTION & PSA_FLAG) +#define PS (m_OPTION & PS_REG) + + +/******** The following is the Config Flag register definition. *********/ + /* | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */ + /* | CP | WDTE | FOSC | */ + /* CP Code Protect (ROM read protect) */ +#define WDTE_FLAG 0x04 /* WDTE WatchDog Timer enable */ +#define FOSC_FLAG 0x03 /* FOSC Oscillator source select */ + +#define WDTE (m_CONFIG & WDTE_FLAG) +#define FOSC (m_CONFIG & FOSC_FLAG) + + +/************************************************************************ + * Shortcuts + ************************************************************************/ + +#define CLR(flagreg, flag) ( flagreg &= (uint8)(~flag) ) +#define SET(flagreg, flag) ( flagreg |= flag ) + + +/* Easy bit position selectors */ +#define POS ((M_OPCODE_B0 >> 5) & 7) +static const unsigned int bit_clr[8] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; +static const unsigned int bit_set[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; + +static INLINE void CALCULATE_Z_FLAG(void) +{ + if (m_ALU == 0) SET(STATUS, Z_FLAG); + else CLR(STATUS, Z_FLAG); +} + +static INLINE void CALCULATE_ADD_CARRY(void) +{ + if ((uint8)(m_old_data) > (uint8)(m_ALU)) { + SET(STATUS, C_FLAG); + } + else { + CLR(STATUS, C_FLAG); + } +} + +static INLINE void CALCULATE_ADD_DIGITCARRY(void) +{ + if (((uint8)(m_old_data) & 0x0f) > ((uint8)(m_ALU) & 0x0f)) { + SET(STATUS, DC_FLAG); + } + else { + CLR(STATUS, DC_FLAG); + } +} + +static INLINE void CALCULATE_SUB_CARRY(void) +{ + if ((uint8)(m_old_data) < (uint8)(m_ALU)) { + CLR(STATUS, C_FLAG); + } + else { + SET(STATUS, C_FLAG); + } +} + +static INLINE void CALCULATE_SUB_DIGITCARRY(void) +{ + if (((uint8)(m_old_data) & 0x0f) < ((uint8)(m_ALU) & 0x0f)) { + CLR(STATUS, DC_FLAG); + } + else { + SET(STATUS, DC_FLAG); + } +} + + + +static INLINE uint16 POP_STACK(void) +{ + uint16 data = m_STACK[1]; + m_STACK[1] = m_STACK[0]; + return (data & ADDR_MASK); +} +static INLINE void PUSH_STACK(uint16 data) +{ + m_STACK[0] = m_STACK[1]; + m_STACK[1] = (data & ADDR_MASK); +} + + + +static INLINE uint8 GET_REGFILE(uint32_t addr) /* Read from internal memory */ +{ + uint8 data = 0; + + if (addr == 0) { /* Indirect addressing */ + addr = (FSR & m_picRAMmask); + } + + if ((m_picmodel == 0x16C57) || (m_picmodel == 0x16C58)) { + addr |= (FSR & 0x60); /* FSR bits 6-5 are used for banking in direct mode */ + } + + if ((addr & 0x10) == 0) addr &= 0x0f; + + switch(addr) + { + case 0: /* Not an actual register, so return 0 */ + data = 0; + break; + case 4: data = (FSR | (uint8)(~m_picRAMmask)); + break; + case 5: /* read port A */ + if (m_picmodel == 0x1650) { + data = m_read(PIC16C5x_PORTA) & PORTA; + } + else if (m_picmodel == 0x1655) { + data = m_read(PIC16C5x_PORTA) & 0x0f; + } + else { + data = m_read(PIC16C5x_PORTA); + data &= m_TRISA; + data |= ((uint8)(~m_TRISA) & PORTA); + data &= 0x0f; /* 4-bit port (only lower 4 bits used) */ + } + break; + case 6: /* read port B */ + if (m_picmodel == 0x1650) { + data = m_read(PIC16C5x_PORTB) & PORTB; + } + else if (m_picmodel != 0x1655) { /* B is output-only on 1655 */ + data = m_read(PIC16C5x_PORTB); + data &= m_TRISB; + data |= ((uint8)(~m_TRISB) & PORTB); + } + break; + case 7: /* read port C */ + if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { + data = m_read(PIC16C5x_PORTC) & PORTC; + } + else if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { + data = m_read(PIC16C5x_PORTC); + data &= m_TRISC; + data |= ((uint8)(~m_TRISC) & PORTC); + } + else { /* PIC16C54, PIC16C56, PIC16C58 */ + data = M_RDRAM(addr); + } + break; + case 8: /* read port D */ + if (m_picmodel == 0x1650) { + data = m_read(PIC16C5x_PORTD) & PORTD; + } + else { + data = M_RDRAM(addr); + } + break; + default: data = M_RDRAM(addr); + break; + } + return data; +} + +static INLINE void STORE_REGFILE(uint32_t addr, uint8 data) /* Write to internal memory */ +{ + if (addr == 0) { /* Indirect addressing */ + addr = (FSR & m_picRAMmask); + } + + if ((m_picmodel == 0x16C57) || (m_picmodel == 0x16C58)) { + addr |= (FSR & 0x60); /* FSR bits 6-5 are used for banking in direct mode */ + } + + if ((addr & 0x10) == 0) addr &= 0x0f; + + switch(addr) + { + case 0: /* Not an actual register, nothing to save */ + break; + case 1: m_delay_timer = 2; /* Timer starts after next two instructions */ + if (PSA == 0) m_prescaler = 0; /* Must clear the Prescaler */ + TMR0 = data; + break; + case 2: PCL = data; + m_PC = ((STATUS & PA_REG) << 4) | data; + break; + case 3: STATUS = (STATUS & (TO_FLAG | PD_FLAG)) | (data & (uint8)(~(TO_FLAG | PD_FLAG))); + break; + case 4: FSR = (data | (uint8)(~m_picRAMmask)); + break; + case 5: /* write port A */ + if (m_picmodel == 0x1650) { + m_write(PIC16C5x_PORTA, data); + } + else if (m_picmodel != 0x1655) { /* A is input-only on 1655 */ + data &= 0x0f; /* 4-bit port (only lower 4 bits used) */ + m_write(PIC16C5x_PORTA, data & (uint8)(~m_TRISA)); + } + PORTA = data; + break; + case 6: /* write port B */ + if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { + m_write(PIC16C5x_PORTB, data); + } + else { + m_write(PIC16C5x_PORTB, data & (uint8)(~m_TRISB)); + } + PORTB = data; + break; + case 7: /* write port C */ + if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { + m_write(PIC16C5x_PORTC, data); + } + else if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { + m_write(PIC16C5x_PORTC, data & (uint8)(~m_TRISC)); + } + PORTC = data; /* also writes to RAM */ + break; + case 8: /* write port D */ + if (m_picmodel == 0x1650) { + m_write(PIC16C5x_PORTD, data); + } + PORTD = data; /* also writes to RAM */ + break; + default: M_WRTRAM(addr, data); + break; + } +} + + +static INLINE void STORE_RESULT(uint32_t addr, uint8 data) +{ + if (M_OPCODE_B0 & 0x20) + { + STORE_REGFILE(addr, data); + } + else + { + m_W = data; + } +} + + +/************************************************************************ + * Emulate the Instructions + ************************************************************************/ + +/* This following function is here to fill in the void for */ +/* the opcode call function. This function is never called. */ + + +static INLINE void illegal(void) +{ + /* printf("PIC16C5x: PC=%03x, Illegal opcode = %04x\n", (m_PC-1), M_OPCODE_S0); */ +} + +/* + Note: + According to the manual, if the STATUS register is the destination for an instruction that affects the Z, DC or C bits + then the write to these three bits is disabled. These bits are set or cleared according to the device logic. + To ensure this is correctly emulated, in instructions that write to the file registers, always change the status flags + *after* storing the result of the instruction. + e.g. CALCULATE_*, SET(STATUS,*_FLAG) and CLR(STATUS,*_FLAG) should appear as the last steps of the instruction emulation. +*/ + +static INLINE void addwf(void) +{ + m_old_data = GET_REGFILE(ADDR); + m_ALU = m_old_data + m_W; + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); + CALCULATE_ADD_CARRY(); + CALCULATE_ADD_DIGITCARRY(); +} + +static INLINE void andwf(void) +{ + m_ALU = GET_REGFILE(ADDR) & m_W; + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); +} + +static INLINE void andlw(void) +{ + m_ALU = M_OPCODE_B0 & m_W; + m_W = m_ALU; + CALCULATE_Z_FLAG(); +} + +static INLINE void bcf(void) +{ + m_ALU = GET_REGFILE(ADDR); + m_ALU &= bit_clr[POS]; + STORE_REGFILE(ADDR, m_ALU); +} + +static INLINE void bsf(void) +{ + m_ALU = GET_REGFILE(ADDR); + m_ALU |= bit_set[POS]; + STORE_REGFILE(ADDR, m_ALU); +} + +static INLINE void btfss(void) +{ + if ((GET_REGFILE(ADDR) & bit_set[POS]) == bit_set[POS]) + { + m_PC++; + PCL = m_PC & 0xff; + m_inst_cycles += 1; /* Add NOP cycles */ + } +} + +static INLINE void btfsc(void) +{ + if ((GET_REGFILE(ADDR) & bit_set[POS]) == 0) + { + m_PC++; + PCL = m_PC & 0xff; + m_inst_cycles += 1; /* Add NOP cycles */ + } +} + +static INLINE void call(void) +{ + PUSH_STACK(m_PC); + m_PC = ((STATUS & PA_REG) << 4) | M_OPCODE_B0; + m_PC &= 0x6ff; + PCL = m_PC & 0xff; +} + +static INLINE void clrw(void) +{ + m_W = 0; + SET(STATUS, Z_FLAG); +} + +static INLINE void clrf(void) +{ + STORE_REGFILE(ADDR, 0); + SET(STATUS, Z_FLAG); +} + +static INLINE void clrwdt(void) +{ + m_WDT = 0; + if (PSA) m_prescaler = 0; + SET(STATUS, TO_FLAG); + SET(STATUS, PD_FLAG); +} + +static INLINE void comf(void) +{ + m_ALU = (uint8)(~(GET_REGFILE(ADDR))); + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); +} + +static INLINE void decf(void) +{ + m_ALU = GET_REGFILE(ADDR) - 1; + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); +} + +static INLINE void decfsz(void) +{ + m_ALU = GET_REGFILE(ADDR) - 1; + STORE_RESULT(ADDR, m_ALU); + if (m_ALU == 0) + { + m_PC++; + PCL = m_PC & 0xff; + m_inst_cycles += 1; /* Add NOP cycles */ + } +} + +static INLINE void goto_op(void) +{ + m_PC = ((STATUS & PA_REG) << 4) | (M_OPCODE_S0 & 0x1ff); + m_PC &= ADDR_MASK; + PCL = m_PC & 0xff; +} + +static INLINE void incf(void) +{ + m_ALU = GET_REGFILE(ADDR) + 1; + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); +} + +static INLINE void incfsz(void) +{ + m_ALU = GET_REGFILE(ADDR) + 1; + STORE_RESULT(ADDR, m_ALU); + if (m_ALU == 0) + { + m_PC++; + PCL = m_PC & 0xff; + m_inst_cycles += 1; /* Add NOP cycles */ + } +} + +static INLINE void iorlw(void) +{ + m_ALU = M_OPCODE_B0 | m_W; + m_W = m_ALU; + CALCULATE_Z_FLAG(); +} + +static INLINE void iorwf(void) +{ + m_ALU = GET_REGFILE(ADDR) | m_W; + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); +} + +static INLINE void movf(void) +{ + m_ALU = GET_REGFILE(ADDR); + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); +} + +static INLINE void movlw(void) +{ + m_W = M_OPCODE_B0; +} + +static INLINE void movwf(void) +{ + STORE_REGFILE(ADDR, m_W); +} + +static INLINE void nop(void) +{ + /* Do nothing */ +} + +static INLINE void option(void) +{ + m_OPTION = m_W & (T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG); +} + +static INLINE void retlw(void) +{ + m_W = M_OPCODE_B0; + m_PC = POP_STACK(); + PCL = m_PC & 0xff; +} + +static INLINE void rlf(void) +{ + uint8 bit7; + m_ALU = GET_REGFILE(ADDR); + bit7 = m_ALU & 0x80; + m_ALU <<= 1; + if (STATUS & C_FLAG) m_ALU |= 1; + STORE_RESULT(ADDR, m_ALU); + if (bit7) SET(STATUS, C_FLAG); + else CLR(STATUS, C_FLAG); +} + +static INLINE void rrf(void) +{ + uint8 bit0; + m_ALU = GET_REGFILE(ADDR); + bit0 = m_ALU & 1; + m_ALU >>= 1; + if (STATUS & C_FLAG) m_ALU |= 0x80; + STORE_RESULT(ADDR, m_ALU); + if (bit0) SET(STATUS, C_FLAG); + else CLR(STATUS, C_FLAG); +} + +static INLINE void sleepic(void) +{ + if (WDTE) m_WDT = 0; + if (PSA) m_prescaler = 0; + SET(STATUS, TO_FLAG); + CLR(STATUS, PD_FLAG); +} + +static INLINE void subwf(void) +{ + m_old_data = GET_REGFILE(ADDR); + m_ALU = m_old_data - m_W; + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); + CALCULATE_SUB_CARRY(); + CALCULATE_SUB_DIGITCARRY(); +} + +static INLINE void swapf(void) +{ + m_ALU = ((GET_REGFILE(ADDR) << 4) & 0xf0); + m_ALU |= ((GET_REGFILE(ADDR) >> 4) & 0x0f); + STORE_RESULT(ADDR, m_ALU); +} + +static INLINE void tris(void) +{ + switch(M_OPCODE_B0 & 0x7) + { + case 5: if (m_TRISA == m_W) break; + else { m_TRISA = m_W | 0xf0; m_write(PIC16C5x_PORTA, 0x1000 | (PORTA & (uint8)(~m_TRISA) & 0x0f)); break; } + case 6: if (m_TRISB == m_W) break; + else { m_TRISB = m_W; m_write(PIC16C5x_PORTB, 0x1000 | (PORTB & (uint8)(~m_TRISB))); break; } + case 7: if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { + if (m_TRISC == m_W) break; + else { m_TRISC = m_W; m_write(PIC16C5x_PORTC, 0x1000 | (PORTC & (uint8)(~m_TRISC))); break; } + } + else { + illegal(); break; + } + default: illegal(); break; + } +} + +static INLINE void xorlw(void) +{ + m_ALU = m_W ^ M_OPCODE_B0; + m_W = m_ALU; + CALCULATE_Z_FLAG(); +} + +static INLINE void xorwf(void) +{ + m_ALU = GET_REGFILE(ADDR) ^ m_W; + STORE_RESULT(ADDR, m_ALU); + CALCULATE_Z_FLAG(); +} + + + + +/*********************************************************************** + * Opcode Table (Cycles, Instruction) + ***********************************************************************/ + +static const uint8 s_opcode_main_cycles[256] = { +/*00*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*08*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*10*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*18*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*20*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*28*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*30*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*38*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*40*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*48*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*50*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*58*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*60*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*68*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*70*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*78*/ 1, 1, 1, 1, 1, 1, 1, 1, + +/*80*/ 2, 2, 2, 2, 2, 2, 2, 2, +/*88*/ 2, 2, 2, 2, 2, 2, 2, 2, +/*90*/ 2, 2, 2, 2, 2, 2, 2, 2, +/*98*/ 2, 2, 2, 2, 2, 2, 2, 2, +/*A0*/ 2, 2, 2, 2, 2, 2, 2, 2, +/*A8*/ 2, 2, 2, 2, 2, 2, 2, 2, +/*B0*/ 2, 2, 2, 2, 2, 2, 2, 2, +/*B8*/ 2, 2, 2, 2, 2, 2, 2, 2, + +/*C0*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*C8*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*D0*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*D8*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*E0*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*E8*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*F0*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*F8*/ 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static const uint8 s_opcode_00x_cycles[16] = { +/*00*/ 1, 1, 1, 1, 1, 1, 1, 1, +/*08*/ 1, 1, 1, 1, 1, 1, 1, 1 +}; + + + +/**************************************************************************** + * Inits CPU emulation + ****************************************************************************/ + +enum +{ + PIC16C5x_PC=1, PIC16C5x_STK0, PIC16C5x_STK1, PIC16C5x_FSR, + PIC16C5x_W, PIC16C5x_ALU, PIC16C5x_STR, PIC16C5x_OPT, + PIC16C5x_TMR0, PIC16C5x_PRTA, PIC16C5x_PRTB, PIC16C5x_PRTC, PIC16C5x_PRTD, + PIC16C5x_WDT, PIC16C5x_TRSA, PIC16C5x_TRSB, PIC16C5x_TRSC, + PIC16C5x_PSCL +}; + +/**************************************************************************** + * Reset registers to their initial values + ****************************************************************************/ + +static INLINE void PIC16C5x_reset_regs(void) +{ + m_PC = m_picROMmask; + m_CONFIG = m_temp_config; + m_TRISA = 0xff; + m_TRISB = 0xff; + m_TRISC = 0xff; + m_OPTION = (T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG); + PCL = 0xff; + FSR |= (uint8)(~m_picRAMmask); + m_prescaler = 0; + m_delay_timer = 0; + m_inst_cycles = 0; + m_count_pending = FALSE; +} + +void pic16c5x_reset(uint8 hard) +{ + if (hard) { + memset(m_internalram, 0, sizeof(m_internalram)); + PIC16C5x_reset_regs(); + CLR(STATUS, PA_REG); + SET(STATUS, (TO_FLAG | PD_FLAG)); + m_icount = 0; + m_clock2cycle = 0; + } else { + SET(STATUS, (TO_FLAG | PD_FLAG | Z_FLAG | DC_FLAG | C_FLAG)); + PIC16C5x_reset_regs(); + } +} + +void pic16c5x_set_config(uint16 data) +{ + m_temp_config = data; +} + + + +/**************************************************************************** + * WatchDog + ****************************************************************************/ + +static INLINE void PIC16C5x_update_watchdog(int counts) +{ + /* WatchDog is set up to count 18,000 (0x464f hex) ticks to provide */ + /* the timeout period of 0.018ms based on a 4MHz input clock. */ + /* Note: the 4MHz clock should be divided by the PIC16C5x_CLOCK_DIVIDER */ + /* which effectively makes the PIC run at 1MHz internally. */ + + /* If the current instruction is CLRWDT or SLEEP, don't update the WDT */ + + if ((M_OPCODE_S0 != 3) && (M_OPCODE_S0 != 4)) + { + uint16 old_WDT = m_WDT; + + m_WDT -= counts; + + if (m_WDT > 0x464f) { + m_WDT = 0x464f - (0xffff - m_WDT); + } + + if (((old_WDT != 0) && (old_WDT < m_WDT)) || (m_WDT == 0)) + { + if (PSA) { + m_prescaler++; + if (m_prescaler >= (1 << PS)) { /* Prescale values from 1 to 128 */ + m_prescaler = 0; + CLR(STATUS, TO_FLAG); + /* PIC16C5x_soft_reset(); */ + } + } + else { + CLR(STATUS, TO_FLAG); + /* PIC16C5x_soft_reset(); */ + } + } + } +} + + +/**************************************************************************** + * Update Timer + ****************************************************************************/ + +static INLINE void PIC16C5x_update_timer(int counts) +{ + if (PSA == 0) { + m_prescaler += counts; + if (m_prescaler >= (2 << PS)) { /* Prescale values from 2 to 256 */ + TMR0 += (m_prescaler / (2 << PS)); + m_prescaler %= (2 << PS); /* Overflow prescaler */ + } + } + else { + TMR0 += counts; + } +} + +void pic16c5x_set_input(int line, int state) +{ + switch (line) + { + /* RTCC/T0CKI pin */ + case PIC16C5x_RTCC: + if (T0CS && state != m_rtcc) /* Count mode, edge triggered */ + if ((T0SE && !state) || (!T0SE && state)) + m_count_pending = TRUE; + + m_rtcc = state; + break; + + default: + break; + } +} + + +void pic16c5x_run(void) +{ + if ((++m_clock2cycle &3) ==0) m_icount++; + + while (m_icount > 0) { + if (PD == 0) /* Sleep Mode */ + { + m_count_pending = FALSE; + m_inst_cycles = 1; + if (WDTE) { + PIC16C5x_update_watchdog(1); + } + } + else + { + if (m_count_pending) { /* RTCC/T0CKI clocked while in Count mode */ + m_count_pending = FALSE; + PIC16C5x_update_timer(1); + } + + m_PREVPC = m_PC; + + M_OPCODE_S0 = M_RDOP(m_PC); + /* printf("%04X: %03X %03X\n", m_PC, M_OPCODE_S0, M_OPCODE_B0); */ + m_PC++; + PCL++; + + if (m_picmodel == 0x1650 || m_picmodel == 0x1655 || (M_OPCODE_S0 & 0xff0) != 0x000) { /* Do all opcodes except the 00? ones */ + uint8 b1 = (M_OPCODE_S0 >> 4) & 0xff; + m_inst_cycles = s_opcode_main_cycles[b1]; + switch (b1) { + #include "pic16c5x_ops_main.inc" + } + } + else { /* Opcode 0x00? has many opcodes in its minor nibble */ + uint8 b1 = M_OPCODE_B0 & 0x1f; + m_inst_cycles = s_opcode_00x_cycles[b1]; + switch (b1) { + #include "pic16c5x_ops_00x.inc" + } + } + + if (!T0CS) { /* Timer mode */ + if (m_delay_timer) { + m_delay_timer--; + } + else { + PIC16C5x_update_timer(m_inst_cycles); + } + } + if (WDTE) { + PIC16C5x_update_watchdog(m_inst_cycles); + } + } + + m_icount -= m_inst_cycles; + } +} + +void AddExState(void *v, uint32 s, int type, char *desc); + +void pic16c5x_add_statesinfo(void) { + AddExState(&m_PC, sizeof(m_PC), 0, "PC00"); + AddExState(&m_PREVPC, sizeof(m_PREVPC), 0, "PRPC"); + AddExState(&m_W, sizeof(m_W), 0, "W000"); + AddExState(&m_OPTION, sizeof(m_OPTION), 0, "OPT0"); + AddExState(&m_CONFIG, sizeof(m_CONFIG), 0, "CONF"); + AddExState(&m_ALU, sizeof(m_ALU), 0, "ALU"); + AddExState(&m_WDT, sizeof(m_WDT), 0, "WDT"); + AddExState(&m_TRISA, sizeof(m_TRISA), 0, "TRSA"); + AddExState(&m_TRISB, sizeof(m_TRISB), 0, "TRSB"); + AddExState(&m_TRISC, sizeof(m_TRISC), 0, "TRSC"); + AddExState(&m_STACK[0], sizeof(m_STACK[0]), 0, "STC0"); + AddExState(&m_STACK[1], sizeof(m_STACK[1]), 0, "STC1"); + AddExState(&m_prescaler, sizeof(m_prescaler), 0, "PSCL"); + AddExState(&m_opcode, sizeof(m_opcode), 0, "OPS0"); + AddExState(m_internalram, sizeof(m_internalram), 0, "IRAM"); + AddExState(&m_icount, sizeof(m_icount), 0, "ICNT"); + AddExState(&m_delay_timer, sizeof(m_delay_timer), 0, "DTIM"); + AddExState(&m_rtcc, sizeof(m_rtcc), 0, "RTCC"); + AddExState(&m_count_pending, sizeof(m_count_pending), 0, "CNTP"); + AddExState(&m_inst_cycles, sizeof(m_inst_cycles), 0, "ICYC"); + AddExState(&m_clock2cycle, sizeof(m_clock2cycle), 0, "CL2C"); +} \ No newline at end of file diff --git a/src/mappers/hw/pic16c5x.h b/src/mappers/hw/pic16c5x.h new file mode 100644 index 000000000..67c03dc17 --- /dev/null +++ b/src/mappers/hw/pic16c5x.h @@ -0,0 +1,57 @@ +/* license:BSD-3-Clause */ +/* copyright-holders:Tony La Porta */ + /**************************************************************************\ + * Microchip PIC16C5x_ Emulator * + * * + * Copyright Tony La Porta * + * Originally written for the MAME project. * + * * + * * + * Addressing architecture is based on the Harvard addressing scheme. * + * * + \**************************************************************************/ + +#ifndef _PIC16C5x_H +#define _PIC16C5x_H + +#include "../../fceu-types.h" + +typedef uint8 (*pic16c5x_readfunc)(int); +typedef void (*pic16c5x_writefunc)(int, int); + +enum { + PIC16C5x_RTCC = 0 +}; + + +/* in the mid-90s RTCC was renamed to T0CKI */ +#define PIC16C5x_T0CKI PIC16C5x_RTCC + +/* i/o ports */ +enum { + PIC16C5x_PORTA = 0, + PIC16C5x_PORTB, + PIC16C5x_PORTC, + PIC16C5x_PORTD +}; + +/**************************************************************************** + * Function to configure the CONFIG register. This is actually hard-wired + * during ROM programming, so should be called in the driver INIT, with + * the value if known (available in HEX dumps of the ROM). + */ +void pic16c5x_set_input(int line, int state); +void pic16c5x_set_config(uint16 data); +void pic16c5x_reset(uint8 hard); +void pic16c5x_run(void); +void pic16c5x_add_statesinfo(void); + +void pic16c54_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); +void pic16c55_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); +void pic16c56_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); +void pic16c57_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); +void pic16c58_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); +void pic1650_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); +void pic1655_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); + +#endif /* _PIC16C5x_H */ diff --git a/src/mappers/hw/pic16c5x_ops_00x.inc b/src/mappers/hw/pic16c5x_ops_00x.inc new file mode 100644 index 000000000..67f058efc --- /dev/null +++ b/src/mappers/hw/pic16c5x_ops_00x.inc @@ -0,0 +1,16 @@ +case 0x00: nop(); break; +case 0x01: illegal(); break; +case 0x02: option(); break; +case 0x03: sleepic(); break; +case 0x04: clrwdt(); break; +case 0x05: tris(); break; +case 0x06: tris(); break; +case 0x07: tris(); break; +case 0x08: illegal(); break; +case 0x09: illegal(); break; +case 0x0A: illegal(); break; +case 0x0B: illegal(); break; +case 0x0C: illegal(); break; +case 0x0D: illegal(); break; +case 0x0E: illegal(); break; +case 0x0F: illegal(); break; \ No newline at end of file diff --git a/src/mappers/hw/pic16c5x_ops_main.inc b/src/mappers/hw/pic16c5x_ops_main.inc new file mode 100644 index 000000000..f054d548f --- /dev/null +++ b/src/mappers/hw/pic16c5x_ops_main.inc @@ -0,0 +1,287 @@ +case 0x00: nop(); break; +case 0x01: illegal(); break; +case 0x02: movwf(); break; +case 0x03: movwf(); break; +case 0x04: clrw(); break; +case 0x05: illegal(); break; +case 0x06: clrf(); break; +case 0x07: clrf(); break; +/*08*/ +case 0x08: subwf(); break; +case 0x09: subwf(); break; +case 0x0A: subwf(); break; +case 0x0B: subwf(); break; +case 0x0C: decf(); break; +case 0x0D: decf(); break; +case 0x0E: decf(); break; +case 0x0F: decf(); break; +/*10*/ +case 0x10: iorwf(); break; +case 0x11: iorwf(); break; +case 0x12: iorwf(); break; +case 0x13: iorwf(); break; +case 0x14: andwf(); break; +case 0x15: andwf(); break; +case 0x16: andwf(); break; +case 0x17: andwf(); break; +/*18*/ +case 0x18: xorwf(); break; +case 0x19: xorwf(); break; +case 0x1A: xorwf(); break; +case 0x1B: xorwf(); break; +case 0x1C: addwf(); break; +case 0x1D: addwf(); break; +case 0x1E: addwf(); break; +case 0x1F: addwf(); break; +/*20*/ +case 0x20: movf(); break; +case 0x21: movf(); break; +case 0x22: movf(); break; +case 0x23: movf(); break; +case 0x24: comf(); break; +case 0x25: comf(); break; +case 0x26: comf(); break; +case 0x27: comf(); break; +/*28*/ +case 0x28: incf(); break; +case 0x29: incf(); break; +case 0x2A: incf(); break; +case 0x2B: incf(); break; +case 0x2C: decfsz(); break; +case 0x2D: decfsz(); break; +case 0x2E: decfsz(); break; +case 0x2F: decfsz(); break; +/*30*/ +case 0x30: rrf(); break; +case 0x31: rrf(); break; +case 0x32: rrf(); break; +case 0x33: rrf(); break; +case 0x34: rlf(); break; +case 0x35: rlf(); break; +case 0x36: rlf(); break; +case 0x37: rlf(); break; +/*38*/ +case 0x38: swapf(); break; +case 0x39: swapf(); break; +case 0x3A: swapf(); break; +case 0x3B: swapf(); break; +case 0x3C: incfsz(); break; +case 0x3D: incfsz(); break; +case 0x3E: incfsz(); break; +case 0x3F: incfsz(); break; +/*40*/ +case 0x40: bcf(); break; +case 0x41: bcf(); break; +case 0x42: bcf(); break; +case 0x43: bcf(); break; +case 0x44: bcf(); break; +case 0x45: bcf(); break; +case 0x46: bcf(); break; +case 0x47: bcf(); break; +/*48*/ +case 0x48: bcf(); break; +case 0x49: bcf(); break; +case 0x4A: bcf(); break; +case 0x4B: bcf(); break; +case 0x4C: bcf(); break; +case 0x4D: bcf(); break; +case 0x4E: bcf(); break; +case 0x4F: bcf(); break; +/*50*/ +case 0x50: bsf(); break; +case 0x51: bsf(); break; +case 0x52: bsf(); break; +case 0x53: bsf(); break; +case 0x54: bsf(); break; +case 0x55: bsf(); break; +case 0x56: bsf(); break; +case 0x57: bsf(); break; +/*58*/ +case 0x58: bsf(); break; +case 0x59: bsf(); break; +case 0x5A: bsf(); break; +case 0x5B: bsf(); break; +case 0x5C: bsf(); break; +case 0x5D: bsf(); break; +case 0x5E: bsf(); break; +case 0x5F: bsf(); break; +/*60*/ +case 0x60: btfsc(); break; +case 0x61: btfsc(); break; +case 0x62: btfsc(); break; +case 0x63: btfsc(); break; +case 0x64: btfsc(); break; +case 0x65: btfsc(); break; +case 0x66: btfsc(); break; +case 0x67: btfsc(); break; +/*68*/ +case 0x68: btfsc(); break; +case 0x69: btfsc(); break; +case 0x6A: btfsc(); break; +case 0x6B: btfsc(); break; +case 0x6C: btfsc(); break; +case 0x6D: btfsc(); break; +case 0x6E: btfsc(); break; +case 0x6F: btfsc(); break; +/*70*/ +case 0x70: btfss(); break; +case 0x71: btfss(); break; +case 0x72: btfss(); break; +case 0x73: btfss(); break; +case 0x74: btfss(); break; +case 0x75: btfss(); break; +case 0x76: btfss(); break; +case 0x77: btfss(); break; +/*78*/ +case 0x78: btfss(); break; +case 0x79: btfss(); break; +case 0x7A: btfss(); break; +case 0x7B: btfss(); break; +case 0x7C: btfss(); break; +case 0x7E: btfss(); break; +case 0x7D: btfss(); break; +case 0x7F: btfss(); break; +/*80*/ +case 0x80: retlw(); break; +case 0x81: retlw(); break; +case 0x82: retlw(); break; +case 0x83: retlw(); break; +case 0x84: retlw(); break; +case 0x85: retlw(); break; +case 0x86: retlw(); break; +case 0x87: retlw(); break; +/*88*/ +case 0x88: retlw(); break; +case 0x89: retlw(); break; +case 0x8A: retlw(); break; +case 0x8B: retlw(); break; +case 0x8C: retlw(); break; +case 0x8D: retlw(); break; +case 0x8E: retlw(); break; +case 0x8F: retlw(); break; +/*90*/ +case 0x90: call(); break; +case 0x91: call(); break; +case 0x92: call(); break; +case 0x93: call(); break; +case 0x94: call(); break; +case 0x95: call(); break; +case 0x96: call(); break; +case 0x97: call(); break; +/*98*/ +case 0x98: call(); break; +case 0x99: call(); break; +case 0x9A: call(); break; +case 0x9B: call(); break; +case 0x9C: call(); break; +case 0x9D: call(); break; +case 0x9E: call(); break; +case 0x9F: call(); break; +/*A0*/ +case 0xA0: goto_op(); break; +case 0xA1: goto_op(); break; +case 0xA2: goto_op(); break; +case 0xA3: goto_op(); break; +case 0xA4: goto_op(); break; +case 0xA5: goto_op(); break; +case 0xA6: goto_op(); break; +case 0xA7: goto_op(); break; +/*A8*/ +case 0xA8: goto_op(); break; +case 0xA9: goto_op(); break; +case 0xAA: goto_op(); break; +case 0xAB: goto_op(); break; +case 0xAC: goto_op(); break; +case 0xAD: goto_op(); break; +case 0xAE: goto_op(); break; +case 0xAF: goto_op(); break; +/*B0*/ +case 0xB0: goto_op(); break; +case 0xB1: goto_op(); break; +case 0xB2: goto_op(); break; +case 0xB3: goto_op(); break; +case 0xB4: goto_op(); break; +case 0xB5: goto_op(); break; +case 0xB6: goto_op(); break; +case 0xB7: goto_op(); break; +/*B8*/ +case 0xB8: goto_op(); break; +case 0xB9: goto_op(); break; +case 0xBA: goto_op(); break; +case 0xBB: goto_op(); break; +case 0xBC: goto_op(); break; +case 0xBD: goto_op(); break; +case 0xBE: goto_op(); break; +case 0xBF: goto_op(); break; +/*C0*/ +case 0xC0: movlw(); break; +case 0xC1: movlw(); break; +case 0xC2: movlw(); break; +case 0xC3: movlw(); break; +case 0xC4: movlw(); break; +case 0xC5: movlw(); break; +case 0xC6: movlw(); break; +case 0xC7: movlw(); break; +/*C8*/ +case 0xC8: movlw(); break; +case 0xC9: movlw(); break; +case 0xCA: movlw(); break; +case 0xCB: movlw(); break; +case 0xCC: movlw(); break; +case 0xCD: movlw(); break; +case 0xCE: movlw(); break; +case 0xCF: movlw(); break; +/*D0*/ +case 0xD0: iorlw(); break; +case 0xD1: iorlw(); break; +case 0xD2: iorlw(); break; +case 0xD3: iorlw(); break; +case 0xD4: iorlw(); break; +case 0xD5: iorlw(); break; +case 0xD6: iorlw(); break; +case 0xD7: iorlw(); break; +/*D8*/ +case 0xD8: iorlw(); break; +case 0xD9: iorlw(); break; +case 0xDA: iorlw(); break; +case 0xDB: iorlw(); break; +case 0xDC: iorlw(); break; +case 0xDD: iorlw(); break; +case 0xDE: iorlw(); break; +case 0xDF: iorlw(); break; +/*E0*/ +case 0xE0: andlw(); break; +case 0xE1: andlw(); break; +case 0xE2: andlw(); break; +case 0xE3: andlw(); break; +case 0xE4: andlw(); break; +case 0xE5: andlw(); break; +case 0xE6: andlw(); break; +case 0xE7: andlw(); break; +/*E8*/ +case 0xE8: andlw(); break; +case 0xE9: andlw(); break; +case 0xEA: andlw(); break; +case 0xEB: andlw(); break; +case 0xEC: andlw(); break; +case 0xED: andlw(); break; +case 0xEE: andlw(); break; +case 0xEF: andlw(); break; +/*F0*/ +case 0xF0: xorlw(); break; +case 0xF1: xorlw(); break; +case 0xF2: xorlw(); break; +case 0xF3: xorlw(); break; +case 0xF4: xorlw(); break; +case 0xF5: xorlw(); break; +case 0xF6: xorlw(); break; +case 0xF7: xorlw(); break; +/*F8*/ +case 0xF8: xorlw(); break; +case 0xF9: xorlw(); break; +case 0xFA: xorlw(); break; +case 0xFB: xorlw(); break; +case 0xFC: xorlw(); break; +case 0xFD: xorlw(); break; +case 0xFE: xorlw(); break; +case 0xFF: xorlw(); break; diff --git a/src/mappers/hw/txc.c b/src/mappers/hw/txc.c new file mode 100644 index 000000000..98953e27a --- /dev/null +++ b/src/mappers/hw/txc.c @@ -0,0 +1,138 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * TXC/Micro Genius simplified mapper + * updated 06-2019 http://wiki.nesdev.com/w/index.php/INES_Mapper_036 + * + * Known games: + * - Strike Wolf (Asia) (Unl) + * - Policeman (Gluk Video) (unl) + * - F-15 City War (Spain) (Gluk Video) (Unl) + * + * TXC mappers, originally much complex banksitching + * + * 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang + * 01-22110-000 (52S ) - MGC-002 2-in-1 Gun + * 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block + * (079 ) - MGC-012 Poke Block + * 01-22110-200 (05-00002-010) (036 ) - MGC-014 Strike Wolf + * 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman + * 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior + * 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1 + * 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom + * 01-22200-400 (------------) (079 ) - ET.03 F-15 City War + * (172 ) - 1991 Du Ma Racing + * + */ + +/* added 2020-2-16 + * Updated based on latest source + * Mappers 36, 132, 173 + * Mappers 136, 147, 172 + */ + +#include "mapinc.h" +#include "txc.h" + +TXC txc; + +static void Dummyfunc(void) { } +static void (*WSync)(void) = Dummyfunc; + +static SFORMAT StateRegs[] = +{ + { &txc.accumulator, 1, "ACC0" }, + { &txc.inverter, 1, "INVR" }, + { &txc.staging, 1, "STG0" }, + { &txc.output, 1, "OUT0" }, + { &txc.increase, 1, "INC0" }, + { &txc.X, 1, "XFLG" }, + { &txc.Y, 1, "YFLG" }, + { &txc.invert, 1, "INVT" }, + { 0 } +}; + +DECLFR(TXC_Read) { + uint8 ret = CPU_OPENBUS; + if ((A & 0x103) == 0x100) { + ret = ((txc.accumulator & 0x07) | ((txc.inverter ^ txc.invert) & ~0x07)); + txc.Y = txc.X || ((ret & 0x10) != 0); + WSync(); + } + return ret; +} + +DECLFW(TXC_Write) { + if (A & 0x8000) { + txc.output = (txc.accumulator & 0x0F) | ((txc.inverter << 1) & 0x10); + } else { + switch (A & 0x103) { + case 0x100: + if (txc.increase) { + txc.accumulator++; + } else { + txc.accumulator = ((txc.accumulator & ~0x07) | ((txc.staging ^ txc.invert) & 0x07)); + } + break; + case 0x101: + txc.invert = (V & 0x01) ? 0xFF : 0x00; + break; + case 0x102: + txc.staging = V & 0x07; + txc.inverter = V & ~0x07; + break; + case 0x103: + txc.increase = ((V & 0x01) != 0); + break; + } + } + txc.X = txc.invert ? txc.A : txc.B; + txc.Y = txc.X || ((V & 0x10) != 0); + WSync(); +} + +static void TXCRegReset(void) { + WSync(); +} + +void TXC_Power(void) { + txc.output = 0; + txc.accumulator = 0; + txc.inverter = 0; + txc.staging = 0; + txc.increase = 0; + txc.invert = 0; + txc.X = 0; + txc.Y = 0; + txc.A = 0; + txc.B = 1; + TXCRegReset(); +} + +static void StateRestore(int version) { + WSync(); +} + +void TXC_Init(CartInfo *info, void (*proc)(void)) { + WSync = proc; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/hw/txc.h b/src/mappers/hw/txc.h new file mode 100644 index 000000000..589ec32ee --- /dev/null +++ b/src/mappers/hw/txc.h @@ -0,0 +1,46 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _TXC_H +#define _TXC_H + +typedef struct __TXC { + uint8 accumulator; + uint8 inverter; + uint8 staging; + uint8 output; + uint8 increase; + uint8 invert; + uint8 A; + uint8 B; + uint8 X; + uint8 Y; +} TXC; + +extern TXC txc; + +DECLFR(TXC_Read); +DECLFW(TXC_Write); + +void TXC_Power(void); + +void TXC_Init(CartInfo *info, void (*proc)(void)); + +#endif /* _TXC_H */ diff --git a/src/mappers/hw/vrc24.c b/src/mappers/hw/vrc24.c new file mode 100644 index 000000000..8a2791f9a --- /dev/null +++ b/src/mappers/hw/vrc24.c @@ -0,0 +1,277 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-2/VRC-4 Konami + * VRC-4 Pirate + * + * VRC2 + * Nickname PCB A0 A1 Registers iNES mapper submapper + * VRC2a 351618 A1 A0 $x000, $x002, $x001, $x003 22 0 + * VRC2b many† A0 A1 $x000, $x001, $x002, $x003 23 3 + * VRC2c 351948 A1 A0 $x000, $x002, $x001, $x003 25 3 + * VRC4 + * Nickname PCB A0 A1 Registers iNES mapper submapper + * VRC4a 352398 A1 A2 $x000, $x002, $x004, $x006 21 1 + * VRC4b 351406 A1 A0 $x000, $x002, $x001, $x003 25 1 + * VRC4c 352889 A6 A7 $x000, $x040, $x080, $x0C0 21 2 + * VRC4d 352400 A3 A2 $x000, $x008, $x004, $x00C 25 2 + * VRC4e 352396 A2 A3 $x000, $x004, $x008, $x00C 23 2 + * VRC4f - A0 A1 $x000, $x001, $x002, $x003 23 1 + * + */ + +#include "mapinc.h" +#include "vrc24.h" +#include "vrcirq.h" + +void (*VRC24_FixPRG)(void); +void (*VRC24_FixCHR)(void); +void (*VRC24_FixMIR)(void); + +void (*VRC24_pwrap)(uint16 A, uint16 V); +void (*VRC24_cwrap)(uint16 A, uint16 V); +void (*VRC24_miscWrite)(uint16 A, uint8 V); + +VRC24 vrc24; + +static SFORMAT StateRegs[] = { + { vrc24.prg, 2, "PREG" }, + { vrc24.chr, 16, "CREG" }, + { &vrc24.cmd, 1, "CMDR" }, + { &vrc24.mirr, 1, "MIRR" }, + { &vrc24.latch, 1, "LATC" }, + + { &vrc24.VRC4, 1, "VRC4" }, + { &vrc24.A0, 2, "ADR0" }, + { &vrc24.A1, 2, "ADR1" }, + + { 0 } +}; + +static void GENFIXPRG(void) { + if (vrc24.cmd & 2) { + VRC24_pwrap(0x8000, ~1); + VRC24_pwrap(0xC000, vrc24.prg[0]); + } else { + VRC24_pwrap(0x8000, vrc24.prg[0]); + VRC24_pwrap(0xC000, ~1); + } + VRC24_pwrap(0xA000, vrc24.prg[1]); + VRC24_pwrap(0xE000, ~0); +} + +static void GENFIXCHR(void) { + VRC24_cwrap(0x0000, vrc24.chr[0]); + VRC24_cwrap(0x0400, vrc24.chr[1]); + VRC24_cwrap(0x0800, vrc24.chr[2]); + VRC24_cwrap(0x0C00, vrc24.chr[3]); + VRC24_cwrap(0x1000, vrc24.chr[4]); + VRC24_cwrap(0x1400, vrc24.chr[5]); + VRC24_cwrap(0x1800, vrc24.chr[6]); + VRC24_cwrap(0x1C00, vrc24.chr[7]); +} + +static void GENFIXMIR(void) { + switch (vrc24.mirr & (vrc24.VRC4 ? 0x03 : 0x01)) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +static DECLFR(VRC24WRAMRead) { + A = 0x6000 | (A & (WRAMSIZE - 1)); + return CartBR(A); +} + +static DECLFW(VRC24WRAMWrite) { + A = 0x6000 | (A & (WRAMSIZE - 1)); + CartBW(A, V); +} + +static DECLFR(VRC24LatchRead) { + return (CPU_OPENBUS & ~0x01) | (vrc24.latch & 0x01); +} + +static DECLFW(VRC24LatchWrite) { + vrc24.latch = V; + VRC24_FixPRG(); + VRC24_FixCHR(); +} + +DECLFW(VRC24_Write) { + uint8 index; + + switch (A & 0xF000) { + case 0x8000: + case 0xA000: + vrc24.prg[(A >> 13) & 0x01] = V & 0x1F; + VRC24_FixPRG(); + break; + + case 0x9000: + index = ((A & vrc24.A1) ? 0x02 : 0x00) | ((A & vrc24.A0) ? 0x01 : 0x00); + switch (index & (vrc24.VRC4 ? 0x03 : 0x00)) { + case 0: + case 1: + if (V != 0xFF) { + vrc24.mirr = V; + VRC24_FixMIR(); + } + break; + case 2: + vrc24.cmd = V; + VRC24_FixPRG(); + break; + case 3: + if (VRC24_miscWrite) { + VRC24_miscWrite(A, V); + } + break; + } + break; + + case 0xF000: + index = ((A & vrc24.A1) ? 0x02 : 0x00) | ((A & vrc24.A0) ? 0x01 : 0x00); + switch (index) { + case 0x00: VRCIRQ_LatchNibble(V, 0); break; + case 0x01: VRCIRQ_LatchNibble(V, 1); break; + case 0x02: VRCIRQ_Control(V); break; + case 0x03: VRCIRQ_Acknowledge(); break; + } + break; + + default: + index = (((A - 0xB000) >> 11) & 0x06) | ((A & vrc24.A1) ? 0x01 : 0x00); + if (A & vrc24.A0) { + /* m25 can be 512K, rest are 256K or less */ + vrc24.chr[index] = (vrc24.chr[index] & 0x000F) | (V << 4); + } else { + vrc24.chr[index] = (vrc24.chr[index] & 0x0FF0) | (V & 0x0F); + } + VRC24_cwrap(index << 10, vrc24.chr[index]); + break; + } +} + +static void GENPWRAP(uint16 A, uint16 V) { + setprg8(A, V & 0x1F); +} + +static void GENCWRAP(uint16 A, uint16 V) { + setchr1(A, V & 0x1FF); +} + +void VRC24_IRQCPUHook(int a) { + VRCIRQ_CPUHook(a); +} + +void VRC24_Reset(void) { + vrc24.prg[0] = 0; + vrc24.prg[1] = 1; + + vrc24.chr[0] = 0; + vrc24.chr[1] = 1; + vrc24.chr[2] = 2; + vrc24.chr[3] = 3; + vrc24.chr[4] = 4; + vrc24.chr[5] = 5; + vrc24.chr[6] = 6; + vrc24.chr[7] = 7; + + vrc24.cmd = vrc24.mirr = 0; + + VRC24_FixPRG(); + VRC24_FixCHR(); +} + +void VRC24_Power(void) { + VRC24_Reset(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, VRC24_Write); + + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, VRC24WRAMRead); + SetWriteHandler(0x6000, 0x7FFF, VRC24WRAMWrite); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } else if (!vrc24.VRC4) { + /* microwire interface */ + SetReadHandler(0x6000, 0x6FFF, VRC24LatchRead); + SetWriteHandler(0x6000, 0x6FFF, VRC24LatchWrite); + } + + if (!CHR_ROM_SIZE_8K) { + setchr8(0); + } +} + +static void StateRestore(int version) { + VRC24_FixPRG(); + VRC24_FixCHR(); + VRC24_FixMIR(); +} + +void VRC24_Close(void) { +} + +void VRC24_Init(CartInfo *info, uint8 vrc4, uint32 A0, uint32 A1, int wram, int irqRepeated) { + VRC24_FixPRG = GENFIXPRG; + VRC24_FixCHR = GENFIXCHR; + VRC24_FixMIR = GENFIXMIR; + + VRC24_pwrap = GENPWRAP; + VRC24_cwrap = GENCWRAP; + VRC24_miscWrite = NULL; + + vrc24.A0 = A0; + vrc24.A1 = A1; + vrc24.VRC4 = vrc4; + + if (wram) { + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } else { + WRAMSIZE = 8192; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } + } + + AddExState(StateRegs, ~0, 0, NULL); + + info->Power = VRC24_Power; + info->Close = VRC24_Close; + GameStateRestore = StateRestore; + + VRCIRQ_Init(irqRepeated); + MapIRQHook = VRCIRQ_CPUHook; + AddExState(&VRCIRQ_StateRegs, ~0, 0, 0); +} diff --git a/src/mappers/hw/vrc24.h b/src/mappers/hw/vrc24.h new file mode 100644 index 000000000..797b2efba --- /dev/null +++ b/src/mappers/hw/vrc24.h @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _VRC24_H +#define _VRC24_H + +typedef enum { + VRC2a = 1, /* Mapper 22 */ + VRC2b, /* Mapper 23 */ + VRC2c, /* Mapper 25 */ + VRC4a, /* Mapper 21 */ + VRC4b, /* Mapper 25 */ + VRC4c, /* Mapper 21 */ + VRC4d, /* Mapper 25 */ + VRC4e, /* Mapper 23 */ + VRC4f, /* Mapper 23 */ + VRC4_544, + VRC4_559 +} VRC24Type; + +enum { + VRC2 = 0, + VRC4 +}; + +typedef struct __VRC24 { + uint8 prg[2]; + uint16 chr[8]; + uint8 cmd; + uint8 mirr; + uint8 latch; /* VRC2 $6000-$6FFF */ + + uint8 VRC4; /* type */ + uint16 A0; + uint16 A1; +} VRC24; + +extern VRC24 vrc24; + +DECLFW(VRC24_Write); + +void VRC24_IRQCPUHook(int a); +void VRC24_Reset(void); +void VRC24_Power(void); +void VRC24_Close(void); + +void VRC24_Init(CartInfo *info, uint8 vrc4, uint32 A0, uint32 A1, int wram, int irqRepeated); + +extern void (*VRC24_FixPRG)(void); +extern void (*VRC24_FixCHR)(void); +extern void (*VRC24_FixMIR)(void); + +extern void (*VRC24_pwrap)(uint16 A, uint16 V); +extern void (*VRC24_cwrap)(uint16 A, uint16 V); +extern void (*VRC24_miscWrite)(uint16 A, uint8 V); + +#endif /* _VRC24_H */ diff --git a/src/mappers/hw/vrc6.c b/src/mappers/hw/vrc6.c new file mode 100644 index 000000000..447b64c5d --- /dev/null +++ b/src/mappers/hw/vrc6.c @@ -0,0 +1,203 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-6 + * + */ + +#include "mapinc.h" +#include "vrc6.h" +#include "vrcirq.h" +#include "vrc6sound.h" + +static uint32 vrc6_A0; +static uint32 vrc6_A1; + +VRC6 vrc6; + +void (*VRC6_pwrap)(uint16 A, uint16 V); +void (*VRC6_cwrap)(uint16 A, uint16 V); + +static SFORMAT StateRegs[] = +{ + { vrc6.prg, 2, "PRG" }, + { vrc6.chr, 8, "CHR" }, + { &vrc6.mirr, 1, "MIRR" }, + + { 0 } +}; + +static void GENPWRAP(uint16 A, uint16 V) { + setprg8(A, V & 0x3F); +} + +static void GENCWRAP(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +void VRC6_FixMIR(void) { + switch (vrc6.mirr & 3) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +void VRC6_FixPRG(void) { + VRC6_pwrap(0x8000, (vrc6.prg[0] << 1) | 0x00); + VRC6_pwrap(0xa000, (vrc6.prg[0] << 1) | 0x01); + VRC6_pwrap(0xc000, vrc6.prg[1]); + VRC6_pwrap(0xe000, ~0); +} + +void VRC6_FixCHR(void) { + int i; + + for (i = 0; i < 8; i++) { + VRC6_cwrap(i << 10, vrc6.chr[i]); + } +} + +DECLFW(VRC6_Write) { + int index; + + A = (A & 0xF000) | ((A & vrc6_A1) ? 0x02 : 0x00) | ((A & vrc6_A0) ? 0x01 : 0x00); + switch (A & 0xF000) { + case 0x8000: + vrc6.prg[0] = V; + VRC6_pwrap(0x8000, (V << 1) | 0x00); + VRC6_pwrap(0xA000, (V << 1) | 0x01); + break; + case 0x9000: + VRC6Sound_Write(A, V); + break; + case 0xA000: + VRC6Sound_Write(A, V); + break; + case 0xB000: + VRC6Sound_Write(A, V); + if ((A & 0x03) == 0x03) { + vrc6.mirr = (V >> 2) & 3; + VRC6_FixMIR(); + } + break; + case 0xC000: + vrc6.prg[1] = V; + VRC6_pwrap(0xC000, V); + break; + case 0xD000: + case 0xE000: + index = ((A - 0xD000) >> 10) | (A & 0x03); + vrc6.chr[index] = V; + VRC6_cwrap(index << 10, V); + break; + case 0xF000: + index = A & 0x03; + switch (index) { + case 0x00: VRCIRQ_Latch(V); break; + case 0x01: VRCIRQ_Control(V); break; + case 0x02: VRCIRQ_Acknowledge(); break; + } + } +} + +void VRC6_IRQCPUHook(int a) { + VRCIRQ_CPUHook(a); +} + +void VRC6_Reset(void) { + vrc6.prg[0] = 0; + vrc6.prg[1] = 1; + + vrc6.chr[0] = 0; + vrc6.chr[1] = 1; + vrc6.chr[2] = 2; + vrc6.chr[3] = 3; + vrc6.chr[4] = 4; + vrc6.chr[5] = 5; + vrc6.chr[6] = 6; + vrc6.chr[7] = 7; + + vrc6.mirr = 0; + + VRC6_FixPRG(); + VRC6_FixCHR(); + VRC6_FixMIR(); +} + +void VRC6_Power(void) { + VRC6_Reset(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, VRC6_Write); + + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } +} + +void VRC6_Close(void) { +} + +void VRC6_Restore(int version) { + VRC6_FixPRG(); + VRC6_FixCHR(); + VRC6_FixMIR(); +} + +void VRC6_Init(CartInfo *info, uint32 A0, uint32 A1, int wram) { + VRC6_pwrap = GENPWRAP; + VRC6_cwrap = GENCWRAP; + + vrc6_A0 = A0; + vrc6_A1 = A1; + + if (wram) { + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } else if (info->mapper == 26) { + WRAMSIZE = 8192; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } + } + AddExState(StateRegs, ~0, 0, NULL); + + info->Power = VRC6_Power; + info->Close = VRC6_Close; + GameStateRestore = VRC6_Restore; + + VRCIRQ_Init(TRUE); + MapIRQHook = VRC6_IRQCPUHook; + AddExState(&VRCIRQ_StateRegs, ~0, 0, 0); + + VRC6Sound_ESI(); + VRC6Sound_AddStateInfo(); +} diff --git a/src/mappers/hw/vrc6.h b/src/mappers/hw/vrc6.h new file mode 100644 index 000000000..59f709082 --- /dev/null +++ b/src/mappers/hw/vrc6.h @@ -0,0 +1,49 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _VRC6_H +#define _VRC6_H + +typedef struct __VRC6 { + uint8 prg[2]; + uint8 chr[8]; + uint8 mirr; +} VRC6; + +extern VRC6 vrc6; + +DECLFW(VRC6_Write); + +void VRC6_Power(void); +void VRC6_Reset(void); +void VRC6_Close(void); +void VRC6_Restore(int version); +void VRC6_IRQCPUHook(int a); + +void VRC6_Init(CartInfo *info, uint32 A0, uint32 A1, int wram); + +void VRC6_FixPRG(void); +void VRC6_FixCHR(void); +void VRC6_FixMIR(void); + +extern void (*VRC6_pwrap)(uint16 A, uint16 V); +extern void (*VRC6_cwrap)(uint16 A, uint16 V); + +#endif /* _VRC6_H */ diff --git a/src/mappers/hw/vrc7.c b/src/mappers/hw/vrc7.c new file mode 100644 index 000000000..47590431e --- /dev/null +++ b/src/mappers/hw/vrc7.c @@ -0,0 +1,185 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "vrcirq.h" +#include "vrc7sound.h" +#include "vrc7.h" + +static uint32 vrc7_A0; +static uint32 vrc7_A1; + +VRC7 vrc7; + +void (*VRC7_pwrap)(uint16 A, uint16 V); +void (*VRC7_cwrap)(uint16 A, uint16 V); +void (*VRC7_mwrap)(uint8 V); + +static SFORMAT StateRegs[] = +{ + { vrc7.prg, 3, "PREG" }, + { vrc7.chr, 8, "CREG" }, + { &vrc7.mirr, 1, "MIRR" }, + + { 0 } +}; + +static void GENPWRAP(uint16 A, uint16 V) { + setprg8(A, V & 0x3F); +} + +static void GENCWRAP(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +static void GENMWRAP(uint8 V) { + vrc7.mirr = V; + + switch (vrc7.mirr & 3) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +void VRC7_FixPRG(void) { + setprg8r(0x10, 0x6000, 0); + VRC7_pwrap(0x8000, vrc7.prg[0]); + VRC7_pwrap(0xa000, vrc7.prg[1]); + VRC7_pwrap(0xc000, vrc7.prg[2]); + VRC7_pwrap(0xe000, ~0); +} + +void VRC7_FixCHR(void) { + int i; + for (i = 0; i < 8; i++) { + VRC7_cwrap(i << 10, vrc7.chr[i]); + } + + if (VRC7_mwrap) { + VRC7_mwrap(vrc7.mirr); + } +} + +DECLFW(VRC7_Write) { + int index; + switch (A & 0xF000) { + case 0x8000: + case 0x9000: + index = ((A >> 11) & 0x02) | ((A & vrc7_A0) ? 0x01 : 0x00); + switch (index) { + case 0x00: + case 0x01: + case 0x02: + vrc7.prg[index] = V; + VRC7_FixPRG(); + break; + default: + VRC7Sound_Write(A, V); + break; + } + break; + + case 0xA000: + case 0xB000: + case 0xC000: + case 0xD000: + index = ((A - 0xA000) >> 11) | ((A & vrc7_A0) ? 0x01 : 0x00); + vrc7.chr[index] = V; + VRC7_FixCHR(); + break; + + case 0xE000: + case 0xF000: + index = ((A >> 11) & 0x02) | ((A & vrc7_A0) ? 0x01 : 0x00); + switch (index) { + case 0x00: if (VRC7_mwrap) VRC7_mwrap(V); break; + case 0x01: VRCIRQ_Latch(V); break; + case 0x02: VRCIRQ_Control(V); break; + case 0x03: VRCIRQ_Acknowledge(); break; + } + break; + } +} + +void VRC7_Power(void) { + vrc7.prg[0] = 0; + vrc7.prg[1] = 1; + vrc7.prg[2] = ~1; + + vrc7.chr[0] = 0; + vrc7.chr[1] = 1; + vrc7.chr[2] = 2; + vrc7.chr[3] = 3; + vrc7.chr[4] = 4; + vrc7.chr[5] = 5; + vrc7.chr[6] = 6; + vrc7.chr[7] = 7; + + vrc7.mirr = 0; + + VRC7_FixPRG(); + VRC7_FixCHR(); + + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, VRC7_Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +void VRC7_Close(void) { +} + +static void StateRestore(int version) { + VRC7_FixPRG(); + VRC7_FixCHR(); +} + +void VRC7_Init(CartInfo *info, uint32 A0, uint32 A1) { + VRC7_pwrap = GENPWRAP; + VRC7_cwrap = GENCWRAP; + VRC7_mwrap = GENMWRAP; + + vrc7_A0 = A0; + vrc7_A1 = A1; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(StateRegs, ~0, 0, NULL); + + info->Power = VRC7_Power; + info->Close = VRC7_Close; + GameStateRestore = StateRestore; + + VRCIRQ_Init(TRUE); + MapIRQHook = VRCIRQ_CPUHook; + AddExState(&VRCIRQ_StateRegs, ~0, 0, 0); + + VRC7Sound_ESI(); + VRC7Sound_AddStateInfo(); +} diff --git a/src/mappers/hw/vrc7.h b/src/mappers/hw/vrc7.h new file mode 100644 index 000000000..4d0788052 --- /dev/null +++ b/src/mappers/hw/vrc7.h @@ -0,0 +1,46 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _VRC7_H +#define _VRC7_H + +typedef struct __VRC7 { + uint8 prg[4]; + uint8 chr[8]; + uint8 mirr; +} VRC7; + +extern VRC7 vrc7; + +DECLFW(VRC7_Write); + +void VRC7_Power(void); +void VRC7_Close(void); + +void VRC7_Init(CartInfo *info, uint32 A0, uint32 A1); + +void VRC7_FixPRG(void); +void VRC7_FixCHR(void); + +extern void (*VRC7_pwrap)(uint16 A, uint16 V); +extern void (*VRC7_cwrap)(uint16 A, uint16 V); +extern void (*VRC7_mwrap)(uint8 V); + +#endif /* _VRC7_H */ diff --git a/src/mappers/hw/vrcirq.c b/src/mappers/hw/vrcirq.c new file mode 100644 index 000000000..f0396a874 --- /dev/null +++ b/src/mappers/hw/vrcirq.c @@ -0,0 +1,117 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "vrcirq.h" + +static int16 IRQPrescaler; +static uint8 IRQCount, IRQLatch, IRQd, IRQa, IRQm, IRQr; + +static uint8 IRQScanPos; +static uint8 IRQScanLut[3] = { 113, 113, 112 }; + +SFORMAT VRCIRQ_StateRegs[] = { + { &IRQPrescaler, 2, "PREC" }, + { &IRQCount, 1, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQd, 1, "IRQD" }, + { &IRQa, 1, "IRQA" }, + { &IRQm, 1, "IRQM" }, + { &IRQr, 1, "IRQR" }, + { &IRQScanPos, 1, "IPOS" }, + { 0 } +}; + +static void VRCIRQ_Clock(void) { + if (IRQCount == 0xFF) { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount = IRQLatch; + } else { + IRQCount++; + } +} + +void VRCIRQ_CPUHook(int a) { + if (!IRQa) { + return; + } + + while (a--) { + if (IRQm) { /* cycle mode */ + VRCIRQ_Clock(); + } else { + if (IRQPrescaler >= IRQScanLut[IRQScanPos]) { + VRCIRQ_Clock(); + IRQScanPos++; + if (IRQScanPos >= 3) IRQScanPos = 0; + IRQPrescaler = 0; + } else { + IRQPrescaler++; + } + } + } +} + +void VRCIRQ_Latch(uint8 V) { + IRQLatch = V; +} + +void VRCIRQ_LatchNibble(uint8 V, uint8 highBit) { + if (highBit) { + IRQLatch &= 0x0F; + IRQLatch |= V << 4; + } else { + IRQLatch &= 0xF0; + IRQLatch |= V & 0xF; + } +} + +void VRCIRQ_Control(uint8 V) { + IRQd = (V & 0x01) == 0x01; + IRQa = (V & 0x02) == 0x02; + IRQm = (V & 0x04) == 0x04; + + if (IRQa) { + IRQCount = IRQLatch; + IRQPrescaler = 0; + IRQScanPos = 0; + } + + X6502_IRQEnd(FCEU_IQEXT); +} + +void VRCIRQ_Acknowledge(void) { + if (IRQr == TRUE) { + IRQa = IRQd; + } + + X6502_IRQEnd(FCEU_IQEXT); +} + +void VRCIRQ_Init(int irqRepeated) { + IRQPrescaler = 0; + IRQCount = 0; + IRQLatch = 0; + IRQd = 0; + IRQa = 0; + IRQm = 0; + IRQr = irqRepeated ? TRUE : FALSE; + IRQScanPos = 0; +} diff --git a/src/mappers/hw/vrcirq.h b/src/mappers/hw/vrcirq.h new file mode 100644 index 000000000..87f989729 --- /dev/null +++ b/src/mappers/hw/vrcirq.h @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _VRCIRQ_H +#define _VRCIRQ_H + +void VRCIRQ_Init(int irqRepeated); +void VRCIRQ_Latch(uint8 V); +void VRCIRQ_LatchNibble(uint8 V, uint8 highBit); +void VRCIRQ_Control(uint8 V); +void VRCIRQ_Acknowledge(void); +void VRCIRQ_CPUHook(int a); + +extern SFORMAT VRCIRQ_StateRegs[]; + +#endif /* _VRCIRQ_H */ diff --git a/src/mappers/mapinc.h b/src/mappers/mapinc.h new file mode 100644 index 000000000..7423f8b7e --- /dev/null +++ b/src/mappers/mapinc.h @@ -0,0 +1,46 @@ +#ifndef _MAPINC_H +#define _MAPINC_H + +#include "../fceu-types.h" +#include "../x6502.h" +#include "../fceu.h" +#include "../ppu.h" +#include "../fceu-memory.h" +#include "../sound.h" +#include "../state.h" +#include "../cart.h" +#include "../cheat.h" +#include "../unif.h" +#include "../ines.h" +#include "../nsf.h" +#include "../x6502.h" +#include +#include + +extern uint8 *WRAM; +extern uint32 WRAMSIZE; + +extern uint8 *CHRRAM; +extern uint32 CHRRAMSIZE; + +extern uint8 *miscROM; +extern uint32 miscROMSIZE; + +#define CPU_OPENBUS X.DB + +#define PRG_PAGE_SIZE (16 * 1024) +#define CHR_PAGE_SIZE (8 * 1024) + +#define PRG_ROM_DATA ROM +#define PRG_ROM_SIZE_16K ROM_size + +#define CHR_ROM_DATA VROM +#define CHR_ROM_SIZE_8K VROM_size + +#define PRG_BANK_COUNT(x) ((PRG_ROM_SIZE_16K * PRG_PAGE_SIZE) / ((x) * 1024)) +#define CHR_BANK_COUNT(x) ((CHR_ROM_SIZE_8K * CHR_PAGE_SIZE) / ((x) * 1024)) + +#define MISC_ROM_DATA miscROM +#define MISC_ROM_SIZE miscROMSIZE + +#endif /* _MAPINC_H */ diff --git a/src/mappers/mapper.c b/src/mappers/mapper.c new file mode 100644 index 000000000..ad210bfec --- /dev/null +++ b/src/mappers/mapper.c @@ -0,0 +1,10 @@ +#include "mapinc.h" + +uint8 *WRAM; +uint32 WRAMSIZE; + +uint8 *CHRRAM; +uint32 CHRRAMSIZE; + +uint8 *miscROM; +uint32 miscROMSIZE; diff --git a/src/mappers/mapper000.c b/src/mappers/mapper000.c new file mode 100644 index 000000000..6b031dabc --- /dev/null +++ b/src/mappers/mapper000.c @@ -0,0 +1,73 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static void NROMClose(void) { +} + +static void NROMPower(void) { + if (PRG_ROM_SIZE_16K == (48 * 1024)) { /* NROM-368 */ + setprg16(0x4000, 0); + setprg16(0x8000, 1); + setprg16(0xC000, 2); + SetReadHandler(0x4800, 0xFFFF, CartBR); + } else { + setprg32(0x8000, 0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, 0); /* Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB */ + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } + } + + setchr8(0); +} + +void Mapper000_Init(CartInfo *info) { + info->Power = NROMPower; + info->Close = NROMClose; + + WRAMSIZE = 8192; + + if (info->submapper) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } + + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } + + if ((info->CRC32 == 0x4233B70E) || ((info->PRGCRC32 == 0x17E013A2) && CHR_ROM_SIZE_8K)) { + /* BADDUMP: A variant of Wild Ball with chrrom when its suppose to use chrram */ + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 1); + } +} diff --git a/src/mappers/mapper001.c b/src/mappers/mapper001.c new file mode 100644 index 000000000..3a18b3758 --- /dev/null +++ b/src/mappers/mapper001.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc1.h" + +static int DetectMMC1WRAMSize(CartInfo *info, int *saveRAM) { + int workRAM = 8; + + if (info->iNES2) { + workRAM = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; + *saveRAM = info->PRGRamSaveSize / 1024; + /* we only support sizes between 8K and 32K */ + if (workRAM > 0 && workRAM < 8) + workRAM = 8; + if (workRAM > 32) + workRAM = 32; + if (*saveRAM > 0 && *saveRAM < 8) + *saveRAM = 8; + if (*saveRAM > 32) + *saveRAM = 32; + /* save ram cannot be bigger than workram */ + if (*saveRAM > workRAM) { + *saveRAM = workRAM; + workRAM = 0; + } + } else if (info->battery) { + *saveRAM = 8; + } + if (workRAM > 8) { + FCEU_printf(" >8KB external WRAM present. Use NES 2.0 if you hack the ROM image.\n"); + } + return workRAM; +} + +static void M001PW(uint16 A, uint16 V) { + if (iNESCart.submapper == 5) { + setprg32(0x8000, 0); + } else { + setprg16(A, (MMC1_GetCHRBank(0) & 0x10) | (V & 0x0F)); + } +} + +void Mapper001_Init(CartInfo *info) { + int bs = 0; + int ws = DetectMMC1WRAMSize(info, &bs); + MMC1_Init(info, ws, bs); + MMC1_pwrap = M001PW; + mmc1_type = (info->submapper == 3) ? MMC1A : MMC1B; +} diff --git a/src/mappers/mapper002.c b/src/mappers/mapper002.c new file mode 100644 index 000000000..7c329069c --- /dev/null +++ b/src/mappers/mapper002.c @@ -0,0 +1,34 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, latch.data); + setprg16(0xC000, ~0); + setchr8(0); +} + +void Mapper002_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, (info->submapper == 2)); +} diff --git a/src/mappers/mapper003.c b/src/mappers/mapper003.c new file mode 100644 index 000000000..9a460a310 --- /dev/null +++ b/src/mappers/mapper003.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); /* Hayauchy IGO uses 2Kb or RAM */ + setprg32(0x8000, 0); + setchr8(latch.data); +} + +void Mapper003_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, (info->submapper == 2)); +} diff --git a/src/mappers/mapper004.c b/src/mappers/mapper004.c new file mode 100644 index 000000000..4376fe2e8 --- /dev/null +++ b/src/mappers/mapper004.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "mmc6.h" + +static void M004PW(uint16 A, uint16 V) { + setprg8(A, V & 0xFF); +} + +static void M004CW(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +void Mapper004_Init(CartInfo *info) { + int ws = 8; + + if (info->submapper == 1) { + MMC6_Init(info); + return; + } + + if (info->submapper == 5) { + Mapper249_Init(info); + return; + } + + if (!info->iNES2) { + if ((info->CRC32 == 0x93991433) || (info->CRC32 == 0xaf65aa84)) { + FCEU_printf( + "Low-G-Man can not work normally in the iNES format.\nThis game has been recognized by its CRC32 " + "value, and the appropriate changes will be made so it will run.\nIf you wish to hack this game, " + "you should use the UNIF format for your hack.\n\n"); + ws = 0; + } + } else { + ws = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; + } + + if ((info->submapper == 4) || (info->CRC32 == 0x97b6cb19)) { + isRevB = 0; /* MMC3A */ + } + + if ((info->CRC32 == 0x762653B1) && (ws < 8)) { + /* Mickey Mouse III - Dream Balloon [NikcDC v1.1] */ + ws = 8; + } + + MMC3_Init(info, ws, info->battery); + MMC3_pwrap = M004PW; + MMC3_cwrap = M004CW; +} diff --git a/src/mappers/mapper005.c b/src/mappers/mapper005.c new file mode 100644 index 000000000..8af73d339 --- /dev/null +++ b/src/mappers/mapper005.c @@ -0,0 +1,807 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* None of this code should use any of the iNES bank switching wrappers. */ + +#include "mapinc.h" +#include "mmc5sound.h" + +static INLINE void MMC5SPRVROM_BANK1(uint32 A, uint32 V) { + if (CHRptr[0]) { + V &= CHRmask1[0]; + MMC5SPRVPage[A >> 10] = &CHRptr[0][V << 10] - A; + } +} + +static INLINE void MMC5BGVROM_BANK1(uint32 A, uint32 V) { + if (CHRptr[0]) { + V &= CHRmask1[0]; MMC5BGVPage[A >> 10] = &CHRptr[0][V << 10] - A; + } +} + +static INLINE void MMC5SPRVROM_BANK2(uint32 A, uint32 V) { + if (CHRptr[0]) { + V &= CHRmask2[0]; MMC5SPRVPage[A >> 10] = MMC5SPRVPage[(A >> 10) + 1] = &CHRptr[0][V << 11] - A; + } +} + +static INLINE void MMC5BGVROM_BANK2(uint32 A, uint32 V) { + if (CHRptr[0]) { + V &= CHRmask2[0]; MMC5BGVPage[A >> 10] = MMC5BGVPage[(A >> 10) + 1] = &CHRptr[0][V << 11] - A; + } +} + +static INLINE void MMC5SPRVROM_BANK4(uint32 A, uint32 V) { + if (CHRptr[0]) { + V &= CHRmask4[0]; MMC5SPRVPage[A >> 10] = MMC5SPRVPage[(A >> 10) + 1] = MMC5SPRVPage[(A >> 10) + 2] = MMC5SPRVPage[(A >> 10) + 3] = &CHRptr[0][V << 12] - A; + } +} + +static INLINE void MMC5BGVROM_BANK4(uint32 A, uint32 V) { + if (CHRptr[0]) { + V &= CHRmask4[0]; MMC5BGVPage[A >> 10] = MMC5BGVPage[(A >> 10) + 1] = MMC5BGVPage[(A >> 10) + 2] = MMC5BGVPage[(A >> 10) + 3] = &CHRptr[0][V << 12] - A; + } +} + +static INLINE void MMC5SPRVROM_BANK8(uint32 V) { + if (CHRptr[0]) { + V &= CHRmask8[0]; MMC5SPRVPage[0] = MMC5SPRVPage[1] = MMC5SPRVPage[2] = MMC5SPRVPage[3] = MMC5SPRVPage[4] = MMC5SPRVPage[5] = MMC5SPRVPage[6] = MMC5SPRVPage[7] = &CHRptr[0][V << 13]; + } +} + +static INLINE void MMC5BGVROM_BANK8(uint32 V) { + if (CHRptr[0]) { + V &= CHRmask8[0]; MMC5BGVPage[0] = MMC5BGVPage[1] = MMC5BGVPage[2] = MMC5BGVPage[3] = MMC5BGVPage[4] = MMC5BGVPage[5] = MMC5BGVPage[6] = MMC5BGVPage[7] = &CHRptr[0][V << 13]; + } +} + +static uint8 PRGBanks[4]; +static uint8 WRAMPage; +static uint16 CHRBanksA[8], CHRBanksB[4]; +static uint8 WRAMMaskEnable[2]; +uint8 mmc5ABMode; /* A=0, B=1 */ + +static uint8 IRQScanline, IRQEnable; +static uint8 CHRMode, NTAMirroring, NTFill, ATFill; + +static uint8 MMC5IRQR; +static uint8 MMC5LineCounter; +static uint8 mmc5psize, mmc5vsize; +static uint8 mul[2]; + +static uint8 *MMC5fill = NULL; +static uint8 *ExRAM = NULL; +static uint8 MMC5battery = 0; + +static uint8 MMC5WRAMsize; /* configuration, not state */ +static uint8 MMC5WRAMIndex[8]; /* configuration, not state */ + +static uint8 MMC5ROMWrProtect[4]; +static uint8 MMC5MemIn[5]; + +static SFORMAT MMC5_StateRegs[] = { + { PRGBanks, 4, "PREG" }, + { CHRBanksA, 16, "CHRA" }, + { CHRBanksB, 8, "CHRB" }, + { &WRAMPage, 1, "WRMP" }, + { WRAMMaskEnable, 2, "WRMK" }, + { &mmc5ABMode, 1, "ABMD" }, + { &IRQScanline, 1, "IRQS" }, + { &IRQEnable, 1, "IRQE" }, + { &CHRMode, 1, "CHRM" }, + { &NTAMirroring, 1, "NTAM" }, + { &NTFill, 1, "NTFL" }, + { &ATFill, 1, "ATFL" }, + { &MMC5IRQR, 1, "IRQR" }, + { &MMC5LineCounter, 1, "LCTR" }, + { &mmc5psize, 1, "PSIZ" }, + { &mmc5vsize, 1, "VSIZ" }, + { mul, 2, "MUL0" }, + { MMC5ROMWrProtect, 4, "PROT" }, + { MMC5MemIn, 5, "MEMN" }, + + { 0 } +}; + +uint8 *MMC5BGVRAMADR(uint32 A) { +#ifdef NEWPPU + if (newppu) { + if (Sprite16) { + bool isPattern = PPUON != 0; + if (ppuphase == PPUPHASE_OBJ && isPattern) { + return &ABANKS[(A) >> 10][(A)]; + } + if (ppuphase == PPUPHASE_BG && isPattern) { + return &BBANKS[(A) >> 10][(A)]; + } else if (mmc5ABMode == 0) { + return &ABANKS[(A) >> 10][(A)]; + } else { + return &BBANKS[(A) >> 10][(A)]; + } + } else { + return &ABANKS[(A) >> 10][(A)]; + } + } +#endif /* NEWPPU */ + + if (!Sprite16) { + if (mmc5ABMode == 0) { + return &ABANKS[(A) >> 10][(A)]; + } else { + return &BBANKS[(A) >> 10][(A)]; + } + } else { + return &BBANKS[(A) >> 10][(A)]; + } +} + +extern uint8 PALRAM[0x20]; +extern uint8 UPALRAM[0x03]; +extern uint32 NTRefreshAddr; + +#ifdef NEWPPU +static void mmc5_PPUWrite(uint32 A, uint8 V) { + uint32 tmp = A; + + if (tmp >= 0x3F00) { + if (!(tmp & 3)) { + if (!(tmp & 0xC)) { + PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F; + PALRAM[0x10] = PALRAM[0x14] = PALRAM[0x18] = PALRAM[0x1C] = V & 0x3F; + } else { + UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F; + } + } else { + PALRAM[tmp & 0x1F] = V & 0x3F; + } + } else if (tmp < 0x2000) { + if (PPUCHRRAM & (1 << (tmp >> 10))) { + VPage[tmp >> 10][tmp] = V; + } + } else { + if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) { + vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; + } + } +} + +uint8 mmc5_PPURead(uint32 A) { + bool split = false; + + if (newppu) { + if ((MMC5HackSPMode & 0x80) && !(MMC5HackCHRMode & 2)) { + int target = MMC5HackSPMode & 0x1f; + int side = MMC5HackSPMode & 0x40; + int ht = NTRefreshAddr & 31; + + if (side == 0) { + if (ht < target) { + split = true; + } + } else { + if (ht >= target) { + split = true; + } + } + } + } + + if (A < 0x2000) { + if (Sprite16) { + bool isPattern = !!PPUON; + + if (ppuphase == PPUPHASE_OBJ && isPattern) { + return ABANKS[(A) >> 10][(A)]; + } + if (ppuphase == PPUPHASE_BG && isPattern) { + if (split) { + return MMC5HackVROMPTR[MMC5HackSPPage * 0x1000 + (A & 0xFFF)]; + } + + /* uhhh call through to this more sophisticated function, only + * if it's really needed? we should probably reuse it + * completely, if we can + */ + if (MMC5HackCHRMode == 1) { + return *FCEUPPU_GetCHR(A, NTRefreshAddr); + } + + return BBANKS[(A) >> 10][(A)]; + } else if (mmc5ABMode == 0) { + return ABANKS[(A) >> 10][(A)]; + } else { + return BBANKS[(A) >> 10][(A)]; + } + } else { + if (ppuphase == PPUPHASE_BG && ScreenON) { + if (split) { + return MMC5HackVROMPTR[MMC5HackSPPage * 0x1000 + (A & 0xFFF)]; + } + + /* uhhh call through to this more sophisticated function, only + * if it's really needed? we should probably reuse it + * completely, if we can + */ + if (MMC5HackCHRMode == 1) { + return *FCEUPPU_GetCHR(A, NTRefreshAddr); + } + } + + return ABANKS[(A) >> 10][(A)]; + } + } else { + if (split) { + static const int kHack = -1; /* dunno if theres science to this or if it just fixes SDF + (cant be bothered to think about it) */ + int linetile = (newppu_get_scanline() + kHack) / 8 + MMC5HackSPScroll; + + /* REF NT: return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht; + REF AT: return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & + 0x1C) << 1) | ((ht & 0x1C) >> 2); */ + + if ((A & 0x3FF) >= 0x3C0) { + A &= ~(0x1C << 1); /* mask off VT */ + A |= (linetile & 0x1C) << 1; /* mask on adjusted VT */ + return ExRAM[A & 0x3FF]; + } else { + A &= ~((0x1F << 5) | (1 << 0xB)); /* mask off VT and V */ + A |= (linetile & 31) << 5; /* mask on adjusted VT (V doesnt make */ + /* any sense, I think) */ + return ExRAM[A & 0x3FF]; + } + } + + if (MMC5HackCHRMode == 1) { + if ((A & 0x3FF) >= 0x3C0) { + uint8 byte = ExRAM[NTRefreshAddr & 0x3ff]; + + /* get attribute part and paste it 4x across the byte */ + byte >>= 6; + byte *= 0x55; + return byte; + } + } + + return vnapage[(A >> 10) & 0x3][A & 0x3FF]; + } +} +#endif /* NEWPPU */ + +static void BuildWRAMSizeTable(void) { + int x; + for (x = 0; x < 8; x++) { + switch (MMC5WRAMsize) { + case 0: MMC5WRAMIndex[x] = 255; break; /* X,X,X,X,X,X,X,X */ + case 1: MMC5WRAMIndex[x] = (x > 3) ? 255 : 0; break; /* 0,0,0,0,X,X,X,X */ + case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; /* 0,0,0,0,1,1,1,1 */ + case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; /* 0,1,2,3,X,X,X,X */ + case 8: MMC5WRAMIndex[x] = x; break; /* 0,1,2,3,4,5,6,7 */ + } + } +} + +static void MMC5CHRA(void) { + int x; + switch (mmc5vsize & 3) { + case 0: + setchr8(CHRBanksA[7]); + MMC5SPRVROM_BANK8(CHRBanksA[7]); + break; + case 1: + setchr4(0x0000, CHRBanksA[3]); + setchr4(0x1000, CHRBanksA[7]); + MMC5SPRVROM_BANK4(0x0000, CHRBanksA[3]); + MMC5SPRVROM_BANK4(0x1000, CHRBanksA[7]); + break; + case 2: + setchr2(0x0000, CHRBanksA[1]); + setchr2(0x0800, CHRBanksA[3]); + setchr2(0x1000, CHRBanksA[5]); + setchr2(0x1800, CHRBanksA[7]); + MMC5SPRVROM_BANK2(0x0000, CHRBanksA[1]); + MMC5SPRVROM_BANK2(0x0800, CHRBanksA[3]); + MMC5SPRVROM_BANK2(0x1000, CHRBanksA[5]); + MMC5SPRVROM_BANK2(0x1800, CHRBanksA[7]); + break; + case 3: + for (x = 0; x < 8; x++) { + setchr1(x << 10, CHRBanksA[x]); + MMC5SPRVROM_BANK1(x << 10, CHRBanksA[x]); + } + break; + } +} + +static void MMC5CHRB(void) { + int x; + switch (mmc5vsize & 3) { + case 0: + setchr8(CHRBanksB[3]); + MMC5BGVROM_BANK8(CHRBanksB[3]); + break; + case 1: + setchr4(0x0000, CHRBanksB[3]); + setchr4(0x1000, CHRBanksB[3]); + MMC5BGVROM_BANK4(0x0000, CHRBanksB[3]); + MMC5BGVROM_BANK4(0x1000, CHRBanksB[3]); + break; + case 2: + setchr2(0x0000, CHRBanksB[1]); + setchr2(0x0800, CHRBanksB[3]); + setchr2(0x1000, CHRBanksB[1]); + setchr2(0x1800, CHRBanksB[3]); + MMC5BGVROM_BANK2(0x0000, CHRBanksB[1]); + MMC5BGVROM_BANK2(0x0800, CHRBanksB[3]); + MMC5BGVROM_BANK2(0x1000, CHRBanksB[1]); + MMC5BGVROM_BANK2(0x1800, CHRBanksB[3]); + break; + case 3: + for (x = 0; x < 8; x++) { + setchr1(x << 10, CHRBanksB[x & 3]); + MMC5BGVROM_BANK1(x << 10, CHRBanksB[x & 3]); + } + break; + } +} + +static void MMC5WRAM(uint32 A, uint32 V) { + V = MMC5WRAMIndex[V & 7]; + if (V != 255) { + setprg8r(0x10, A, V); + FCEU_CheatAddRAM(8, 0x6000, (WRAM + ((V * 8192) & (WRAMSIZE - 1)))); + MMC5MemIn[(A - 0x6000) >> 13] = 1; + } else { + MMC5MemIn[(A - 0x6000) >> 13] = 0; + } +} + +static void MMC5PRG(void) { + int x; + switch (mmc5psize & 3) { + case 0: + MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1; + setprg32(0x8000, ((PRGBanks[3] & 0x7F) >> 2)); + for (x = 0; x < 4; x++) { + MMC5MemIn[1 + x] = 1; + } + break; + case 1: + if (PRGBanks[1] & 0x80) { + MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 1; + setprg16(0x8000, (PRGBanks[1] >> 1)); + MMC5MemIn[1] = MMC5MemIn[2] = 1; + } else { + MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0; + MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE); + MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1); + } + MMC5MemIn[3] = MMC5MemIn[4] = 1; + MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1; + setprg16(0xC000, (PRGBanks[3] & 0x7F) >> 1); + break; + case 2: + if (PRGBanks[1] & 0x80) { + MMC5MemIn[1] = MMC5MemIn[2] = 1; + MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 1; + setprg16(0x8000, (PRGBanks[1] & 0x7F) >> 1); + } else { + MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0; + MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE); + MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1); + } + if (PRGBanks[2] & 0x80) { + MMC5ROMWrProtect[2] = 1; + MMC5MemIn[3] = 1; + setprg8(0xC000, PRGBanks[2] & 0x7F); + } else { + MMC5ROMWrProtect[2] = 0; + MMC5WRAM(0xC000, PRGBanks[2] & 7); + } + MMC5MemIn[4] = 1; + MMC5ROMWrProtect[3] = 1; + setprg8(0xE000, PRGBanks[3] & 0x7F); + break; + case 3: + for (x = 0; x < 3; x++) { + if (PRGBanks[x] & 0x80) { + MMC5ROMWrProtect[x] = 1; + setprg8(0x8000 + (x << 13), PRGBanks[x] & 0x7F); + MMC5MemIn[1 + x] = 1; + } else { + MMC5ROMWrProtect[x] = 0; + MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & 7); + } + } + MMC5MemIn[4] = 1; + MMC5ROMWrProtect[3] = 1; + setprg8(0xE000, PRGBanks[3] & 0x7F); + break; + } +} + +static void MMC5MIRR(void) { + int x; + for (x = 0; x < 4; x++) { + switch ((NTAMirroring >> (x << 1)) & 3) { + case 0: PPUNTARAM |= 1 << x; vnapage[x] = NTARAM; break; + case 1: PPUNTARAM |= 1 << x; vnapage[x] = NTARAM + 0x400; break; + case 2: PPUNTARAM |= 1 << x; vnapage[x] = ExRAM; break; + case 3: PPUNTARAM &= ~(1 << x); vnapage[x] = MMC5fill; break; + } + } +} + +DECLFW(Mapper5_write) { + switch (A) { + case 0x5100: + mmc5psize = V; + MMC5PRG(); + break; + case 0x5101: + mmc5vsize = V; + if (!mmc5ABMode) { + MMC5CHRB(); + MMC5CHRA(); + } else { + MMC5CHRA(); + MMC5CHRB(); + } + break; + case 0x5102: + WRAMMaskEnable[0] = V; + break; + case 0x5103: + WRAMMaskEnable[1] = V; + break; + case 0x5104: + CHRMode = V; + MMC5HackCHRMode = V & 3; + break; + case 0x5105: + NTAMirroring = V; + MMC5MIRR(); + break; + case 0x5106: + if (V != NTFill) { + FCEU_dwmemset(MMC5fill, (V | (V << 8) | (V << 16) | (V << 24)), 0x3c0); + } + NTFill = V; + break; + case 0x5107: + if (V != ATFill) { + unsigned char moop = V | (V << 2) | (V << 4) | (V << 6); + FCEU_dwmemset(MMC5fill + 0x3c0, moop | (moop << 8) | (moop << 16) | (moop << 24), 0x40); + } + ATFill = V; + break; + case 0x5113: + WRAMPage = V; + MMC5WRAM(0x6000, V & 7); + break; + case 0x5114: + case 0x5115: + case 0x5116: + case 0x5117: + PRGBanks[A & 3] = V; + MMC5PRG(); + break; + case 0x5120: + case 0x5121: + case 0x5122: + case 0x5123: + case 0x5124: + case 0x5125: + case 0x5126: + case 0x5127: + mmc5ABMode = 0; + CHRBanksA[A & 7] = V | ((MMC50x5130 & 0x3) << 8); + MMC5CHRA(); + break; + case 0x5128: + case 0x5129: + case 0x512a: + case 0x512b: + mmc5ABMode = 1; + CHRBanksB[A & 3] = V | ((MMC50x5130 & 0x3) << 8); + MMC5CHRB(); + break; + case 0x5130: + MMC50x5130 = V; + break; + case 0x5200: + MMC5HackSPMode = V; + break; + case 0x5201: + MMC5HackSPScroll = (V >> 3) & 0x1F; + break; + case 0x5202: + MMC5HackSPPage = V & 0x3F; + break; + case 0x5203: + X6502_IRQEnd(FCEU_IQEXT); + IRQScanline = V; + break; + case 0x5204: + X6502_IRQEnd(FCEU_IQEXT); + IRQEnable = V & 0x80; + break; + case 0x5205: + mul[0] = V; + break; + case 0x5206: + mul[1] = V; + break; + } +} + +static DECLFR(MMC5_ReadROMRAM) { + if (MMC5MemIn[(A - 0x6000) >> 13]) { + return Page[A >> 11][A]; + } + return CPU_OPENBUS; +} + +static DECLFW(MMC5_WriteROMRAM) { + if ((A >= 0x8000) && (MMC5ROMWrProtect[(A - 0x8000) >> 13])) { + return; + } + if (MMC5MemIn[(A - 0x6000) >> 13]) { + if (((WRAMMaskEnable[0] & 3) | ((WRAMMaskEnable[1] & 3) << 2)) == 6) { + Page[A >> 11][A] = V; + } + } +} + +DECLFW(MMC5_ExRAMWr) { + if (MMC5HackCHRMode != 3) { + ExRAM[A & 0x3ff] = V; + } +} + +static DECLFR(MMC5_ExRAMRd) { + return ExRAM[A & 0x3ff]; +} + +static DECLFR(MMC5_read) { + uint8 ret = CPU_OPENBUS; + switch (A) { + case 0x5204: + X6502_IRQEnd(FCEU_IQEXT); + ret = MMC5IRQR; +#ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) +#endif + MMC5IRQR &= 0x40; + return ret; + case 0x5205: + return ((uint32)(mul[0] * mul[1]) & 0xFF); + case 0x5206: + return ((uint32)(mul[0] * mul[1]) >> 8); + } + return ret; +} + +static void MMC5Synco(void) { + uint8 moop; + + MMC5PRG(); + MMC5MIRR(); + MMC5WRAM(0x6000, WRAMPage & 7); + if (!mmc5ABMode) { + MMC5CHRB(); + MMC5CHRA(); + } else { + MMC5CHRA(); + MMC5CHRB(); + } + + /* in case the fill register changed, we need to overwrite the fill buffer */ + FCEU_dwmemset(MMC5fill, NTFill | (NTFill << 8) | (NTFill << 16) | (NTFill << 24), 0x3c0); + moop = ATFill | (ATFill << 2) | (ATFill << 4) | (ATFill << 6); + FCEU_dwmemset(MMC5fill + 0x3c0, moop | (moop << 8) | (moop << 16) | (moop << 24), 0x40); + + MMC5HackCHRMode = CHRMode & 3; + + /* zero 17-apr-2013 - why the heck should this happen here? anything in a `synco` should be depending on the state. + * im going to leave it commented out to see what happens + */ + /* X6502_IRQEnd(FCEU_IQEXT); */ +} + +void MMC5_hb(int cur_scanline) { + /* zero 24-jul-2014 - revised for newer understanding, to fix metal slader glory credits. see r7371 in bizhawk */ + int sl = cur_scanline + 1; + int ppuon = (PPU[1] & 0x18); + + if (!ppuon || sl >= 241) { + /* whenever rendering is off for any reason (vblank or forced disable + * the irq counter resets, as well as the inframe flag (easily verifiable from software) + */ + MMC5IRQR &= ~0x40; + MMC5IRQR &= ~0x80; + MMC5LineCounter = 0; + X6502_IRQEnd(FCEU_IQEXT); + return; + } + + if (!(MMC5IRQR & 0x40)) { + MMC5IRQR |= 0x40; + MMC5IRQR &= ~0x80; + MMC5LineCounter = 0; + X6502_IRQEnd(FCEU_IQEXT); + } else { + MMC5LineCounter++; + if (MMC5LineCounter == IRQScanline) { + MMC5IRQR |= 0x80; + if (IRQEnable & 0x80) { + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void MMC5_StateRestore(int version) { + MMC5Synco(); +} + +static void GenMMC5Power(void) { + int x; + uint8 nval; + uint8 aval; + + for (x = 0; x < 4; x++) PRGBanks[x] = ~0; + for (x = 0; x < 8; x++) CHRBanksA[x] = ~0; + for (x = 0; x < 4; x++) CHRBanksB[x] = ~0; + for (x = 0; x < 2; x++) WRAMMaskEnable[x] = ~0; + for (x = 0; x < 4; x++) MMC5ROMWrProtect[x] = 0; + for (x = 0; x < 5; x++) MMC5MemIn[x] = 0; + for (x = 0; x < 2; x++) mul[x] = 0; + + WRAMPage = 0; + CHRMode = 0; + mmc5ABMode = 0; + mmc5psize = mmc5vsize = 3; + + IRQScanline = 0; + IRQEnable = 0; + MMC5IRQR = 0; + MMC5LineCounter = 0; + + NTAMirroring = NTFill = ATFill = 0xFF; + + /* MMC5fill is and 8-bit tile index, and a 2-bit attribute implented as a mirrored nametable */ + nval = MMC5fill[0x000]; + aval = MMC5fill[0x3C0] & 3; aval = aval | (aval << 2) | (aval << 4) | (aval << 6); + FCEU_dwmemset(MMC5fill + 0x000, nval | (nval<<8) | (nval<<16) | (nval<<24), 0x3C0); + FCEU_dwmemset(MMC5fill + 0x3C0, aval | (aval<<8) | (aval<<16) | (aval<<24), 0x040); + + if (MMC5battery == 0) { + FCEU_MemoryRand(WRAM, MMC5WRAMsize * 8 * 1024); + FCEU_MemoryRand(MMC5fill, 1024); + FCEU_MemoryRand(ExRAM, 1024); + } + + MMC5Synco(); + + SetWriteHandler(0x4020, 0x5bff, Mapper5_write); + SetReadHandler(0x4020, 0x5bff, MMC5_read); + + SetWriteHandler(0x5c00, 0x5fff, MMC5_ExRAMWr); + SetReadHandler(0x5c00, 0x5fff, MMC5_ExRAMRd); + + SetWriteHandler(0x6000, 0xFFFF, MMC5_WriteROMRAM); + SetReadHandler(0x6000, 0xFFFF, MMC5_ReadROMRAM); + + SetWriteHandler(0x5000, 0x5015, MMC5Sound_Write); + SetWriteHandler(0x5205, 0x5206, Mapper5_write); + SetReadHandler(0x5205, 0x5206, MMC5_read); + +/* GameHBIRQHook=MMC5_hb; */ +/* FCEU_CheatAddRAM(8, 0x6000, WRAM); */ + FCEU_CheatAddRAM(1, 0x5c00, ExRAM); + +#ifdef NEW_PPU + FFCEUX_PPURead = mmc5_PPURead; + FFCEUX_PPUWrite = mmc5_PPUWrite; +#endif +} + +static void GenMMC5_Init(CartInfo *info, int wsize, int battery) { + if (wsize) { + WRAM = (uint8 *)FCEU_gmalloc(wsize * 1024); + SetupCartPRGMapping(0x10, WRAM, wsize * 1024, 1); + AddExState(WRAM, wsize * 1024, 0, "WRAM"); + } + + MMC5fill = (uint8 *)FCEU_gmalloc(1024); + ExRAM = (uint8 *)FCEU_gmalloc(1024); + + FCEU_MemoryRand(MMC5fill, 1024); + FCEU_MemoryRand(ExRAM, 1024); + + AddExState(ExRAM, 1024, 0, "ERAM"); + AddExState(&MMC5HackSPMode, 1, 0, "SPLM"); + AddExState(&MMC5HackSPScroll, 1, 0, "SPLS"); + AddExState(&MMC5HackSPPage, 1, 0, "SPLP"); + AddExState(&MMC50x5130, 1, 0, "5130"); + AddExState(MMC5_StateRegs, ~0, 0, 0); + + MMC5WRAMsize = wsize ? (wsize / 8) : 0; + BuildWRAMSizeTable(); + GameStateRestore = MMC5_StateRestore; + info->Power = GenMMC5Power; + + MMC5battery = battery; + if (battery) { + uint32 saveramsize; + if (info->iNES2) { + saveramsize = info->PRGRamSaveSize; + } else { + if (wsize <= 16) saveramsize = 8 * 1024; + else if (wsize >= 64) saveramsize = 64 * 1024; + else saveramsize = 32 * 1024; + } + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = saveramsize; + } + + MMC5HackVROMMask = CHRmask4[0]; + MMC5HackExNTARAMPtr = ExRAM; + MMC5Hack = TRUE; + MMC5HackVROMPTR = CHRptr[0]; + MMC5HackCHRMode = 0; + MMC5HackSPMode = MMC5HackSPScroll = MMC5HackSPPage = 0; + + MMC5Sound_ESI(); + MMC5Sound_AddStateInfo(); +} + +void Mapper005_Init(CartInfo *info) { + WRAMSIZE = 64; + if (info->iNES2) { + WRAMSIZE = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; + if (WRAMSIZE && WRAMSIZE < 8) WRAMSIZE = 8; + else if (WRAMSIZE > 64) WRAMSIZE = 64; + } + GenMMC5_Init(info, WRAMSIZE, info->battery); +} + +/* ELROM seems to have 0KB of WRAM + * EKROM seems to have 8KB of WRAM, battery-backed + * ETROM seems to have 16KB of WRAM, battery-backed + * EWROM seems to have 32KB of WRAM, battery-backed + */ + +void ELROM_Init(CartInfo *info) { + GenMMC5_Init(info, 0, 0); +} + +void EKROM_Init(CartInfo *info) { + GenMMC5_Init(info, 8, info->battery); +} + +void ETROM_Init(CartInfo *info) { + GenMMC5_Init(info, 16, info->battery); +} + +void EWROM_Init(CartInfo *info) { + GenMMC5_Init(info, 32, info->battery); +} diff --git a/src/mappers/mapper006.c b/src/mappers/mapper006.c new file mode 100644 index 000000000..7e9f62c14 --- /dev/null +++ b/src/mappers/mapper006.c @@ -0,0 +1,486 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Front Fareast Magic Card 1M or 2M RAM cartridges + * + */ + +#include "mapinc.h" +#include "mapper006.h" + +static uint8 mode_1m; +static uint8 mode_2m; +static uint8 mode_smc; + +static uint8 prg[4]; +static uint8 chr[8]; +static uint8 nt[4]; +static uint8 chr_mmc4latch[2]; +static uint8 latch; +static uint8 chr_lock; + +static uint8 smc_irq_enabled; +static uint32 smc_irq_counter; + +static uint8 fds_control; +static int16 fds_irq_counter; + +static uint8 scratch[0x1000]; + +static SFORMAT StateRegs[] = { + { &mode_1m, 1, "MC1M" }, + { &mode_2m, 1, "MC2M" }, + { &mode_smc, 1, "SMCM" }, + + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { nt, 4, "NTAR" }, + { chr_mmc4latch, 2, "MMC4" }, + { &latch, 1, "LATC" }, + { &chr_lock, 1, "CHRL" }, + + { &smc_irq_enabled, 1, "IRQA" }, + { &smc_irq_enabled, 4, "IRQC" }, + + { &fds_control, 1, "FDSI" }, + { &fds_irq_counter, 4, "FDSC" }, + + { 0 }, +}; + +static void SyncPRG(void) { + uint8 prg_writable = !(mode_1m & 0x02); + + SetupCartPRGMapping(0, PRGptr[0], PRGsize[0], prg_writable); + + if (!(mode_2m & 0x01)) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, prg[3]); + } else { + switch (mode_1m >> 5) { + case 0: + setprg16(0x8000, latch & 0x07); + setprg16(0xC000, 0x07); + break; + case 1: + setprg16(0x8000, (latch >> 2) & 0x0F); + setprg16(0xC000, 0x07); + break; + case 2: + setprg16(0x8000, latch & 0x0F); + setprg16(0xC000, 0x0F); + break; + case 3: + setprg16(0x8000, 0x0F); + setprg16(0xC000, latch & 0x0F); + break; + case 4: + setprg32(0x8000, (latch >> 4) & 0x03); + break; + case 5: + case 6: + case 7: + setprg32(0x8000, 0x03); + break; + } + } +} + +static void SyncCHR(void) { + uint8 chr_writable = !(((mode_1m & 0xE1) >= 0x81) || chr_lock); + + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], chr_writable); + + if (mode_smc & 0x01) { + if (mode_smc & 0x04) { + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + } else { + setchr4(0x0000, chr[0 | chr_mmc4latch[0]] >> 2); + setchr4(0x1000, chr[4 | chr_mmc4latch[1]] >> 2); + } + } else { + switch (mode_1m >> 5) { + case 0: + case 2: + setchr8(0); + break; + case 1: + case 4: + case 5: + setchr8(latch & 0x03); + break; + case 3: + setchr8((latch >> 4) & 0x03); + break; + case 6: + setchr8(latch & 0x01); + break; + case 7: + setchr8(0x03); + break; + } + } +} + +static void SyncMIR(void) { + if (mode_smc & 0x02) { + switch (mode_1m & 0x11) { + case 0x00: setmirror(MI_0); break; + case 0x10: setmirror(MI_1); break; + case 0x01: setmirror(MI_V); break; + case 0x11: setmirror(MI_H); break; + } + } else { + setntamem(CHRptr[0] + 0x400 * (nt[0] & CHRmask1[0]), 1, 0); + setntamem(CHRptr[0] + 0x400 * (nt[1] & CHRmask1[0]), 1, 1); + setntamem(CHRptr[0] + 0x400 * (nt[2] & CHRmask1[0]), 1, 2); + setntamem(CHRptr[0] + 0x400 * (nt[3] & CHRmask1[0]), 1, 3); + } +} + +static void Sync(void) { + setprg4r(0x11, 0x5000, 0); + setprg8r(0x10, 0x6000, 0); + + SyncPRG(); + SyncCHR(); + SyncMIR(); +} + +static DECLFR(M006ReadREG) { + return mode_smc; +} + +static DECLFW(M006WriteREG) { + switch (A) { + case 0x4024: + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x4025: + X6502_IRQEnd(FCEU_IQEXT); + if (!smc_irq_enabled) { + fds_control = V; + if (V & 0x42) { + fds_irq_counter = 0; + } + } + break; + case 0x42FC: + case 0x42FD: + case 0x42FE: + case 0x42FF: + mode_1m = (V & 0xF0) | (A & 0x03); + if (mode_1m >= 0x80) { + chr_lock = FALSE; + } + SyncPRG(); + SyncCHR(); + SyncMIR(); + break; + case 0x43FC: + case 0x43FD: + case 0x43FE: + case 0x43FF: + mode_2m = (V & 0xF0) | (A & 0x03); + latch = V; + SyncPRG(); + SyncCHR(); + break; + case 0x4500: + mode_smc = V; + SyncCHR(); + SyncMIR(); + break; + case 0x4501: + smc_irq_enabled = FALSE; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x4502: + smc_irq_counter = (smc_irq_counter & 0xFF00) | V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x4503: + smc_irq_enabled = TRUE; + smc_irq_counter = (smc_irq_counter & 0x00FF) | (V << 8); + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x4504: + case 0x4505: + case 0x4506: + case 0x4507: + if (mode_2m & 0x02) { + V >>= 2; + } + prg[A & 0x03] = V; + SyncPRG(); + break; + case 0x4510: + case 0x4511: + case 0x4512: + case 0x4513: + case 0x4514: + case 0x4515: + case 0x4516: + case 0x4517: + chr[A & 0x07] = V; + SyncCHR(); + break; + case 0x4518: + case 0x4519: + case 0x451A: + case 0x451B: + nt[A & 0x03] = V; + SyncMIR(); + break; + } +} + +static DECLFW(M006WriteLatch) { + if (mode_1m & 0x02) { + latch = V; + if (mode_2m & 0x03) { + prg[(A >> 13) & 0x03] = V >> 2; + } + SyncPRG(); + SyncCHR(); + } else { + CartBW(A, V); + } +} + +static void M006Reset(void) { + smc_irq_enabled = FALSE; + smc_irq_counter = 0; + fds_control = 0; + fds_irq_counter = 0; + Sync(); +} + +static uint32 prg_size_8K = 0; +static void SetTrainer(void) { + int nmiHandler; + + #define PRGPAGE_DMR(a) Page[(a) >> 11][(a)] + #define PRGPAGE_DMW(a, d) Page[(a) >> 11][(a)] = (d) + + nmiHandler = PRGPAGE_DMR(0xFFFA) | (PRGPAGE_DMR(0xFFFB) << 8); + if (nmiHandler == 0x5032) { + PRGPAGE_DMW(0xFFFA, scratch[0x4F]); + PRGPAGE_DMW(0xFFFB, scratch[0x50]); + } + memcpy(&scratch[0], &smc5000[0], sizeof(smc5000)); + scratch[0x4F] = PRGPAGE_DMR(0xFFFA); + scratch[0x50] = PRGPAGE_DMR(0xFFFB); + if (iNESCart.mapper == 17) { + PRGPAGE_DMW(0xFFFA, 0x32); + PRGPAGE_DMW(0xFFFB, 0x50); + } + if (iNESCart.trainer && WRAM) { + int i; + uint8 *trainerData = 0; + uint16 trainerAddr = + iNESCart.mapper != 17 ? 0x7000 : + iNESCart.submapper == 0 ? 0x7000 : + iNESCart.submapper << 8 | 0x5C00; + + for (i = 0; i < (int)MISC_ROM_SIZE; i++) { + PRGPAGE_DMW((trainerAddr & 0x7F00) + i, MISC_ROM_DATA[i]); + } + + X6502_SetNewPC((iNESCart.mapper == 17) ? trainerAddr : 0x5000); + } + (GetWriteHandler(0x4017))(0x4017, 0x40); + + #undef PRGPAGE_DMR + #undef PRGPAGE_DMW +} + +static void M006Power(void) { + mode_1m = (((iNESCart.mapper == 6) ? iNESCart.submapper : 1) << 5) | + ((iNESCart.mirror & MI_V) ? 0x01 : 0x11) | + 0x02; + chr_lock = FALSE; + + mode_2m = ((iNESCart.mapper == 12) || + (iNESCart.mapper == 17)) ? 0x00 : 0x03; + mode_smc = (iNESCart.mapper == 17) ? 0x47 : 0x42; + latch = 0; + + prg[0] = prg_size_8K - 4; + prg[1] = prg_size_8K - 3; + prg[2] = prg_size_8K - 2; + prg[3] = prg_size_8K - 1; + + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + chr[4] = 4; + chr[5] = 5; + chr[6] = 6; + chr[7] = 7; + + M006Reset(); + + SetReadHandler(0x5000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x7FFF, CartBW); + + SetReadHandler (0x4500, 0x4500, M006ReadREG); + SetWriteHandler(0x4024, 0x451B, M006WriteREG); + SetWriteHandler(0x8000, 0xFFFF, M006WriteLatch); + + SetTrainer(); +} + +static void ClockSMCCounter(void) { + if (smc_irq_enabled) { + smc_irq_counter++; + if (smc_irq_counter >= 0x10000 ) { + smc_irq_counter = 0; + smc_irq_enabled = FALSE; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M006CPUHook(int a) { + while (a--) { + fds_irq_counter += 3; + while ((fds_irq_counter >= 448) && (fds_control & 0x80)) { + X6502_IRQBegin(FCEU_IQEXT); + fds_irq_counter -= 448; + } + + if (!(mode_smc & 0x08)) { + ClockSMCCounter(); + } + } +} + +static void M006HBHook(void) { + if (mode_smc & 0x08) { + int i; + for (i = 0; i < 8; i++) { + ClockSMCCounter(); + } + } +} + +static void M006PPUHook(uint32 A) { + if ((A & 0x3000) != 0x2000) { + int needsync = FALSE; + + if ((mode_1m >= 0xA0) && !(mode_1m & 0x01)) { + chr_lock = (mode_1m & 0x10) != 0; + needsync = TRUE; + } + + if ((mode_smc & 0x05) == 0x01) { + uint8 value = (A >> 4) & 0x02; + uint8 bank = (A >> 12) & 0x01; + + switch (A & 0x0FF0) { + case 0x0FD0: + case 0x0FE0: + if (chr_mmc4latch[bank] != value) { + chr_mmc4latch[bank] = value; + needsync = TRUE; + } + break; + } + } + if (needsync) { + Sync(); + } + } +} + +static void Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper006_Init(CartInfo *info) { + int ws = info->PRGRamSize + info->PRGRamSaveSize; + + info->Power = M006Power; + info->Reset = M006Reset; + + MapIRQHook = M006CPUHook; + PPU_hook = M006PPUHook; + GameHBIRQHook2 = M006HBHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = ws ? ws : 8192; + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + + SetupCartPRGMapping(0x11, scratch, 4096, TRUE); + AddExState(scratch, 4096, 0, "SRAM"); + + prg_size_8K = PRG_BANK_COUNT(8); + + if (CHR_ROM_SIZE_8K) { + if (info->mapper == 12) { + int i; + size_t ssize; + + PRG_ROM_SIZE_16K = (512 * 1024); + PRG_ROM_DATA = realloc(PRG_ROM_DATA, PRG_ROM_SIZE_16K); + for (i = 0; i < ((CHR_ROM_SIZE_8K < (256 * 1024)) ? CHR_ROM_SIZE_8K : (256 * 1024)); i++) { + PRG_ROM_DATA[(256 * 1024) + i] = CHR_ROM_DATA[i]; + } + SetupCartPRGMapping(0, PRG_ROM_DATA, PRG_ROM_SIZE_16K, TRUE); + + memset(CHR_ROM_DATA, 0, CHR_ROM_SIZE_8K); + ssize = info->CHRRamSize ? info->CHRRamSize : (32 * 1024); + SetupCartCHRMapping(0, CHR_ROM_DATA, ssize, TRUE); + AddExState(CHR_ROM_DATA, ssize, 0, "CHRR"); + CHR_ROM_SIZE_8K = 0; + } else { + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], TRUE); + AddExState(CHR_ROM_DATA, CHR_ROM_SIZE_8K, 0, "CHRR"); + } + } + + if ((iNESCart.iNES2 == 0) && (iNESCart.mapper == 6)) { + iNESCart.submapper = 1; + } + + if (iNESCart.mapper == 8) { + iNESCart.mapper = 6; + iNESCart.submapper = 4; + } +} diff --git a/src/mappers/mapper006.h b/src/mappers/mapper006.h new file mode 100644 index 000000000..3061f0b69 --- /dev/null +++ b/src/mappers/mapper006.h @@ -0,0 +1,262 @@ +#ifndef _MAPPER006_H +#define _MAPPER006_H + +const uint8_t smc5000[4096] ={ + 0x20, 0x03, 0x70, 0x6C, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xDD, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x2C, 0x00, 0x45, 0x30, 0x19, 0x50, 0x17, 0x2C, 0x2F, 0x50, 0x10, 0x0E, 0x8D, + 0x44, 0x58, 0xA5, 0xFA, 0x0A, 0x09, 0xE0, 0x8D, 0xFD, 0x42, 0xAD, 0x44, 0x58, 0x28, 0x4C, 0x11, + 0x11, 0x8D, 0x44, 0x58, 0x8E, 0x45, 0x58, 0x8C, 0x46, 0x58, 0xBA, 0x8E, 0x47, 0x58, 0xAD, 0x00, + 0x58, 0x8D, 0x40, 0x58, 0x29, 0x7F, 0x8D, 0x00, 0x20, 0xAD, 0x01, 0x58, 0x8D, 0x41, 0x58, 0xAD, + 0x00, 0x45, 0x8D, 0x42, 0x58, 0xAD, 0x01, 0x45, 0x8D, 0x43, 0x58, 0xA2, 0x1F, 0xBD, 0x00, 0x50, + 0x9D, 0x48, 0x58, 0xBD, 0x00, 0x55, 0x9D, 0x68, 0x58, 0xCA, 0x10, 0xF1, 0xA9, 0x00, 0x8D, 0x01, + 0x45, 0x8D, 0x10, 0x40, 0x8D, 0x11, 0x40, 0x8D, 0x15, 0x40, 0xA9, 0x01, 0x8D, 0x31, 0x50, 0x20, + 0xCE, 0x53, 0xAD, 0xCA, 0x53, 0xF0, 0xF8, 0xA9, 0x72, 0x8D, 0x00, 0x45, 0xA2, 0x00, 0xB5, 0x00, + 0x9D, 0x00, 0x60, 0xBD, 0x00, 0x01, 0x9D, 0x00, 0x61, 0xBD, 0x00, 0x02, 0x9D, 0x00, 0x62, 0xBD, + 0x00, 0x03, 0x9D, 0x00, 0x63, 0xBD, 0x00, 0x04, 0x9D, 0x00, 0x64, 0xBD, 0x00, 0x05, 0x9D, 0x00, + 0x65, 0xBD, 0x00, 0x06, 0x9D, 0x00, 0x66, 0xBD, 0x00, 0x07, 0x9D, 0x00, 0x67, 0xE8, 0xD0, 0xCE, + 0xA9, 0x00, 0x8D, 0x00, 0x20, 0x8D, 0x01, 0x20, 0xA2, 0x07, 0x9D, 0x10, 0x45, 0xCA, 0x10, 0xFA, + 0x20, 0xF8, 0x51, 0x20, 0xB6, 0x52, 0x20, 0x24, 0x53, 0x20, 0xE7, 0x52, 0x20, 0x18, 0x53, 0xA9, + 0x00, 0x8D, 0x00, 0x45, 0xA0, 0x02, 0x8C, 0x31, 0x50, 0x4C, 0x3D, 0xF0, 0xAD, 0x31, 0x50, 0xC9, + 0x01, 0xF0, 0x01, 0x60, 0x4C, 0xA7, 0x50, 0xAD, 0x31, 0x50, 0xC9, 0x02, 0xF0, 0x01, 0x60, 0xA9, + 0x00, 0x8D, 0x31, 0x50, 0x8D, 0x00, 0x20, 0x8D, 0x01, 0x20, 0x20, 0x52, 0x53, 0x20, 0x88, 0x52, + 0x20, 0x80, 0x53, 0x20, 0xAE, 0x53, 0xA9, 0x00, 0x8D, 0xFC, 0x43, 0xA2, 0x03, 0xBD, 0x6C, 0x58, + 0x9D, 0x04, 0x45, 0xCA, 0x10, 0xF7, 0xA2, 0x0B, 0xBD, 0x78, 0x58, 0x9D, 0x10, 0x45, 0xCA, 0x10, + 0xF7, 0xA2, 0x00, 0xBD, 0x48, 0x58, 0x9D, 0x00, 0x40, 0xE8, 0xE0, 0x10, 0xD0, 0xF5, 0xAD, 0x5D, + 0x58, 0x8D, 0x15, 0x40, 0xAD, 0x5E, 0x58, 0x8D, 0x16, 0x40, 0xAD, 0x5F, 0x58, 0x8D, 0x17, 0x40, + 0xA9, 0x72, 0x8D, 0x00, 0x45, 0xA2, 0x00, 0xBD, 0x00, 0x60, 0x95, 0x00, 0xBD, 0x00, 0x61, 0x9D, + 0x00, 0x01, 0xBD, 0x00, 0x62, 0x9D, 0x00, 0x02, 0xBD, 0x00, 0x63, 0x9D, 0x00, 0x03, 0xBD, 0x00, + 0x64, 0x9D, 0x00, 0x04, 0xBD, 0x00, 0x65, 0x9D, 0x00, 0x05, 0xBD, 0x00, 0x66, 0x9D, 0x00, 0x06, + 0xBD, 0x00, 0x67, 0x9D, 0x00, 0x07, 0xE8, 0xD0, 0xCE, 0xAD, 0x68, 0x58, 0x8D, 0x00, 0x45, 0xAD, + 0x42, 0x58, 0x29, 0x03, 0xAA, 0xAD, 0x42, 0x58, 0x0A, 0x0A, 0x9D, 0xFC, 0x42, 0xAD, 0x43, 0x58, + 0x29, 0x03, 0xAA, 0xAD, 0x43, 0x58, 0x4A, 0x4A, 0x9D, 0xFC, 0x43, 0xAD, 0x02, 0x20, 0x10, 0xFB, + 0xAD, 0x02, 0x20, 0x10, 0xFB, 0x2C, 0x00, 0x45, 0x10, 0x03, 0x2C, 0x0A, 0x45, 0xAE, 0x47, 0x58, + 0x9A, 0xAC, 0x46, 0x58, 0xAE, 0x45, 0x58, 0xAD, 0x41, 0x58, 0x8D, 0x01, 0x20, 0xAD, 0x40, 0x58, + 0x8D, 0x00, 0x20, 0xAD, 0x44, 0x58, 0x28, 0x40, 0xA9, 0x20, 0x8D, 0xFD, 0x42, 0x8D, 0xFC, 0x43, + 0xA9, 0x00, 0x85, 0x00, 0xA9, 0x80, 0xA0, 0x04, 0x20, 0x2D, 0x52, 0x8E, 0x6C, 0x58, 0xA9, 0xA0, + 0xA0, 0x05, 0x20, 0x2D, 0x52, 0x8E, 0x6D, 0x58, 0xA9, 0xC0, 0xA0, 0x06, 0x20, 0x2D, 0x52, 0x8E, + 0x6E, 0x58, 0xA9, 0xE0, 0xA0, 0x07, 0x20, 0x2D, 0x52, 0x8E, 0x6F, 0x58, 0x60, 0x85, 0x01, 0x8C, + 0x56, 0x52, 0xA0, 0x00, 0xB1, 0x00, 0x8D, 0xC7, 0x53, 0xC8, 0xB1, 0x00, 0x8D, 0xC8, 0x53, 0xC8, + 0xB1, 0x00, 0x8D, 0xC9, 0x53, 0xA9, 0x49, 0x91, 0x00, 0x88, 0xA9, 0x53, 0x91, 0x00, 0x88, 0xA9, + 0x4A, 0x91, 0x00, 0xA2, 0x00, 0x8E, 0x04, 0x45, 0xA0, 0x00, 0xB1, 0x00, 0xC9, 0x4A, 0xD0, 0x0E, + 0xC8, 0xB1, 0x00, 0xC9, 0x53, 0xD0, 0x07, 0xC8, 0xB1, 0x00, 0xC9, 0x49, 0xF0, 0x08, 0xE8, 0xE0, + 0x80, 0xD0, 0xE2, 0x4C, 0x73, 0x52, 0xAD, 0xC9, 0x53, 0x91, 0x00, 0x88, 0xAD, 0xC8, 0x53, 0x91, + 0x00, 0x88, 0xAD, 0xC7, 0x53, 0x91, 0x00, 0x60, 0x2C, 0x2F, 0x50, 0x10, 0x15, 0xA2, 0x0C, 0xA0, + 0x01, 0x20, 0xA3, 0x52, 0xA2, 0x0D, 0xA0, 0x02, 0x20, 0xA3, 0x52, 0xA2, 0x0E, 0xA0, 0x03, 0x20, + 0xA3, 0x52, 0x60, 0x8E, 0x07, 0x45, 0x8C, 0xFC, 0x43, 0xA9, 0x02, 0x8D, 0x00, 0x45, 0xA9, 0x20, + 0x8D, 0xFD, 0x42, 0x4C, 0xC5, 0x52, 0xA9, 0x62, 0x8D, 0x00, 0x45, 0xA9, 0x00, 0x8D, 0xFC, 0x43, + 0xA9, 0x20, 0x8D, 0xFF, 0x42, 0x2C, 0x02, 0x20, 0xA0, 0x00, 0x8C, 0x06, 0x20, 0x8C, 0x06, 0x20, + 0xA9, 0x60, 0x8D, 0xDD, 0x52, 0xAD, 0x07, 0x20, 0xAD, 0x07, 0x20, 0x99, 0x00, 0x60, 0xC8, 0xD0, + 0xF7, 0xEE, 0xDD, 0x52, 0x10, 0xF2, 0x60, 0xA9, 0x72, 0x8D, 0x00, 0x45, 0xA9, 0x20, 0x8D, 0xFF, + 0x42, 0x2C, 0x02, 0x20, 0xA0, 0x20, 0x8C, 0x06, 0x20, 0xA0, 0x00, 0x8C, 0x06, 0x20, 0xA9, 0x68, + 0x8D, 0x0D, 0x53, 0xA2, 0x08, 0xAD, 0x07, 0x20, 0xAD, 0x07, 0x20, 0x99, 0x00, 0x68, 0xC8, 0xD0, + 0xF7, 0xEE, 0x0D, 0x53, 0xCA, 0xD0, 0xF1, 0x60, 0xA2, 0x1F, 0xBD, 0x20, 0x58, 0x9D, 0x88, 0x58, + 0xCA, 0x10, 0xF7, 0x60, 0x2C, 0x2F, 0x50, 0x10, 0x15, 0xA2, 0x0C, 0xA0, 0x01, 0x20, 0x3F, 0x53, + 0xA2, 0x0D, 0xA0, 0x02, 0x20, 0x3F, 0x53, 0xA2, 0x0E, 0xA0, 0x03, 0x20, 0x3F, 0x53, 0x60, 0x8E, + 0x07, 0x45, 0x8C, 0xFC, 0x43, 0xA9, 0x02, 0x8D, 0x00, 0x45, 0xA9, 0x20, 0x8D, 0xFD, 0x42, 0x4C, + 0x61, 0x53, 0xA9, 0x62, 0x8D, 0x00, 0x45, 0xA9, 0x00, 0x8D, 0xFC, 0x43, 0xA9, 0x20, 0x8D, 0xFF, + 0x42, 0x2C, 0x02, 0x20, 0xA0, 0x00, 0x8C, 0x06, 0x20, 0x8C, 0x06, 0x20, 0xA9, 0x60, 0x8D, 0x73, + 0x53, 0xB9, 0x00, 0x60, 0x8D, 0x07, 0x20, 0xC8, 0xD0, 0xF7, 0xEE, 0x73, 0x53, 0x10, 0xF2, 0x60, + 0xA9, 0x72, 0x8D, 0x00, 0x45, 0xA9, 0x20, 0x8D, 0xFF, 0x42, 0x2C, 0x02, 0x20, 0xA0, 0x20, 0x8C, + 0x06, 0x20, 0xA0, 0x00, 0x8C, 0x06, 0x20, 0xA9, 0x68, 0x8D, 0xA0, 0x53, 0xA2, 0x08, 0xB9, 0x00, + 0x68, 0x8D, 0x07, 0x20, 0xC8, 0xD0, 0xF7, 0xEE, 0xA0, 0x53, 0xCA, 0xD0, 0xF1, 0x60, 0x2C, 0x02, + 0x20, 0xA9, 0x3F, 0x8D, 0x06, 0x20, 0xA2, 0x00, 0x8E, 0x06, 0x20, 0xBD, 0x88, 0x58, 0x8D, 0x07, + 0x20, 0xE8, 0xE0, 0x20, 0x90, 0xF5, 0x60, 0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, + 0x45, 0x10, 0x03, 0x20, 0x21, 0x55, 0xA2, 0x01, 0x8E, 0x16, 0x40, 0xCA, 0x8E, 0x16, 0x40, 0xA2, + 0x08, 0xAD, 0x16, 0x40, 0x4A, 0x2E, 0xCA, 0x53, 0x4A, 0x2E, 0xCC, 0x53, 0xAD, 0x17, 0x40, 0x4A, + 0x2E, 0xCB, 0x53, 0x4A, 0x2E, 0xCD, 0x53, 0xCA, 0xD0, 0xE7, 0xAD, 0xCC, 0x53, 0x0D, 0xCA, 0x53, + 0x8D, 0xCA, 0x53, 0xAD, 0xCD, 0x53, 0x0D, 0xCB, 0x53, 0x8D, 0xCB, 0x53, 0x60, 0xA9, 0x00, 0x8D, + 0x00, 0x45, 0x4C, 0x25, 0xEF, 0xA9, 0x00, 0x8D, 0x01, 0x20, 0xA9, 0x88, 0x8D, 0x00, 0x45, 0xAD, + 0xFC, 0xFF, 0xC9, 0xFF, 0xD0, 0x15, 0xAD, 0xFD, 0xFF, 0xC9, 0xFF, 0xD0, 0x0E, 0xA9, 0x02, 0x8D, + 0x00, 0x45, 0x20, 0x00, 0xE4, 0xA9, 0x0A, 0x8D, 0x01, 0x20, 0x60, 0x6C, 0xFC, 0xFF, 0xA9, 0x00, + 0x8D, 0x01, 0x20, 0xA9, 0x88, 0x8D, 0x00, 0x45, 0xAD, 0xE0, 0xE6, 0xC9, 0x49, 0xD0, 0xDE, 0xAD, + 0xE1, 0xE6, 0xC9, 0x4E, 0xD0, 0xD7, 0xAD, 0xE2, 0xE6, 0xC9, 0x2A, 0xD0, 0xD0, 0xA2, 0x88, 0xA0, + 0x00, 0xA9, 0x0F, 0x8D, 0x07, 0x45, 0x8E, 0x00, 0x45, 0xB9, 0x00, 0xE0, 0x8D, 0xFF, 0x43, 0x99, + 0x00, 0x60, 0xC8, 0xD0, 0xF1, 0xEE, 0x6B, 0x54, 0xEE, 0x71, 0x54, 0x10, 0xE9, 0xA0, 0x06, 0xB9, + 0x9B, 0x54, 0x99, 0x03, 0x06, 0x88, 0x10, 0xF7, 0xA9, 0xC0, 0x8D, 0x20, 0x50, 0xA9, 0xF0, 0x8D, + 0x21, 0x50, 0x8D, 0x27, 0x50, 0x8D, 0x2F, 0x50, 0x4C, 0x13, 0xEE, 0xA9, 0xF0, 0x8D, 0xFD, 0x42, + 0x60, 0xAD, 0x2E, 0x57, 0x8D, 0xCA, 0x53, 0xAD, 0x2F, 0x57, 0x8D, 0xCB, 0x53, 0x68, 0x68, 0x68, + 0x68, 0x60, 0xC9, 0x00, 0xD0, 0x03, 0x4C, 0x0D, 0x54, 0xC9, 0x01, 0xD0, 0x03, 0x4C, 0x13, 0xEE, + 0xC9, 0x02, 0xD0, 0x03, 0x4C, 0x15, 0x54, 0xC9, 0x03, 0xD0, 0x03, 0x4C, 0x0C, 0x51, 0xC9, 0x04, + 0xD0, 0x03, 0x4C, 0x17, 0x51, 0xC9, 0x05, 0xD0, 0x03, 0x4C, 0xA1, 0x54, 0x60, 0x78, 0xD8, 0xAD, + 0x00, 0x55, 0x8D, 0x68, 0x58, 0xAD, 0x07, 0x55, 0x8D, 0x6F, 0x58, 0xA9, 0x02, 0x8D, 0x00, 0x45, + 0x20, 0x73, 0xD6, 0xAA, 0xAD, 0x68, 0x58, 0x8D, 0x00, 0x45, 0xAD, 0x6F, 0x58, 0x8D, 0x07, 0x45, + 0x2C, 0x00, 0x45, 0x10, 0x03, 0x2C, 0x0A, 0x45, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x60, 0xAD, 0x00, 0x55, 0x29, 0xF7, 0x8D, 0x00, 0x45, 0x20, 0x03, 0x57, 0xC9, 0xD5, 0xD0, 0xF0, + 0x20, 0x03, 0x57, 0xC9, 0xAA, 0xD0, 0xF5, 0x20, 0x03, 0x57, 0xC9, 0x96, 0xF0, 0x07, 0xC9, 0xAD, + 0xD0, 0xEA, 0x4C, 0xB5, 0x56, 0x20, 0xF1, 0x56, 0xA2, 0x00, 0x20, 0x03, 0x57, 0x9D, 0x2B, 0x57, + 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0xE8, 0xE0, 0x05, 0x90, 0xEF, 0x20, 0xF7, 0x56, 0xF0, 0x03, + 0x4C, 0xE1, 0x56, 0xAD, 0x2C, 0x57, 0x8D, 0x28, 0x57, 0xAD, 0x2D, 0x57, 0x8D, 0x29, 0x57, 0xAD, + 0x2B, 0x57, 0xC9, 0x00, 0xD0, 0x5C, 0x20, 0xF1, 0x56, 0xA0, 0x00, 0xAD, 0x2F, 0x57, 0xF0, 0x2B, + 0xAD, 0x29, 0x57, 0x8D, 0x96, 0x55, 0xAD, 0x28, 0x57, 0x8D, 0x95, 0x55, 0x2C, 0x00, 0x45, 0x10, + 0xFB, 0xAD, 0x0A, 0x45, 0x99, 0x00, 0x00, 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0xC8, 0xD0, 0xEC, + 0xEE, 0x29, 0x57, 0xEE, 0x96, 0x55, 0xCE, 0x2F, 0x57, 0xD0, 0xE1, 0xAE, 0x2E, 0x57, 0xF0, 0x1C, + 0xA9, 0x8D, 0x8D, 0x27, 0x57, 0x2C, 0x00, 0x45, 0x10, 0xFB, 0xAD, 0x0A, 0x45, 0x20, 0x27, 0x57, + 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0xEE, 0x28, 0x57, 0xCA, 0xD0, 0xE9, 0x20, 0xF7, 0x56, 0x4C, + 0xE5, 0x56, 0xC9, 0x01, 0xD0, 0x54, 0x20, 0xF1, 0x56, 0xA0, 0x00, 0xAD, 0x2F, 0x57, 0xF0, 0x1E, + 0xA9, 0xB9, 0x8D, 0x27, 0x57, 0x20, 0x27, 0x57, 0x48, 0x20, 0x0C, 0x57, 0x68, 0x4D, 0x30, 0x57, + 0x8D, 0x30, 0x57, 0xC8, 0xD0, 0xEF, 0xEE, 0x29, 0x57, 0xCE, 0x2F, 0x57, 0xD0, 0xE7, 0xAE, 0x2E, + 0x57, 0xF0, 0x19, 0xA9, 0xAD, 0x8D, 0x27, 0x57, 0x20, 0x27, 0x57, 0x48, 0x20, 0x0C, 0x57, 0x68, + 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0xEE, 0x28, 0x57, 0xCA, 0xD0, 0xEC, 0xAD, 0x30, 0x57, 0x20, + 0x0C, 0x57, 0x2C, 0x00, 0x45, 0x30, 0xFB, 0x4C, 0xEB, 0x56, 0xC9, 0x02, 0xD0, 0x29, 0x20, 0xAA, + 0x56, 0xAD, 0x29, 0x57, 0x8D, 0x06, 0x20, 0xAD, 0x28, 0x57, 0x8D, 0x06, 0x20, 0x20, 0xF1, 0x56, + 0x20, 0x03, 0x57, 0x8D, 0x07, 0x20, 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0x20, 0xD0, 0x56, 0xD0, + 0xEF, 0x20, 0xF7, 0x56, 0x4C, 0xE5, 0x56, 0xC9, 0x03, 0xD0, 0x36, 0x20, 0xAA, 0x56, 0xAD, 0x29, + 0x57, 0x8D, 0x06, 0x20, 0xAD, 0x28, 0x57, 0x8D, 0x06, 0x20, 0xAD, 0x07, 0x20, 0x20, 0xF1, 0x56, + 0xAD, 0x07, 0x20, 0x48, 0x20, 0x0C, 0x57, 0x68, 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0x20, 0xD0, + 0x56, 0xD0, 0xED, 0xAD, 0x30, 0x57, 0x20, 0x0C, 0x57, 0x2C, 0x00, 0x45, 0x30, 0xFB, 0x4C, 0xEB, + 0x56, 0xC9, 0x04, 0xD0, 0x08, 0xA9, 0x4C, 0x8D, 0x27, 0x57, 0x4C, 0x27, 0x57, 0xC9, 0x05, 0xD0, + 0x44, 0xAD, 0x2C, 0x57, 0x20, 0xB2, 0x54, 0x4C, 0xEB, 0x56, 0x2C, 0x02, 0x20, 0x30, 0xFB, 0x2C, + 0x02, 0x20, 0x10, 0xFB, 0x60, 0xA9, 0xAD, 0x8D, 0x27, 0x57, 0x20, 0x27, 0x57, 0x20, 0x0C, 0x57, + 0xEE, 0x28, 0x57, 0xD0, 0x03, 0xEE, 0x29, 0x57, 0x2C, 0x00, 0x45, 0x30, 0xFB, 0x4C, 0xEB, 0x56, + 0xAD, 0x2E, 0x57, 0xD0, 0x03, 0xCE, 0x2F, 0x57, 0xCE, 0x2E, 0x57, 0xD0, 0x03, 0xAD, 0x2F, 0x57, + 0x60, 0xA9, 0x01, 0xD0, 0x08, 0xF0, 0x04, 0xA9, 0x02, 0xD0, 0x02, 0xA9, 0x00, 0x8D, 0x31, 0x57, + 0x60, 0xA9, 0x81, 0x8D, 0x30, 0x57, 0x60, 0x2C, 0x00, 0x45, 0x10, 0xFB, 0xAD, 0x0A, 0x45, 0x4D, + 0x30, 0x57, 0x60, 0x2C, 0x00, 0x45, 0x10, 0xFB, 0xAD, 0x0A, 0x45, 0x60, 0x2C, 0x00, 0x45, 0x30, + 0xFB, 0x8D, 0x0A, 0x45, 0x2C, 0x0A, 0x45, 0x4A, 0x4A, 0x4A, 0x4A, 0x2C, 0x00, 0x45, 0x30, 0xFB, + 0x8D, 0x0A, 0x45, 0x2C, 0x0A, 0x45, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#endif /* _MAPPER006_H */ \ No newline at end of file diff --git a/src/mappers/mapper007.c b/src/mappers/mapper007.c new file mode 100644 index 000000000..3191b0063 --- /dev/null +++ b/src/mappers/mapper007.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.data); + setchr8(0); + setmirror(MI_0 + ((latch.data >> 4) & 0x01)); +} + +void Mapper007_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, (info->submapper == 2)); +} diff --git a/src/mappers/mapper009.c b/src/mappers/mapper009.c new file mode 100644 index 000000000..c3398cc8d --- /dev/null +++ b/src/mappers/mapper009.c @@ -0,0 +1,38 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "mmc2.h" + +static void M009PW(uint16 A, uint16 V) { + setprg8(A, V & 0x0F); +} + +static void M009CW(uint16 A, uint16 V) { + setchr4(A, V & 0x1F); +} + +void Mapper009_Init(CartInfo *info) { + int ws = info->iNES2 ? ((info->PRGRamSize + info->PRGRamSaveSize) / 1024) : (info->battery ? 8 : 0); + MMC2_Init(info, ws, info->battery); + MMC2_pwrap = M009PW; + MMC2_cwrap = M009CW; +} diff --git a/src/mappers/mapper010.c b/src/mappers/mapper010.c new file mode 100644 index 000000000..449eef3f5 --- /dev/null +++ b/src/mappers/mapper010.c @@ -0,0 +1,38 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "mmc4.h" + +static void M010PW(uint16 A, uint16 V) { + setprg16(A, V & 0x0F); +} + +static void M010CW(uint16 A, uint16 V) { + setchr4(A, V & 0x1F); +} + +void Mapper010_Init(CartInfo *info) { + int ws = info->iNES2 ? ((info->PRGRamSize + info->PRGRamSaveSize) / 1024) : (info->battery ? 8 : 0); + MMC4_Init(info, ws, info->battery); + MMC4_pwrap = M010PW; + MMC4_cwrap = M010CW; +} \ No newline at end of file diff --git a/src/mappers/mapper011.c b/src/mappers/mapper011.c new file mode 100644 index 000000000..a5c42cbcc --- /dev/null +++ b/src/mappers/mapper011.c @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.data); + setchr8(latch.data >> 4); +} + +void Mapper011_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper012.c b/src/mappers/mapper012.c new file mode 100644 index 000000000..51adafa30 --- /dev/null +++ b/src/mappers/mapper012.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static void M012CW(uint16 A, uint16 V) { + uint16 base = reg << ((A & 0x1000) ? 4 : 8); + + setchr1(A, (base & 0x100) | (V & 0xFF)); +} + +static DECLFW(M012Write) { + if (A & 0x100) { + reg = V; + MMC3_FixCHR(); + } +} + +static DECLFR(M012Read) { + if (A & 0x100) { + return dipsw; + } + return CartBR(A); +} + +static void M012Power(void) { + reg = 0; + dipsw = 1; /* chinese is default */ + MMC3_Power(); + SetWriteHandler(0x4100, 0x4FFF, M012Write); + SetReadHandler(0x4100, 0x4FFF, M012Read); +} + +static void M012Reset(void) { + reg = 0; + dipsw ^= 1; + MMC3_Reset(); +} + +void Mapper012_Init(CartInfo *info) { + if (info->submapper == 1) { + Mapper006_Init(info); + } else { + MMC3_Init(info, 8, info->battery); + MMC3_cwrap = M012CW; + isRevB = 0; + + info->Power = M012Power; + info->Reset = M012Reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&dipsw, 1, 0, "DPSW"); + } +} diff --git a/src/mappers/mapper013.c b/src/mappers/mapper013.c new file mode 100644 index 000000000..e60acf483 --- /dev/null +++ b/src/mappers/mapper013.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, 0); + setchr4(0x0000, 0); + setchr4(0x1000, latch.data); +} + +void Mapper013_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper014.c b/src/mappers/mapper014.c new file mode 100644 index 000000000..445db598a --- /dev/null +++ b/src/mappers/mapper014.c @@ -0,0 +1,107 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * SL1632 2-in-1 protected board, similar to SL12 + * Samurai Spirits Rex (Full) + * + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "vrc24.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 }, +}; + +static uint8 GetChrBase(uint16 A) { + if (A & 0x1000) { + if (A & 0x800) { + return ((reg & 0x80) >> 7); + } else { + return ((reg & 0x20) >> 5); + } + } + return ((reg & 0x08) >> 3); +} + +static void M014MMC3CW(uint16 A, uint16 V) { + uint16 mask = 0xFF; + uint16 base = GetChrBase(A) << 8; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M014VRC24CW(uint16 A, uint16 V) { + uint16 mask = 0xFF; + uint16 base = GetChrBase(A) << 8; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M014Write) { + if (A == 0xA131) { + reg = V; + if (reg & 0x02) { + MMC3_FixCHR(); + } else { + VRC24_FixCHR(); + } + } + if (reg & 0x02) { + MMC3_Write(A, V); + } else { + VRC24_Write(A, V); + } +} + +static void StateRestore(int version) { + if (reg & 0x02) { + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } else { + VRC24_FixPRG(); + VRC24_FixCHR(); + VRC24_FixMIR(); + } +} + +static void M014Power(void) { + reg = 0; + VRC24_Power(); + SetWriteHandler(0x8000, 0xFFFF, M014Write); +} + +void Mapper014_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M014MMC3CW; + + VRC24_Init(info, VRC2, 0x01, 0x02, FALSE, TRUE); + VRC24_cwrap = M014VRC24CW; + + info->Power = M014Power; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper015.c b/src/mappers/mapper015.c new file mode 100644 index 000000000..8f3ef3754 --- /dev/null +++ b/src/mappers/mapper015.c @@ -0,0 +1,56 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = latch.data & 0x3F; + + setprg8r(0x10, 0x6000, 0); + switch (latch.addr & 0x03) { + case 0: + setprg32(0x8000, prg >> 1); + break; + case 1: + setprg16(0x8000, prg); + setprg16(0xC000, prg | 0x07); + break; + case 2: + setprg8(0x8000, (prg << 1) | (latch.data >> 7)); + setprg8(0xA000, (prg << 1) | (latch.data >> 7)); + setprg8(0xC000, (prg << 1) | (latch.data >> 7)); + setprg8(0xE000, (prg << 1) | (latch.data >> 7)); + break; + case 3: + setprg16(0x8000, prg); + setprg16(0xC000, prg); + break; + } + setchr8(0); + setmirror(((latch.data >> 6) & 0x01) ^ 0x01); +} + +void Mapper015_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper016.c b/src/mappers/mapper016.c new file mode 100644 index 000000000..4e9b610ec --- /dev/null +++ b/src/mappers/mapper016.c @@ -0,0 +1,51 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "eeprom_x24c0x.h" +#include "bandai.h" + +static void M016PW(uint16 A, uint16 V) { + setprg16(A, V & 0x0F); +} + +static void M016CW(uint16 A, uint16 V) { + setchr1(A, V); +} + +void Mapper016_Init(CartInfo *info) { + switch (info->submapper) { + case 4: + BANDAI_Init(info, EEPROM_NONE, TRUE); + break; + case 5: + if (info->battery || ((info->PRGRamSaveSize > 0) && (info->PRGRamSaveSize <= 256))) { + BANDAI_Init(info, EEPROM_X24C02, FALSE); break; + } else { + BANDAI_Init(info, EEPROM_NONE, FALSE); break; + } + break; + default: + BANDAI_Init(info, EEPROM_NONE, TRUE); + break; + } + BANDAI_pwrap = M016PW; + BANDAI_cwrap = M016CW; +} diff --git a/src/mappers/mapper018.c b/src/mappers/mapper018.c new file mode 100644 index 000000000..8e85062c7 --- /dev/null +++ b/src/mappers/mapper018.c @@ -0,0 +1,163 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[4], chr[8]; +static uint8 IRQa, mirr; +static int32 IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { &IRQLatch, 4, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, ~0); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + if (mirr & 2) + setmirror(MI_0); + else + setmirror(mirr & 0x01); +} + +static DECLFW(M018WriteIRQ) { + switch (A & 0xF003) { + case 0xE000: + IRQLatch &= 0xFFF0; + IRQLatch |= (V & 0x0F) << 0x00; + break; + case 0xE001: + IRQLatch &= 0xFF0F; + IRQLatch |= (V & 0x0F) << 0x04; + break; + case 0xE002: + IRQLatch &= 0xF0FF; + IRQLatch |= (V & 0x0F) << 0x08; + break; + case 0xE003: + IRQLatch &= 0x0FFF; + IRQLatch |= (V & 0x0F) << 0x0C; + break; + case 0xF000: + IRQCount = IRQLatch; + break; + case 0xF001: + IRQa = V & 0x01; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xF002: + mirr = V & 0x03; + Sync(); + break; + } +} + +static DECLFW(M018WritePrg) { + uint32 i = ((A >> 1) & 1) | ((A - 0x8000) >> 11); + + if (A & 0x01) { + prg[i] = (prg[i] & 0x0F) | (V << 4); + } else { + prg[i] = (prg[i] & 0xF0) | (V & 0x0F); + } + Sync(); +} + +static DECLFW(M018WriteChr) { + uint32 i = ((A >> 1) & 1) | ((A - 0xA000) >> 11); + + if (A & 0x01) { + chr[i] = (chr[i] & 0x0F) | (V << 4); + } else { + chr[i] = (chr[i] & 0xF0) | (V & 0x0F); + } + Sync(); +} + +static void M018Power(void) { + IRQa = 0; + prg[0] = 0; + prg[1] = 1; + prg[2] = ~1; + prg[3] = ~0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0x9FFF, M018WritePrg); + SetWriteHandler(0xA000, 0xDFFF, M018WriteChr); + SetWriteHandler(0xE000, 0xFFFF, M018WriteIRQ); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M018IRQHook(int a) { + if (IRQa && IRQCount) { + IRQCount -= a; + if (IRQCount <= 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount = 0; + IRQa = 0; + } + } +} + +static void M018Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper018_Init(CartInfo *info) { + info->Power = M018Power; + info->Close = M018Close; + MapIRQHook = M018IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } +} diff --git a/src/mappers/mapper019.c b/src/mappers/mapper019.c new file mode 100644 index 000000000..53b552861 --- /dev/null +++ b/src/mappers/mapper019.c @@ -0,0 +1,252 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "n163sound.h" + +static uint8 prg[4]; +static uint8 chr[8]; +static uint8 nt[4]; +static uint8 wram_protect; + +static uint16 IRQCount; +static uint8 IRQa; + +static SFORMAT N163_StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { nt, 4, "NMTA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { &wram_protect, 1, "WPRT" }, + + { 0 } +}; + +static void SyncPRG(void) { + setprg8(0x8000, prg[0] & 0x3F); + setprg8(0xa000, prg[1] & 0x3F); + setprg8(0xc000, prg[2] & 0x3F); + setprg8(0xe000, prg[3] & 0x3F); +} + +static void DoCHRRAMROM(int x, uint8 V) { + chr[x] = V; + if (((prg[1] >> ((x >> 2) + 6)) & 1) || (V < 0xE0)) { + setchr1(x << 10, V); + } +} + +static void FixCRR(void) { + int x; + for (x = 0; x < 8; x++) { + DoCHRRAMROM(x, chr[x]); + } +} + +static void DoNTARAMROM(int w, uint8 V) { + nt[w] = V; + if (V < 0xE0) { + V &= CHRmask1[0]; + setntamem(CHRptr[0] + (V << 10), 0, w); + } else { + setntamem(NTARAM + ((V & 1) << 10), 1, w); + } +} + +static void FixNTAR(void) { + int x; + for (x = 0; x < 4; x++) { + DoNTARAMROM(x, nt[x]); + } +} + +static void NamcoIRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount >= 0x7FFF) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + IRQCount = 0x7FFF; + } + } +} + +static DECLFR(AWRAM) { + return WRAM[A - 0x6000]; +} + +static DECLFW(BWRAM) { + if (((A >= 0x6000) && (A <= 0x67FF) && ((wram_protect & 0xF1) == 0x40)) || + ((A >= 0x6800) && (A <= 0x6FFF) && ((wram_protect & 0xF2) == 0x40)) || + ((A >= 0x7000) && (A <= 0x77FF) && ((wram_protect & 0xF4) == 0x40)) || + ((A >= 0x7800) && (A <= 0x7FFF) && ((wram_protect & 0xF8) == 0x40))) { + WRAM[A - 0x6000] = V; + } +} + +static DECLFR(M019Read) { + switch (A & 0xF800) { + case 0x4800: + return N163Sound_Read(A); + case 0x5000: + return IRQCount & 0xFF; + case 0x5800: + return IRQCount >> 8; + } + + return 0; +} + +static DECLFW(M019Write) { + switch (A & 0xF800) { + case 0x4800: + N163Sound_Write(A, V); + break; + case 0x5000: + IRQCount &= 0xFF00; + IRQCount |= V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x5800: + IRQCount &= 0x00ff; + IRQCount |= (V & 0x7F) << 8; + IRQa = V & 0x80; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x8000: + case 0x8800: + case 0x9000: + case 0x9800: + case 0xA000: + case 0xA800: + case 0xB000: + case 0xB800: + DoCHRRAMROM((A - 0x8000) >> 11, V); + break; + case 0xC000: + case 0xC800: + case 0xD000: + case 0xD800: + DoNTARAMROM((A - 0xC000) >> 11, V); + break; + case 0xE000: + prg[0] = V; + SyncPRG(); + break; + case 0xE800: + prg[1] = V; + SyncPRG(); + FixCRR(); + break; + case 0xF000: + prg[2] = V; + SyncPRG(); + break; + case 0xF800: + wram_protect = V; + N163Sound_Write(A, V); + break; + } +} + +static void StateRestore(int version) { + SyncPRG(); + FixNTAR(); + FixCRR(); +} + +static int battery = 0; + +static void N163_Power(void) { + prg[0] = ~3; + prg[1] = ~2; + prg[2] = ~1; + prg[3] = ~0; + + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + chr[4] = 4; + chr[5] = 5; + chr[6] = 6; + chr[7] = 7; + + nt[0] = 0xE0; + nt[1] = 0xE1; + nt[2] = 0xE0; + nt[3] = 0xE1; + + wram_protect = 0xFF; + + SyncPRG(); + FixCRR(); + FixNTAR(); + + SetReadHandler(0x4800, 0x5FFF, M019Read); + SetWriteHandler(0x4800, 0x5FFF, M019Write); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M019Write); + + if (WRAMSIZE) { + SetReadHandler(0x6000, 0x7FFF, AWRAM); + SetWriteHandler(0x6000, 0x7FFF, BWRAM); + FCEU_CheatAddRAM(8, 0x6000, WRAM); + } + + if (!battery) { + FCEU_MemoryRand(WRAM, sizeof(WRAM)); + FCEU_MemoryRand(GetIRAM_ptr(), GetIRAM_size()); + } +} + +void Mapper019_Init(CartInfo *info) { + battery = info->battery; + info->Power = N163_Power; + + MapIRQHook = NamcoIRQHook; + GameStateRestore = StateRestore; + AddExState(N163_StateRegs, ~0, 0, 0); + + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } else if (info->battery) { + WRAMSIZE = 8192; + } + + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = 8192; + info->SaveGame[1] = GetIRAM_ptr(); + info->SaveGameLen[1] = GetIRAM_size(); + } + + N163Sound_ESI(); + N163Sound_AddStateInfo(); +} diff --git a/src/mappers/mapper021.c b/src/mappers/mapper021.c new file mode 100644 index 000000000..8bddb7535 --- /dev/null +++ b/src/mappers/mapper021.c @@ -0,0 +1,31 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "vrc24.h" + +void Mapper021_Init(CartInfo *info) { + /* Mapper 21 - VRC4a, VRC4c */ + switch (info->submapper) { + case 1: VRC24_Init(info, VRC4, 0x02, 0x04, 1, 1); break; + case 2: VRC24_Init(info, VRC4, 0x40, 0x80, 1, 1); break; + default: VRC24_Init(info, VRC4, 0x42, 0x84, 1, 1); break; + } +} diff --git a/src/mappers/mapper022.c b/src/mappers/mapper022.c new file mode 100644 index 000000000..fae114a0b --- /dev/null +++ b/src/mappers/mapper022.c @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "vrc24.h" + +static void M22CW(uint16 A, uint16 V) { + setchr1(A, (V & 0xFF) >> 1); +} + +void Mapper022_Init(CartInfo *info) { + /* Mapper 22 - VRC2a */ + VRC24_Init(info, VRC2, 0x02, 0x01, 0, 1); + VRC24_cwrap = M22CW; +} diff --git a/src/mappers/mapper023.c b/src/mappers/mapper023.c new file mode 100644 index 000000000..ae341063d --- /dev/null +++ b/src/mappers/mapper023.c @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "vrc24.h" + +void Mapper023_Init(CartInfo *info) { + /* Mapper 23 - VRC2b, VRC4e, VRC4f */ + switch (info->submapper) { + case 1: VRC24_Init(info, VRC4, 0x01, 0x02, 1, 1); break; + case 2: VRC24_Init(info, VRC4, 0x04, 0x08, 1, 1); break; + case 3: VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); break; + default: VRC24_Init(info, VRC4, 0x05, 0x0A, 1, 1); break; + } +} diff --git a/src/mappers/mapper024.c b/src/mappers/mapper024.c new file mode 100644 index 000000000..183c0b5d1 --- /dev/null +++ b/src/mappers/mapper024.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "vrc6.h" + +static void M024PW(uint16 A, uint16 V) { + setprg8(A, V & 0x3F); +} + +static void M024CW(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +void Mapper024_Init(CartInfo *info) { + int wram = 0; + if (info->iNES2 && (info->PRGRamSize || info->PRGRamSaveSize)) { + wram = 1; + } else if (info->battery) { + wram = 1; + } + VRC6_Init(info, 0x01, 0x02, wram); + VRC6_pwrap = M024PW; + VRC6_cwrap = M024CW; +} diff --git a/src/mappers/mapper025.c b/src/mappers/mapper025.c new file mode 100644 index 000000000..3cc05b39f --- /dev/null +++ b/src/mappers/mapper025.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "vrc24.h" + +static void M025CW(uint16 A, uint16 V) { + setchr1(A, V & 0xFFF); +} + +void Mapper025_Init(CartInfo *info) { + /* Mapper 25 - VRC2c, VRC4b, VRC4d */ + switch (info->submapper) { + case 1: VRC24_Init(info, VRC4, 0x02, 0x01, 1, 1); break; + case 2: VRC24_Init(info, VRC4, 0x08, 0x04, 1, 1); break; + case 3: VRC24_Init(info, VRC2, 0x02, 0x01, 0, 1); break; + default: VRC24_Init(info, VRC4, 0x0A, 0x05, 1, 1); break; + } + VRC24_cwrap = M025CW; +} diff --git a/src/mappers/mapper026.c b/src/mappers/mapper026.c new file mode 100644 index 000000000..f2bdda3c9 --- /dev/null +++ b/src/mappers/mapper026.c @@ -0,0 +1,38 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "vrc6.h" + +static void M026PW(uint16 A, uint16 V) { + setprg8(A, V & 0x3F); +} + +static void M026CW(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +void Mapper026_Init(CartInfo *info) { + VRC6_Init(info, 0x02, 0x01, 1); + VRC6_pwrap = M026PW; + VRC6_cwrap = M026CW; +} diff --git a/src/mappers/mapper027.c b/src/mappers/mapper027.c new file mode 100644 index 000000000..0813e713f --- /dev/null +++ b/src/mappers/mapper027.c @@ -0,0 +1,34 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2013 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, 0); + setchr4(0x0000, ((latch.addr << 1) & 0x02) | (latch.addr & 0x01)); + setchr4(0x1000, ((latch.addr << 1) & 0x02) | (latch.addr & 0x01)); + setmirror(MI_0 + (latch.addr & 0x01)); +} + +void Mapper027_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper028.c b/src/mappers/mapper028.c new file mode 100644 index 000000000..5b9c54ef9 --- /dev/null +++ b/src/mappers/mapper028.c @@ -0,0 +1,107 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2019-5-23 + * Mapper 28 - Action 53 + * http://wiki.nesdev.com/w/index.php/INES_Mapper_028 */ + +#include "mapinc.h" + +static uint8 cmd; +static uint8 reg[4]; + +static SFORMAT StateRegs[] = { + {&cmd, 1, "REG"}, + {reg, 4, "REGS"}, + {0} +}; + +static uint8 bank_size_masks[4] = { 0x01, 0x03, 0x07, 0x0F }; +static uint16 GetPRGBank(int V) { + uint16 cpu_a14 = V & 0x01; + uint16 outer_bank = reg[3] << 1; + uint16 bank_mode = reg[2] >> 2; /* discard mirroring bits */ + uint16 current_bank = reg[1]; + uint16 bank_size_mask = 0; + + if (((bank_mode ^ cpu_a14) & 0x03) == 0x02) { /* in UNROM fixed bank? */ + bank_mode = 0; /* if so, treat as NROM */ + } + if ((bank_mode & 0x02) == 0) { /* in 32K bank mode? */ + current_bank = (current_bank << 1) | cpu_a14; + } + bank_size_mask = bank_size_masks[(bank_mode >> 2) & 3]; + return ((current_bank & bank_size_mask) | (outer_bank & ~bank_size_mask)); +} + +static void Sync(void) { + setprg16(0x8000, GetPRGBank(0)); + setprg16(0xC000, GetPRGBank(1)); + setchr8(reg[0] & 0x03); + switch (reg[2] & 0x03) { + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_1); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_H); break; + } +} + +static DECLFW(WriteCMD) { + cmd = ((V >> 6) & 0x02) | (V & 0x01); +} + +static DECLFW(WriteREG) { + reg[cmd] = V; + if (!(cmd & 0x02) && !(reg[2] & 0x02)) { + reg[2] &= ~0x01; + reg[2] |= (V >> 4) & 0x01; + } + Sync(); +} + +static void M028Power(void) { + reg[0] = ~0; + reg[1] = ~0; + reg[2] = ~0; + reg[3] = ~0; + Sync(); + + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + SetWriteHandler(0x5000, 0x5FFF, WriteCMD); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, WriteREG); +} + +static void M028Reset(void) { + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper028_Init(CartInfo *info) { + info->Power = M028Power; + info->Reset = M028Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper029.c b/src/mappers/mapper029.c new file mode 100644 index 000000000..a0b038e70 --- /dev/null +++ b/src/mappers/mapper029.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Mapper 28, used by homebrew game Glider + * https://wiki.nesdev.com/w/index.php/INES_Mapper_029 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.data >> 2); + setprg16(0xc000, ~0); + setprg8r(0x10, 0x6000, 0); + setchr8r(0, latch.data & 3); +} + +void Mapper029_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, FALSE); +} diff --git a/src/mappers/mapper030.c b/src/mappers/mapper030.c new file mode 100644 index 000000000..8014966e1 --- /dev/null +++ b/src/mappers/mapper030.c @@ -0,0 +1,144 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2014 CaitSith2, 2022 Cluster + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Roms still using NES 1.0 format should be loaded as 8K CHR RAM. + * Roms defined under NES 2.0 should use the VRAM size field, defining 7, 8 or 9, based on how much VRAM should be + * present. UNIF doesn't have this problem, because unique board names can define this information. The UNIF names are + * UNROM-512-8K, UNROM-512-16K and UNROM-512-32K + * + * The battery flag in the NES header enables flash, Mirrror mode 2 Enables MI_0 and MI_1 mode. + * Known games to use this board are: + * Battle Kid 2: Mountain of Torment (512K PRG, 8K CHR RAM, Horizontal Mirroring, Flash disabled) + * Study Hall (128K PRG (in 512K flash chip), 8K CHR RAM, Horizontal Mirroring, Flash enabled) + * Nix: The Paradox Relic (512 PRG, 8K CHR RAM, Vertical Mirroring, Flash enabled) + * Although Xmas 2013 uses a different board, where LEDs can be controlled (with writes to the $8000-BFFF space), + * it otherwise functions identically. + */ + +#include "mapinc.h" +#include "latch.h" +#include "flashrom.h" + +#define ROM_CHIP 0x00 +#define FLASH_CHIP 0x10 + +static uint8 flash_save; +static uint8 *flash_data; + +static void M030Sync(void) { + int chip = flash_save ? FLASH_CHIP : ROM_CHIP; + + setprg16r(chip, 0x8000, latch.data); + setprg16r(chip, 0xC000, ~0); + setchr8(latch.data >> 5); + switch (iNESCart.submapper) { + case 1: + /* Mega Man II (30th Anniversary Edition) */ + setmirror((latch.data >> 7) & 0x01); + break; + default: + setmirror(MI_0 + ((latch.data >> 7) & 0x01)); + break; + } +} + +static void M030CPUHook(int a) { + FlashROM_CPUCyle(a); +} + +static DECLFR(M030Read) { + if ((A < 0xC000) && flash_save) { + return FlashROM_Read(A); + } + return CartBR(A); +} + +static DECLFW(M030Write) { + if ((A < 0xC000) && flash_save) { + FlashROM_Write(A, V); + } else { + Latch_Write(A, V); + } +} + +static void M030Power(void) { + Latch_Power(); + SetReadHandler(0x8000, 0xFFFF, M030Read); + SetWriteHandler(0x8000, 0xBFFF, M030Write); +} + +static void M030Close(void) { + Latch_Close(); + if (flash_data) { + FCEU_gfree(flash_data); + } + flash_data = NULL; +} + +void Mapper030_Init(CartInfo *info) { + int mirror2bits = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2); + + flash_save = info->battery; + Latch_Init(info, M030Sync, NULL, 0, !flash_save); + + if (!info->submapper && (info->PRGCRC32 == 0x891C14BC)) { + info->submapper = 0x01; + } + + if (!(info->submapper & 1)) { + switch (mirror2bits) { + case 0: /* hard horizontal, internal */ + SetupCartMirroring(MI_H, 1, NULL); + break; + case 1: /* hard vertical, internal */ + SetupCartMirroring(MI_V, 1, NULL); + break; + case 2: /* switchable 1-screen, internal (flags: 4-screen + horizontal) */ + SetupCartMirroring(MI_0, 0, NULL); + break; + case 3: /* hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical) */ + SetupCartMirroring(4, 1, CHR_ROM_DATA + (info->CHRRamSize - 8192)); + break; + } + } + + info->Power = M030Power; + info->Close = M030Close; + + if (flash_save) { + uint32 i, ssize; + /* Allocate memory for flash */ + ssize = PRGsize[0]; + flash_data = (uint8 *)FCEU_gmalloc(ssize); + /* Copy ROM to flash data */ + for (i = 0; i < ssize; i++) { + flash_data[i] = PRGptr[ROM_CHIP][i % ssize]; + } + SetupCartPRGMapping(FLASH_CHIP, flash_data, ssize, 1); + AddExState(flash_data, ssize, 0, "FLSH"); + info->SaveGame[0] = flash_data; + info->SaveGameLen[0] = ssize; + + FlashROM_Init(flash_data, ssize, 0xBF, 0xB7, 4096, 0x5555, 0x2AAA); + MapIRQHook = M030CPUHook; + } +} diff --git a/src/mappers/mapper031.c b/src/mappers/mapper031.c new file mode 100644 index 000000000..489dc81f7 --- /dev/null +++ b/src/mappers/mapper031.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2019-5-23 + * Mapper 31 - custom mapper by infiniteneslives + * https://wiki.nesdev.com/w/index.php/INES_Mapper_031 */ + +#include "mapinc.h" + +static uint8 prg[8]; + +static SFORMAT StateRegs[] = { + { prg, 8, "PREG" }, + { 0 } +}; + +static void Sync(void) { + setprg4(0x8000, prg[0]); + setprg4(0x9000, prg[1]); + setprg4(0xA000, prg[2]); + setprg4(0xB000, prg[3]); + setprg4(0xC000, prg[4]); + setprg4(0xD000, prg[5]); + setprg4(0xE000, prg[6]); + setprg4(0xF000, prg[7]); + setchr8(0); +} + +static DECLFW(M031Write) { + prg[A & 0x07] = V; + Sync(); +} + +static void M031Power(void) { + prg[0] = ~7; + prg[1] = ~6; + prg[2] = ~5; + prg[3] = ~4; + prg[4] = ~3; + prg[5] = ~2; + prg[6] = ~1; + prg[7] = ~0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, M031Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper031_Init(CartInfo *info) { + info->Power = M031Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper032.c b/src/mappers/mapper032.c new file mode 100644 index 000000000..4abd47eb0 --- /dev/null +++ b/src/mappers/mapper032.c @@ -0,0 +1,132 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[2], chr[8], prgMode, mirr; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { &prgMode, 1, "MODE" }, + { &mirr, 1, "mirr" }, + { 0 } +}; + +static void Sync(void) { + if (prgMode == 0) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + } else { + setprg8(0x8000, ~1); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[0]); + setprg8(0xE000, ~0); + } + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + if (iNESCart.submapper == 1) { + setmirror(MI_1); + } else { + setmirror((mirr & 0x01) ^ 0x01); + } +} + +static DECLFW(M032Write) { + switch (A & 0xF000) { + case 0x8000: + case 0xA000: + prg[(A >> 13) & 0x01] = V; + Sync(); + break; + case 0x9000: + mirr = (V & 0x01) != 0; + prgMode = (V & 0x02) != 0; + if (iNESCart.submapper == 1) { + prgMode = 0; + } + Sync(); + break; + case 0xB000: + chr[A & 0x07] = V; + Sync(); + break; + } +} + +static void M032Power(void) { + prg[0] = 0; + prg[1] = 1; + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + chr[4] = 4; + chr[5] = 5; + chr[6] = 6; + chr[7] = 7; + prgMode = 0; + Sync(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M032Write); + + if (WRAM) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } +} + +static void M032Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper032_Init(CartInfo *info) { + info->Power = M032Power; + info->Close = M032Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } +} diff --git a/src/mappers/mapper033.c b/src/mappers/mapper033.c new file mode 100644 index 000000000..a8f57b24e --- /dev/null +++ b/src/mappers/mapper033.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 33 - Taito TC0190/TC0350 */ + +#include "mapinc.h" + +static uint8 prg[2], chr[6]; + +static SFORMAT StateRegs[] = { + { prg, 2, "PREG" }, + { chr, 6, "CREG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg16(0xC000, ~0); + + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr1(0x1000, chr[2]); + setchr1(0x1400, chr[3]); + setchr1(0x1800, chr[4]); + setchr1(0x1C00, chr[5]); + + setmirror(((prg[0] >> 6) & 0x01) ^ 0x01); +} + +static DECLFW(M033Write) { + switch (A & 0xE003) { + case 0x8000: + case 0x8001: + prg[A & 0x01] = V; + Sync(); + break; + case 0x8002: + case 0x8003: + chr[A & 0x01] = V; + Sync(); + break; + case 0xA000: + case 0xA001: + case 0xA002: + case 0xA003: + chr[2 + (A & 0x03)] = V; + Sync(); + break; + } +} + +static void M33Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, M033Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper033_Init(CartInfo *info) { + info->Power = M33Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} + diff --git a/src/mappers/mapper034.c b/src/mappers/mapper034.c new file mode 100644 index 000000000..472a3f416 --- /dev/null +++ b/src/mappers/mapper034.c @@ -0,0 +1,149 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Many-in-one hacked mapper crap. + * + * Original BNROM is actually AxROM variations without mirroring control, + * and haven't SRAM on-board, so it must be removed from here + * + * Difficult banking is what NINA board doing, most hacks for 34 mapper are + * NINA hacks, so this is actually 34 mapper + * + */ + +#include "mapinc.h" +#include "latch.h" + +#define M034_NINA001 1 +#define M034_BNROM 2 +#define M034_NESTICLE 3 + +static uint8 reg[3]; + +static uint8 type; +static void (*WSync)(void); + +static SFORMAT StateRegs[] = { + { reg, 3, "REGS" }, + { 0 } +}; + +/* submapper 1 - AVE NINA-001 */ + +static void Sync_NINA001(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, reg[0]); + setchr4(0x0000, reg[1]); + setchr4(0x1000, reg[2]); +} + +static DECLFW(M034Write_NINA001) { + CartBW(A, V); + if (A >= 0x7FFD) { + reg[A - 0x7FFD] = V; + WSync(); + } +} + +static void M034Power_NINA001(void) { + reg[0] = reg[1] = 0; + reg[2] = 1; + WSync(); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M034Write_NINA001); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +/* submapper 2 - BNROM */ + +static void Sync_BNROM(void) { + setprg32(0x8000, latch.data); + setchr8(0); +} + +/* nesticle */ + +static void Sync_Nesticle(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, reg[0]); + setchr4(0x0000, reg[1]); + setchr4(0x1000, reg[2]); +} + +static DECLFW(M034Write_Nesticle) { + if (A >= 0x8000) { + reg[0] = V; + WSync(); + } else { + CartBW(A, V); + if (A >= 0x7FFD) { + reg[A - 0x7FFD] = V; + WSync(); + } + } +} + +static void M034Power_Nesticle(void) { + reg[0] = reg[1] = 0; + reg[2] = 1; + WSync(); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, M034Write_Nesticle); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M034Close(void) { +} + +static void StateRestore(int version) { + WSync(); +} + +void Mapper034_Init(CartInfo *info) { + if (info->trainer) { + type = M034_NESTICLE; + WSync = Sync_Nesticle; + info->Power = M034Power_Nesticle; + } else if ((info->submapper == 1) || ((info->submapper != 2) && CHR_ROM_SIZE_8K)) { + type = M034_NINA001; + WSync = Sync_NINA001; + info->Power = M034Power_NINA001; + } else if ((info->submapper == 2) || ((info->submapper != 1) && !CHR_ROM_SIZE_8K)) { + type = M034_BNROM; + Latch_Init(info, Sync_BNROM, NULL, FALSE, TRUE); + info->Reset = Latch_RegReset; + } + + switch (type) { + case M034_NESTICLE: + case M034_NINA001: + info->Close = M034Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + break; + } +} diff --git a/src/mappers/mapper036.c b/src/mappers/mapper036.c new file mode 100644 index 000000000..fdc2d8016 --- /dev/null +++ b/src/mappers/mapper036.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "txc.h" + +static uint8 chr = 0; + +static void M036Sync(void) { + setprg32(0x8000, txc.output & 0x03); + setchr8(chr & 0x0F); +} + +static DECLFW(M036Write) { + if ((A & 0xF200) == 0x4200) { + chr = V; + } + TXC_Write(A, (V >> 4) & 0x03); +} + +static DECLFR(M036Read) { + return (CPU_OPENBUS & ~0x30) | ((TXC_Read(A) << 4) & 0x30); +} + +static void M036Power(void) { + chr = 0; + TXC_Power(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M036Read); + SetWriteHandler(0x4100, 0xFFFF, M036Write); +} + +void Mapper036_Init(CartInfo *info) { + TXC_Init(info, M036Sync); + info->Power = M036Power; + AddExState(&chr, 1, 0, "CREG"); +} diff --git a/src/mappers/mapper037.c b/src/mappers/mapper037.c new file mode 100644 index 000000000..5fcb457b8 --- /dev/null +++ b/src/mappers/mapper037.c @@ -0,0 +1,66 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M037PW(uint16 A, uint16 V) { + uint16 mask = (reg << 1) | 0x07; + uint16 base = ((reg << 2) & 0x10) | (((reg & 0x03) == 0x03) ? 0x08 : 0); + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M037CW(uint16 A, uint16 V) { + uint16 mask = 0x7F; + uint16 base = (reg << 5) & 0x80; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M037Write) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M037Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M037Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M037Write); +} + +void Mapper037_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + MMC3_pwrap = M037PW; + MMC3_cwrap = M037CW; + info->Power = M037Power; + info->Reset = M037Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper038.c b/src/mappers/mapper038.c new file mode 100644 index 000000000..d036d050c --- /dev/null +++ b/src/mappers/mapper038.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg & 0x03); + setchr8((reg >> 2) & 0x03); +} + +static DECLFW(M038Write) { + reg = V; + Sync(); +} + +static void M038Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x7000, 0x7FFF, M038Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper038_Init(CartInfo *info) { + info->Power = M038Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper040.c b/src/mappers/mapper040.c new file mode 100644 index 000000000..9218ce246 --- /dev/null +++ b/src/mappers/mapper040.c @@ -0,0 +1,113 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg[2]; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { 0 } +}; + +static void Sync(void) { + if (reg[1] & 0x08) { + if (reg[1] & 0x10) + setprg32(0x8000, 2 | (reg[1] >> 6)); + else { + setprg16(0x8000, 4 | (reg[1] >> 5)); + setprg16(0xC000, 4 | (reg[1] >> 5)); + } + } else { + setprg8(0x6000, 6); + setprg8(0x8000, 4); + setprg8(0xA000, 5); + setprg8(0xC000, reg[0] & 0x07); + setprg8(0xE000, 7); + } + setchr8((reg[1] >> 1) & 0x03); + setmirror((reg[1] & 0x01) ^ 0x01); +} + +static DECLFW(M040Write) { + switch (A & 0xE000) { + case 0x8000: + IRQa = FALSE; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xA000: + IRQa = TRUE; + break; + case 0xC000: + if (iNESCart.submapper == 1) { + reg[1] = A & 0xFF; + Sync(); + } + break; + case 0xE000: + reg[0] = V; + Sync(); + break; + } +} + +static void M040Power(void) { + reg[0] = reg[1] = 0; + IRQCount = IRQa = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M040Write); +} + +static void M040Reset(void) { + reg[0] = 0; + reg[1] = 0; + IRQCount = IRQa = 0; + Sync(); +} + +static void M040IRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount & 0x1000) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper040_Init(CartInfo *info) { + info->Reset = M040Reset; + info->Power = M040Power; + MapIRQHook = M040IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper041.c b/src/mappers/mapper041.c new file mode 100644 index 000000000..12b440ce1 --- /dev/null +++ b/src/mappers/mapper041.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg[0] & 0x07); + setchr8(((reg[0] >> 1) & 0x0C) | (reg[1] & 0x03)); + setmirror(((reg[0] >> 5) & 0x01) ^ 0x01); +} + +static DECLFW(M041Write0) { + reg[0] = A; + Sync(); +} + +static DECLFW(M041Write1) { + if (reg[0] & 0x04) { + /* bus conflict */ + reg[1] = (V & CartBR(A)); + Sync(); + } +} + +static void M041Reset(void) { + reg[0] = reg[1] = 0; + Sync(); +} + +static void M041Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x67FF, M041Write0); + SetWriteHandler(0x8000, 0xFFFF, M041Write1); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper041_Init(CartInfo *info) { + info->Power = M041Power; + info->Reset = M041Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper042.c b/src/mappers/mapper042.c new file mode 100644 index 000000000..147ac1e21 --- /dev/null +++ b/src/mappers/mapper042.c @@ -0,0 +1,201 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * - Submapper 1 - Ai Senshi Nicol (256K PRG, 128K CHR, fixed Mirroring) + * - Submapper 3 - Bio Miracle Bokutte Upa (J) (128K PRG, 0K CHR, IRQ) + * + * - Submapper 2 + * - KS-018/AC-08/LH09 + * - UNIF UNL-AC08 + * - [UNIF] Green Beret (FDS Conversion, LH09) (Unl) [U][!][t1] (160K PRG) + * - Green Beret (FDS Conversion) (Unl) (256K PRG) + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg[2]; +static uint8 IRQa; +static uint16 IRQCount; + +static void (*WSync)(void); + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { 0 } +}; + +/* Submapper 1 - Ai Senshi Nicol */ + +static void M042_Sub1_Sync(void) { + setprg8(0x6000, reg[1] & 0x0F); + setprg32(0x8000, ~0); + setchr8(reg[0] & 0x0F); +} + +static DECLFW(M042_Sub1_Write) { + switch (A & 0xE000) { + case 0x8000: + reg[0] = V; + WSync(); + break; + case 0xE000: + reg[1] = V; + WSync(); + break; + } +} + +static void M042_Sub1_Power(void) { + reg[1] = 0; + reg[0] = 0; + FDSSound_Power(); + WSync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M042_Sub1_Write); +} + +/* Submapper 2 - Green Beret */ + +static void M042_Sub2_Sync(void) { + setprg8(0x6000, (reg[0] >> 1) & 0x0F); + setprg32(0x8000, (PRG_BANK_COUNT(16) & 0x07) ? 4 : 7); + setchr8(0); + setmirror(((reg[1] >> 3) & 1) ^ 1); +} + +static DECLFW(M042_Sub2_Write) { + switch (A & 0xF001) { + case 0x4001: + case 0x4000: + if ((A & 0xFF) != 0x25) { + break; + } + reg[1] = V; + WSync(); + break; + case 0x8001: + reg[0] = V; + WSync(); + break; + } +} + +static void M042_Sub2_Power(void) { + reg[0] = 0; + reg[1] = 0; + WSync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0xFFFF, M042_Sub2_Write); +} + +/* Submapper 3 - Mario Baby */ + +static void M042_Sub3_Sync(void) { + setprg8(0x6000, reg[0] & 0x0F); + setprg32(0x8000, ~0); + setchr8(0); + setmirror(((reg[1] >> 3) & 1) ^ 1); +} + +static DECLFW(M042_Sub3_Write) { + switch (A & 0xE003) { + case 0xE000: + reg[0] = V; + WSync(); + break; + case 0xE001: + reg[1] = V; + WSync(); + break; + case 0xE002: + IRQa = (V & 0x02) != 0; + if (!IRQa) { + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + break; + } +} + +static void M042_Sub3_Power(void) { + reg[0] = 0; + reg[1] = 0; + IRQa = IRQCount = 0; + WSync(); + FDSSound_Power(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0xE000, 0xFFFF, M042_Sub3_Write); +} + +static void M042_Sub3_IRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount >= 24576) { + X6502_IRQBegin(FCEU_IQEXT); + } else { + X6502_IRQEnd(FCEU_IQEXT); + } + } +} + +/* Mapper 42 Loader */ +static void StateRestore(int version) { + WSync(); +} + +void Mapper042_Init(CartInfo *info) { + if (info->submapper == 0 || info-> submapper > 3) { + if (CHR_ROM_SIZE_8K) { + /* Ai Senshi Nicol, only cart with CHR-ROM, all others use CHR-RAM */ + info->submapper = 1; + } else { + if (PRG_ROM_SIZE_16K > (128 * 1024)) { + /* Green Beret LH09 FDS Conversion can be 160K or 256K */ + info->submapper = 2; + } else { + /* Mario Baby has only 128K PRG */ + info->submapper = 3; + } + } + } + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + switch (info->submapper) { + case 1: + info->Power = M042_Sub1_Power; + WSync = M042_Sub1_Sync; + break; + case 2: + info->Power = M042_Sub2_Power; + WSync = M042_Sub2_Sync; + break; + default: + info->Power = M042_Sub3_Power; + WSync = M042_Sub3_Sync; + MapIRQHook = M042_Sub3_IRQHook; + break; + } +} diff --git a/src/mappers/mapper043.c b/src/mappers/mapper043.c new file mode 100644 index 000000000..7840198de --- /dev/null +++ b/src/mappers/mapper043.c @@ -0,0 +1,97 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg, swap; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = { + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { ®, 1, "REGS" }, + { &swap, 1, "SWAP" }, + { 0 } +}; + +static void Sync(void) { + int transo[8] = { 4, 3, 4, 4, 4, 7, 5, 6 }; + + setprg4(0x5000, 8 << 1); /* Only YS-612 advanced version */ + setprg8(0x6000, swap ? 0 : 2); + setprg8(0x8000, 1); + setprg8(0xA000, 0); + setprg8(0xC000, transo[reg & 0x07]); + setprg8(0xE000, swap ? 8 : 9); /* hard dump for mr.Mary is 128K, + * bank 9 is the last 2K ok bank 8 repeated 4 times, then till the end of 128K + * instead used bank A, containing some CHR data, ines rom have unused banks removed, + * and bank A moved to the bank 9 place for compatibility with other crappy dumps + */ + setchr8(0); +} + +static DECLFW(M043Write) { + switch (A & 0xF1FF) { + case 0x4022: + reg = V; + Sync(); + break; + case 0x4120: + swap = V & 0x01; + Sync(); + break; + case 0x8122: /* hacked version */ + case 0x4122: /* original version */ + IRQa = V & 0x01; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +static void M043Power(void) { + reg = swap = 0; + Sync(); + SetReadHandler(0x5000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0x8FFF, M043Write); +} + +static void M043IRQHook(int a) { + IRQCount += a; + if (IRQa && (IRQCount >= 4096)) { + IRQa = 0; + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper043_Init(CartInfo *info) { + info->Power = M043Power; + MapIRQHook = M043IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper044.c b/src/mappers/mapper044.c new file mode 100644 index 000000000..e0f170f1f --- /dev/null +++ b/src/mappers/mapper044.c @@ -0,0 +1,63 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M044PW(uint16 A, uint16 V) { + uint8 base = (mmc3.wram << 4) & 0x70; + uint8 mask = ((mmc3.wram & 0x06) == 0x06) ? 0x1F : 0x0F; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M044CW(uint16 A, uint16 V) { + uint16 base = (mmc3.wram << 7) & 0x380; + uint16 mask = ((mmc3.wram & 0x06) == 0x06) ? 0xFF : 0x7F; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static DECLFW (M044WriteA000) { + MMC3_CMDWrite(A, V); + switch (A & 0xE001) { + case 0xA001: + MMC3_FixPRG(); + MMC3_FixCHR(); + break; + } +} + +static void M044Reset(void) { + MMC3_Reset(); +} + +static void M044Power(void) { + MMC3_Power(); + SetWriteHandler(0xA000, 0xBFFF, M044WriteA000); +} + +void Mapper044_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + MMC3_cwrap = M044CW; + MMC3_pwrap = M044PW; + info->Power = M044Power; + info->Reset = M044Reset; +} diff --git a/src/mappers/mapper045.c b/src/mappers/mapper045.c new file mode 100644 index 000000000..0bb22e3a6 --- /dev/null +++ b/src/mappers/mapper045.c @@ -0,0 +1,108 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; +static uint8 cmd; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &cmd, 1, "CMD0" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M045CW(uint16 A, uint16 V) { + if (CHR_ROM_SIZE_8K || (iNESCart.CHRRamSize > 8192)) { + uint32 mask = 0xFF >> (~reg[2] & 0x0F); + uint32 base = ((reg[2] << 4) & 0xF00) | reg[0]; + + setchr1(A, (base & ~mask) | (V & mask)); + } else { + /* assume chr-ram, 4-in-1 Yhc-Sxx-xx variants */ + setchr8(0); + } +} + +static void M045PW(uint16 A, uint16 V) { + uint32 mask = ~reg[3] & 0x3F; + uint32 base = ((reg[2] << 2) & 0x300) | reg[1]; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static DECLFR(M045ReadCart) { + /* Some multicarts select between five different menus by connecting one of the higher address lines to PRG /CE. + The menu code selects between menus by checking which of the higher address lines disables PRG-ROM when set. */ + if (((PRGsize[0] < 0x200000) && (dipsw == 1) && (reg[1] & 0x80)) || + ((PRGsize[0] < 0x200000) && (dipsw == 2) && (reg[2] & 0x40)) || + ((PRGsize[0] < 0x100000) && (dipsw == 3) && (reg[1] & 0x40)) || + ((PRGsize[0] < 0x100000) && (dipsw == 4) && (reg[2] & 0x20))) { + return CPU_OPENBUS; + } + return CartBR(A); +} + +static DECLFW(M045WriteReg) { + CartBW(A, V); + if (!(reg[3] & 0x40)) { + reg[cmd] = V; + cmd = (cmd + 1) & 0x03; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static DECLFR(M045ReadDIP) { + uint32 addr = 1 << (dipsw + 4); + if (A & (addr | (addr - 1))) { + return 0x01; + } + return 0x00; +} + +static void M045Reset(void) { + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + dipsw++; + dipsw &= 7; + MMC3_Reset(); +} + +static void M045Power(void) { + reg[0] = reg[1] = reg[3] = cmd = dipsw = 0; + reg[2] = 0x0F; + MMC3_Power(); + SetReadHandler(0x8000, 0xFFFF, M045ReadCart); + SetWriteHandler(0x6000, 0x7FFF, M045WriteReg); + SetReadHandler(0x5000, 0x5FFF, M045ReadDIP); +} + +void Mapper045_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + MMC3_cwrap = M045CW; + MMC3_pwrap = M045PW; + info->Reset = M045Reset; + info->Power = M045Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper046.c b/src/mappers/mapper046.c new file mode 100644 index 000000000..04d15ef6e --- /dev/null +++ b/src/mappers/mapper046.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, ((reg & 0x0F) << 1) | (latch.data & 0x01)); + setchr8(((reg & 0xF0) >> 1) | ((latch.data >> 4) & 0x07)); +} + +static DECLFW(M046WriteReg) { + reg = V; + Sync(); +} + +static void M046Power(void) { + reg = 0; + Latch_Power(); + SetWriteHandler(0x6000, 0x7FFF, M046WriteReg); +} + +static void M046Reset(void) { + reg = 0; + Sync(); +} + +void Mapper046_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Power = M046Power; + info->Reset = M046Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper047.c b/src/mappers/mapper047.c new file mode 100644 index 000000000..5f35075ab --- /dev/null +++ b/src/mappers/mapper047.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M047PW(uint16 A, uint16 V) { + setprg8(A, (reg << 4) | (V & 0x0F)); +} + +static void M047CW(uint16 A, uint16 V) { + setchr1(A, (reg << 7) | (V & 0x7F)); +} + +static DECLFW(M047Write) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M047Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M047Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M047Write); +} + +void Mapper047_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M047PW; + MMC3_cwrap = M047CW; + info->Power = M047Power; + info->Reset = M047Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper048.c b/src/mappers/mapper048.c new file mode 100644 index 000000000..3467c5121 --- /dev/null +++ b/src/mappers/mapper048.c @@ -0,0 +1,120 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 48 - Taito TC0690/TC190+PAL16R4 */ + +#include "mapinc.h" + +static uint8 prg[2], chr[6], mirr; +static uint8 IRQa; +static int16 IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = { + { prg, 2, "PREG" }, + { chr, 6, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg16(0xC000, ~0); + + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr1(0x1000, chr[2]); + setchr1(0x1400, chr[3]); + setchr1(0x1800, chr[4]); + setchr1(0x1C00, chr[5]); + + setmirror(((mirr >> 6) & 0x01) ^ 0x01); +} + +static DECLFW(M048Write) { + switch (A & 0xE003) { + case 0x8000: + case 0x8001: + prg[A & 0x01] = V; + Sync(); + break; + case 0x8002: + case 0x8003: + chr[A & 0x01] = V; + Sync(); + break; + case 0xA000: + case 0xA001: + case 0xA002: + case 0xA003: + chr[2 + (A & 0x03)] = V; + Sync(); + break; + case 0xC000: + IRQLatch = V; + break; + case 0xC001: + IRQCount = IRQLatch; + break; + case 0xC002: + IRQa = TRUE; + break; + case 0xC003: + IRQa = FALSE; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xE000: + mirr = V; + Sync(); + break; + } +} + +static void M048Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M048Write); +} + +static void IRQHook(void) { + if (IRQa) { + IRQCount++; + if (IRQCount == 0x100) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper048_Init(CartInfo *info) { + info->Power = M048Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + GameHBIRQHook = IRQHook; +} + diff --git a/src/mappers/mapper049.c b/src/mappers/mapper049.c new file mode 100644 index 000000000..d77f60ec2 --- /dev/null +++ b/src/mappers/mapper049.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 49 */ +/* BMC-STREETFIGTER-GAME4IN1 - Sic. $6000 set to $41 rather than $00 on power-up. */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M049PW(uint16 A, uint16 V) { + if (reg & 0x01) { + setprg8(A, ((reg >> 2) & ~0x0F) | (V & 0x0F)); + } else { + setprg32(0x8000, (reg >> 4) & 0x03); + } +} + +static void M049CW(uint16 A, uint16 V) { + setchr1(A, ((reg << 1) & 0x180) | (V & 0x7F)); +} + +static DECLFW(M049Write) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M049Reset(void) { + reg = ((iNESCart.submapper == 1) || (iNESCart.PRGCRC32 == 0x408EA235)) ? 0x41 : 0x00; /* Street Fighter II Game 4-in-1 */ + MMC3_Reset(); +} + +static void M049Power(void) { + reg = ((iNESCart.submapper == 1) || (iNESCart.PRGCRC32 == 0x408EA235)) ? 0x41 : 0x00; /* Street Fighter II Game 4-in-1 */ + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M049Write); +} + +void Mapper049_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M049CW; + MMC3_pwrap = M049PW; + info->Reset = M049Reset; + info->Power = M049Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper050.c b/src/mappers/mapper050.c new file mode 100644 index 000000000..68cbb6aa1 --- /dev/null +++ b/src/mappers/mapper050.c @@ -0,0 +1,90 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = { + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + uint8 prg = ((reg & 0x01) << 2) | ((reg & 0x02) >> 1) | ((reg & 0x04) >> 1) | (reg & 0x08); + + setprg8(0x6000, 15); + setprg8(0x8000, 8); + setprg8(0xA000, 9); + setprg8(0xC000, prg); + setprg8(0xE000, 11); + setchr8(0); +} + +static DECLFW(M050Write) { + switch (A & 0xD160) { + case 0x4120: + IRQa = V & 0x01; + if (!IRQa) { + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + break; + case 0x4020: + reg = V; + Sync(); + break; + } +} + +static void M050Power(void) { + reg = 0; + IRQa = IRQCount = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0x4FFF, M050Write); +} + +static void M050IRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount & 0x1000) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper050_Init(CartInfo *info) { + info->Power = M050Power; + MapIRQHook = M050IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper051.c b/src/mappers/mapper051.c new file mode 100644 index 000000000..550d5a28c --- /dev/null +++ b/src/mappers/mapper051.c @@ -0,0 +1,95 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg, mode; + +static SFORMAT StateRegs[] = { + { &prg, 1, "PREG" }, + { &mode, 1, "MODE" }, + { 0 } +}; + +static void Sync(void) { + if (iNESCart.submapper == 1) { + setprg8(0x6000, (prg << 1) | 0x23); + if (mode & 0x022) + setprg32(0x8000, prg >> 1); + else { + setprg16(0x8000, ((prg >> 2) & 0x10) | ((prg >> 1) & 0x08) | (prg & 0x07)); + setprg16(0xC000, ((prg >> 2) & 0x10) | ((prg >> 1) & 0x08) | 0x07); + } + } else { + if (mode & 0x02) { + setprg8(0x6000, ((prg << 2) & 0x1C) | 0x23); + setprg32(0x8000, prg); + } else { + setprg8(0x6000, ((prg << 2) & 0x10) | 0x2F); + setprg16(0x8000, (prg << 1) | (prg >> 4)); + setprg16(0xC000, (prg << 1) | 0x07); + } + } + setchr8(0); + setmirror(((mode >> 4) & 1) ^ 1); +} + +static DECLFW(M051WriteMode) { + mode = V; + Sync(); +} + +static DECLFW(M051WriteBank) { + prg = V; + Sync(); +} + +static void M051Power(void) { + prg = 0; + mode = 2; + Sync(); + SetWriteHandler(0x6000, 0x7FFF, M051WriteMode); + SetWriteHandler(0x8000, 0xFFFF, M051WriteBank); + SetReadHandler(0x6000, 0xFFFF, CartBR); +} + +static void M051Reset(void) { + prg = 0; + mode = 2; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper051_Init(CartInfo *info) { + info->Power = M051Power; + info->Reset = M051Reset; + AddExState(StateRegs, ~0, 0, NULL); + GameStateRestore = StateRestore; + + if ((CHR_ROM_SIZE_8K == 8192) && (info->CHRRamSize == 8192)) { + /* at least 1 variant has 8K CHR-ROM which should be treated as CHR-RAM */ + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 1); + AddExState(CHRptr[0], CHRsize[0], 0, "CHRR"); + } +} diff --git a/src/mappers/mapper052.c b/src/mappers/mapper052.c new file mode 100644 index 000000000..1612b0ee7 --- /dev/null +++ b/src/mappers/mapper052.c @@ -0,0 +1,110 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Submapper 13/14 - CHR-ROM + CHR-RAM */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M052PW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x08) ? 0x0F : 0x1F; + uint8 base = (reg << 4) & 0x70; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M052CW(uint16 A, uint16 V) { + uint16 mask = (reg & 0x40) ? 0x7F : 0xFF; + uint16 base = (((reg << 3) & 0x180) | ((reg << 7) & 0x200)); + uint8 chrram = CHRRAM && + (((iNESCart.submapper == 13) && ((reg & 0x03) == 0x03)) || + ((iNESCart.submapper == 14) && (reg & 0x20))); + + if (iNESCart.CRC32 == 0x68FE207F) { + /* Mario 7-in-1 (YH-705) with wrong bank order */ + base = ((reg & 0x20) << 4) | ((reg & 0x04) << 6) | + (reg & 0x40 ? (reg & 0x10) << 3 : 0x00); + } else if (iNESCart.submapper == 14) { + /* Well 8-in-1 (AB128) (Unl) (p1) */ + base = ((reg << 3) & 0x080) | ((reg << 7) & 0x300); + } + + setchr1r(chrram ? 0x10 : 0, A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M052Write) { + if (MMC3_WramIsWritable()) { + if (!(reg & 0x80)) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } else { + CartBW(A, V); + } + } +} + +static void M052Close(void) { + MMC3_Close(); +} + +static void M052Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M052Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M052Write); +} + +void Mapper052_Init(CartInfo *info) { + uint8 ws = info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) / 1024 : 8; + + MMC3_Init(info, ws, info->battery); + MMC3_cwrap = M052CW; + MMC3_pwrap = M052PW; + + info->Reset = M052Reset; + info->Power = M052Power; + info->Close = M052Close; + AddExState(®, 1, 0, "EXPR"); + + + if (info->CRC32 == 0xA874E216 && info->submapper != 13) { + info->submapper = 13; /* (YH-430) 97-98 Four-in-One */ + iNESCart.CHRRamSize = 8192; + } else if (info->CRC32 == 0xCCE8CA2F && info->submapper != 14) { + /* Well 8-in-1 (AB128) (Unl) (p1), with 1024 PRG and CHR is incompatible with submapper 13. + * This is reassigned to submapper 14 instead. */ + info->submapper = 14; + iNESCart.CHRRamSize = 8192; + } + + if (CHR_ROM_SIZE_8K && iNESCart.CHRRamSize) { + CHRRAMSIZE = info->CHRRamSize ? info->CHRRamSize : 8192; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + } +} diff --git a/src/mappers/mapper053.c b/src/mappers/mapper053.c new file mode 100644 index 000000000..56b36dbb2 --- /dev/null +++ b/src/mappers/mapper053.c @@ -0,0 +1,79 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 053 - BMC-Supervision16in1 */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, 0x04 + (((reg[0] & 0x0F) << 4) | 0x0F)); + if (reg[0] & 0x10) { + setprg16(0x8000, 0x02 + (((reg[0] & 0x0F) << 3) | (reg[1] & 0x07))); + setprg16(0xc000, 0x02 + (((reg[0] & 0x0F) << 3) | 0x07)); + } else { + setprg32(0x8000, 0); + } + setchr8(0); + setmirror(((reg[0] & 0x20) >> 5) ^ 0x01); +} + +static DECLFW(M053Write6) { + if (!(reg[0] & 0x10)) { + reg[0] = V; + Sync(); + } +} + +static DECLFW(M053Write8) { + reg[1] = V; + Sync(); +} + +static void M053Power(void) { + SetWriteHandler(0x6000, 0x7FFF, M053Write6); + SetWriteHandler(0x8000, 0xFFFF, M053Write8); + SetReadHandler(0x6000, 0xFFFF, CartBR); + reg[0] = reg[1] = 0; + Sync(); +} + +static void M053Reset(void) { + reg[0] = reg[1] = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper053_Init(CartInfo *info) { + info->Power = M053Power; + info->Reset = M053Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper055.c b/src/mappers/mapper055.c new file mode 100644 index 000000000..3b5c877f8 --- /dev/null +++ b/src/mappers/mapper055.c @@ -0,0 +1,52 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Mapper 55 - UNL-MARIO1-M0552 + * FDS Conversion + * + */ + +#include "mapinc.h" + +static void M055Power(void) { + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x6000, 0x67FF, CartBR); + SetReadHandler(0x7000, 0x77FF, CartBR); + SetWriteHandler(0x7000, 0x77FF, CartBW); + + setprg2(0x6000, 16); + setprg2r(0x10, 0x7000, 0); + setprg32(0x8000, 0); + setchr8(0); +} + +void Mapper055_Init(CartInfo *info) { + info->Power = M055Power; + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } else if (info->battery) { + WRAMSIZE = 2048; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } +} diff --git a/src/mappers/mapper056.c b/src/mappers/mapper056.c new file mode 100644 index 000000000..703a9823c --- /dev/null +++ b/src/mappers/mapper056.c @@ -0,0 +1,94 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * - Mapper 56 - UNL KS202 + * FDS Conversion: Super Mario Bros. 3 (Pirate, Alt) + * similar to M142 but use WRAM instead? $D000 additional IRQ trigger + * - fix IRQ counter, noticeable in status bars of both SMB2J(KS7032) and SMB3J(KS202) + */ + + #include "mapinc.h" + #include "ks202.h" + +static uint8 prg[4]; +static uint8 chr[8]; +static uint8 mirr; + +static SFORMAT M056StateRegs[] = { + { prg, 8, "PREG" }, + { chr, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + + setprg8(0x8000, (prg[0] & 0x10) | (ks202.reg[1] & 0x0F)); + setprg8(0xA000, (prg[1] & 0x10) | (ks202.reg[2] & 0x0F)); + setprg8(0xC000, (prg[2] & 0x10) | (ks202.reg[3] & 0x0F)); + setprg8(0xE000, (prg[3] & 0x10) | ( ~0 & 0x0F)); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + setmirror(mirr & 1); +} + +static DECLFW(M056Write) { + switch (A & 0xC00) { + case 0x000: prg[A & 0x03] = V; break; + case 0x800: mirr = V; break; + case 0xC00: chr[A & 0x07] = V; break; + } + ks202.reg[ks202.cmd & 0x07] = V; + Sync(); +} + +static void M056Reset(void) { + prg[0] = prg[1] = prg[2] = prg[3] = 0x10; + chr[0] = chr[1] = chr[2] = chr[3] = 0; + chr[4] = chr[5] = chr[6] = chr[7] = 0; + mirr = 0; + Sync(); +} + +static void M056Power(void) { + prg[0] = prg[1] = prg[2] = prg[3] = 0x10; + chr[0] = chr[1] = chr[2] = chr[3] = 0; + chr[4] = chr[5] = chr[6] = chr[7] = 0; + mirr = 0; + KS202_Power(); + SetWriteHandler(0xF000, 0xFFFF, M056Write); +} + +void Mapper056_Init(CartInfo *info) { + KS202_Init(info, Sync, 1, 0); + info->Power = M056Power; + info->Reset = M056Reset; + AddExState(&M056StateRegs, ~0, 0, 0); +} diff --git a/src/mappers/mapper057.c b/src/mappers/mapper057.c new file mode 100644 index 000000000..b4af8b52c --- /dev/null +++ b/src/mappers/mapper057.c @@ -0,0 +1,90 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" + +static uint8 reg[2]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 prg = (reg[1] >> 5) & 0x07; + uint8 chr = ((reg[0] >> 3) & 0x08) | (reg[1] & 0x07); + + if (reg[1] & 0x10) { + setprg32(0x8000, prg >> 1); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + if (reg[0] & 0x80) { + setchr8(chr); + } else { + setchr8((chr & ~0x03) | (reg[0] & 0x03)); + } + setmirror(((reg[1] >> 3) & 0x01) ^ 0x01); +} + +static DECLFR(M057Read) { + return dipsw & 0x03; +} + +static DECLFW(M057Write) { + if (A & 0x2000) { + reg[(A >> 11) & 0x01] = (reg[(A >> 11) & 0x01] & ~0x40) | (V & 0x40); + } else { + reg[(A >> 11) & 0x01] = V; + } + Sync(); +} + +static void M057Power(void) { + reg[1] = reg[0] = 0; /* Always reset to menu */ + dipsw = 1; /* YH-xxx "Olympic" multicarts disable the menu after one selection */ + SetReadHandler(0x5000, 0x6FFF, M057Read); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M057Write); + Sync(); +} + +static void M057Reset(void) { + reg[1] = reg[0] = 0; /* Always reset to menu */ + dipsw++; + FCEU_printf("Select Register = %02x\n", dipsw); + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper057_Init(CartInfo *info) { + info->Power = M057Power; + info->Reset = M057Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper058.c b/src/mappers/mapper058.c new file mode 100644 index 000000000..5bbf20b66 --- /dev/null +++ b/src/mappers/mapper058.c @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x40) { + setprg16(0x8000, latch.addr & 0x07); + setprg16(0xC000, latch.addr & 0x07); + } else { + setprg32(0x8000, (latch.addr >> 1) & 0x03); + } + setchr8((latch.addr >> 3) & 0x07); + setmirror(((latch.addr & 0x80) >> 7) ^ 0x01); +} + +void Mapper058_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper059.c b/src/mappers/mapper059.c new file mode 100644 index 000000000..be1140504 --- /dev/null +++ b/src/mappers/mapper059.c @@ -0,0 +1,73 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* iNES Mapper 59 - BMCD1038 */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static void Sync(void) { + if (latch.addr & 0x80) { + setprg16(0x8000, (latch.addr & 0x70) >> 4); + setprg16(0xC000, (latch.addr & 0x70) >> 4); + } else { + setprg32(0x8000, (latch.addr & 0x60) >> 5); + } + setchr8(latch.addr & 0x07); + setmirror(((latch.addr & 0x08) >> 3) ^ 0x01); +} + +static DECLFR(M059Read) { + if (latch.addr & 0x100) { + return (CPU_OPENBUS & ~0x03) | (dipsw & 0x03); + } + return CartBR(A); +} + +static DECLFW(M059Write) { + /* Only recognize the latch write if the lock bit has not been set. */ + /* Needed for NT-234 "Road Fighter" */ + if (!(latch.addr & 0x200)) { + Latch_Write(A, V); + } +} + +static void M059Reset(void) { + dipsw++; + /* Always reset to menu */ + latch.addr = 0; + Sync(); +} + +static void M059Power(void) { + Latch_Power(); + /* Trap latch writes to enforce the "Lock" bit */ + SetWriteHandler(0x8000, 0xFFFF, M059Write); +} + +void Mapper059_Init(CartInfo *info) { + Latch_Init(info, Sync, M059Read, FALSE, FALSE); + info->Reset = M059Reset; + info->Power = M059Power; + AddExState(&dipsw, 1, 0, "DIPSW"); +} diff --git a/src/mappers/mapper060.c b/src/mappers/mapper060.c new file mode 100644 index 000000000..12ea59722 --- /dev/null +++ b/src/mappers/mapper060.c @@ -0,0 +1,52 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mapinc.h" + +static uint8 game = 0; + +static void Sync(void) { + setchr8(game); + setprg16(0x8000, game); + setprg16(0xC000, game); +} + +static void M060Reset(void) { + game++; + Sync(); +} + +static void M060Power(void) { + game = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper060_Init(CartInfo *info) { + info->Power = M060Power; + info->Reset = M060Reset; + GameStateRestore = StateRestore; + AddExState(&game, 1, 0, "GAME"); +} diff --git a/src/mappers/mapper061.c b/src/mappers/mapper061.c new file mode 100644 index 000000000..e1b2994b0 --- /dev/null +++ b/src/mappers/mapper061.c @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x10) { + setprg16(0x8000, ((latch.addr & 0x0F) << 1) | ((latch.addr & 0x20) >> 5)); + setprg16(0xC000, ((latch.addr & 0x0F) << 1) | ((latch.addr & 0x20) >> 5)); + } else { + setprg32(0x8000, latch.addr & 0x0F); + } + setchr8(latch.addr >> 8 & 0x0F); + setmirror(((latch.addr >> 7) & 0x01) ^ 0x01); +} + +void Mapper061_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper062.c b/src/mappers/mapper062.c new file mode 100644 index 000000000..5e7e4d305 --- /dev/null +++ b/src/mappers/mapper062.c @@ -0,0 +1,41 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = (latch.addr & 0x40) | ((latch.addr >> 8) & 0x3F); + + if (latch.addr & 0x20) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { + setprg32(0x8000, prg >> 1); + } + setchr8(((latch.addr & 0x1F) << 2) | (latch.data & 0x03)); + setmirror(((latch.addr >> 7) & 1) ^ 1); +} + +void Mapper062_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper063.c b/src/mappers/mapper063.c new file mode 100644 index 000000000..8eb59154b --- /dev/null +++ b/src/mappers/mapper063.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Mapper 63 NTDEC-Multicart + * http://wiki.nesdev.com/w/index.php/INES_Mapper_063 + * - Powerful 250-in-1 + * - Hello Kitty 255-in-1 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg_mask = (iNESCart.submapper == 0) ? 0xFF : 0x7F; + uint8 prg_bank = (latch.addr >> 2) & prg_mask; + uint8 chr_protect = (latch.addr & ((iNESCart.submapper == 0) ? 0x400 : 0x200)) == 0; + + /* return openbus for unpopulated rom banks */ + SetReadHandler(0x8000, 0xFFFF, prg_bank >= PRG_BANK_COUNT(16) ? 0 : CartBROB); + + if (latch.addr & 2) { + setprg32(0x8000, prg_bank >> 1); + } else { + setprg16(0x8000, prg_bank); + setprg16(0xC000, prg_bank); + } + + setchr8(0); + setmirror((latch.addr & 1) ^ 1); + + /* chr-ram protect */ + SetupCartCHRMapping(0, CHRptr[0], 0x2000, chr_protect); +} + +void Mapper063_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper064.c b/src/mappers/mapper064.c new file mode 100644 index 000000000..fd05dc8c9 --- /dev/null +++ b/src/mappers/mapper064.c @@ -0,0 +1,183 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 64 - Tengen 800032 Rambo-1 + * Mapper 158 - Tengen 800037 (Alien Syndrome Unl) +*/ + +#include "mapinc.h" + +static uint8 cmd, mirr, reg[16]; +static uint8 IRQReload, IRQmode, IRQCount, IRQa, IRQLatch; +static uint8 IRQPrescaler; + +static SFORMAT StateRegs[] = { + { reg, 16, "REGS" }, + { &cmd, 1, "CMDR" }, + { &mirr, 1, "MIRR" }, + { &IRQReload, 1, "IRQR" }, + { &IRQmode, 1, "IRQM" }, + { &IRQCount, 1, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQPrescaler, 1, "IRQP" }, + { 0 } +}; + +static void Sync(void) { + /* + 0000: R0: Select 2 (K=0) or 1 (K=1) KiB CHR bank at PPU $0000 (or $1000) + 0001: R1: Select 2 (K=0) or 1 (K=1) KiB CHR bank at PPU $0800 (or $1800) + 0010: R2: Select 1 KiB CHR bank at PPU $1000-$13FF (or $0000-$03FF) + 0011: R3: Select 1 KiB CHR bank at PPU $1400-$17FF (or $0400-$07FF) + 0100: R4: Select 1 KiB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF) + 0101: R5: Select 1 KiB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF) + 0110: R6: Select 8 KiB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF) + 0111: R7: Select 8 KiB PRG ROM bank at $A000-$BFFF + 1000: R8: If K=1, Select 1 KiB CHR bank at PPU $0400 (or $1400) + 1001: R9: If K=1, Select 1 KiB CHR bank at PPU $0C00 (or $1C00) + 1111: RF: Select 8 KiB PRG ROM bank at $C000-$DFFF (or $8000-$9FFF) + */ + setprg8(0x8000, reg[6]); + setprg8(0xA000, reg[7]); + setprg8(0xC000, reg[15]); + setprg8(0xE000, ~0); + + if (cmd & 0x20) { + setchr1(0x0000, reg[0]); + setchr1(0x0400, reg[8]); + setchr1(0x0800, reg[1]); + setchr1(0x0C00, reg[9]); + } else { + setchr1(0x0000, (reg[0] & 0xFE)); + setchr1(0x0400, (reg[0] & 0xFE) | 1); + setchr1(0x0800, (reg[1] & 0xFE)); + setchr1(0x0C00, (reg[1] & 0xFE) | 1); + } + + setchr1(0x1000, reg[2]); + setchr1(0x1400, reg[3]); + setchr1(0x1800, reg[4]); + setchr1(0x1C00, reg[5]); + + if (iNESCart.mapper == 158) { + if (cmd & 0x20) { + setntamem(NTARAM + ((reg[0] >> 7) << 10), 1, 0); + setntamem(NTARAM + ((reg[8] >> 7) << 10), 1, 1); + setntamem(NTARAM + ((reg[1] >> 7) << 10), 1, 2); + setntamem(NTARAM + ((reg[9] >> 7) << 10), 1, 3); + } else { + setntamem(NTARAM + ((reg[0] >> 7) << 10), 1, 0); + setntamem(NTARAM + ((reg[0] >> 7) << 10), 1, 1); + setntamem(NTARAM + ((reg[1] >> 7) << 10), 1, 2); + setntamem(NTARAM + ((reg[1] >> 7) << 10), 1, 3); + } + } else { + setmirror((mirr & 1) ^ 1); + } +} + +static DECLFW(M064Write) { + switch (A & 0xF001) { + case 0xA000: + mirr = V; + Sync(); + break; + case 0x8000: + cmd = V; + break; + case 0x8001: + reg[cmd & 0x0F] = V; + Sync(); + break; + case 0xC000: + IRQLatch = V; + if (IRQReload) { + IRQCount = IRQLatch; + } + break; + case 0xC001: + IRQReload = TRUE; + IRQCount = IRQLatch; + IRQmode = V & 1; + break; + case 0xE000: + IRQa = FALSE; + X6502_IRQEnd(FCEU_IQEXT); + if (IRQReload) { + IRQCount = IRQLatch; + } + break; + case 0xE001: + IRQa = TRUE; + if (IRQReload) { + IRQCount = IRQLatch; + } + break; + } +} + +static void M064Power(void) { + cmd = mirr = 0; + reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = ~0; + reg[6] = reg[7] = reg[8] = reg[9] = reg[10] = ~0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M064Write); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M064CPUHook(int a) { + static int32 smallcount; + if (IRQmode) { + smallcount += a; + while (smallcount >= 4) { + smallcount -= 4; + IRQCount--; + if (IRQCount == 0xFF) + if (IRQa) X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M064HBHook(void) { + if ((!IRQmode) && (scanline != 240)) { + IRQReload = 0; + IRQCount--; + if (IRQCount == 0xFF) { + if (IRQa) { + IRQReload = 1; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +void Mapper064_Init(CartInfo *info) { + info->Power = M064Power; + GameHBIRQHook = M064HBHook; + MapIRQHook = M064CPUHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper065.c b/src/mappers/mapper065.c new file mode 100644 index 000000000..4ebf8f842 --- /dev/null +++ b/src/mappers/mapper065.c @@ -0,0 +1,153 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[2], chr[8], mirr, cmd; +static uint8 IRQa; +static int16 IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = { + { &cmd, 1, "CMD0" }, + { prg, 2, "PREG" }, + { chr, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + if (cmd & 0x80) { + setprg8(0x8000, ~1); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[0]); + setprg8(0xE000, ~0); + } else { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + } + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + switch (mirr >> 6) { + case 0: + setmirror(MI_V); + break; + case 2: + setmirror(MI_H); + break; + default: + setmirror(MI_0); + break; + } +} + +static DECLFW(M065Write) { + switch (A & 0xF000) { + case 0x8000: + case 0xA000: + prg[(A >> 13) & 0x01] = V; + Sync(); + break; + case 0x9000: + switch (A & 0x07) { + case 0: + cmd = V; + Sync(); + break; + case 1: + mirr = V; + Sync(); + break; + case 3: + IRQa = V & 0x80; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 4: + IRQCount = IRQLatch; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 5: + IRQLatch &= 0x00FF; + IRQLatch |= V << 8; + break; + case 6: + IRQLatch &= 0xFF00; + IRQLatch |= V; + break; + } + break; + case 0xB000: + chr[A & 0x07] = V; + Sync(); + break; + } +} + +static void M065Power(void) { + prg[0] = 0; + prg[1] = 1; + + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + chr[4] = 4; + chr[5] = 5; + chr[6] = 6; + chr[7] = 7; + + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, M065Write); +} + +static void M065IRQ(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper065_Init(CartInfo *info) { + info->Power = M065Power; + MapIRQHook = M065IRQ; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper066.c b/src/mappers/mapper066.c new file mode 100644 index 000000000..c40f30fed --- /dev/null +++ b/src/mappers/mapper066.c @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, (latch.data >> 4) & 0x07); + setchr8(latch.data & 0x0F); +} + +void Mapper066_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper067.c b/src/mappers/mapper067.c new file mode 100644 index 000000000..b852dcfcf --- /dev/null +++ b/src/mappers/mapper067.c @@ -0,0 +1,126 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg, chr[4], mirr; +static uint8 IRQa, toggle = 0; +static int16 IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = { + { &prg, 1, "PREG" }, + { &toggle, 1, "TOGL" }, + { chr, 4, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, prg); + setprg16(0xC000, ~0); + + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr2(0x1000, chr[2]); + setchr2(0x1800, chr[3]); + + switch (mirr & 0x03) { + case 0: + setmirror(MI_V); + break; + case 1: + setmirror(MI_H); + break; + case 2: + setmirror(MI_0); + break; + case 3: + setmirror(MI_1); + break; + } +} + +static DECLFW(M067Write) { + switch (A & 0xF800) { + case 0x8800: + case 0x9800: + case 0xA800: + case 0xB800: + chr[(A >> 12) & 0x03] = V; + Sync(); + break; + case 0xC000: + case 0xC800: + IRQCount &= 0xFF << (toggle << 3); + IRQCount |= V << ((toggle ^ 1) << 3); + toggle ^= 1; + break; + case 0xD800: + toggle = 0; + IRQa = V & 0x10; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xE800: + mirr = V; + Sync(); + break; + case 0xF800: + prg = V; + Sync(); + break; + } +} + +static void M067Power(void) { + prg = 0; + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + IRQa = IRQCount = IRQLatch = toggle = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M067Write); +} + +static void M067IRQ(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount < 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper067_Init(CartInfo *info) { + info->Power = M067Power; + MapIRQHook = M067IRQ; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper068.c b/src/mappers/mapper068.c new file mode 100644 index 000000000..a43bac57f --- /dev/null +++ b/src/mappers/mapper068.c @@ -0,0 +1,150 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +/* FIXME: needs updating, submapper 1 support etc */ + +static uint8 chr[4]; +static uint8 nt[2]; +static uint8 kogame, prg, mirr; +static uint32 count; + +static SFORMAT StateRegs[] = { + { &mirr, 1, "MIRR" }, + { &prg, 1, "PRG" }, + { &kogame, 1, "KGME" }, + { &count, 4, "CNT" }, + { chr, 4, "CHR" }, + { nt, 2, "NTAR" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg16r((PRGptr[1]) ? kogame : 0, 0x8000, prg); + setprg16(0xC000, 0x07); + + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr2(0x1000, chr[2]); + setchr2(0x1800, chr[3]); + + switch (mirr & 0x03) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } + + if (mirr & 0x10) { + int i; + PPUNTARAM = 0; + for (i = 0; i < 4; i++) { + switch (mirr & 0x03) { + case 0: vnapage[i] = CHRptr[0] + (((nt[i & 0x01] | 0x80) & CHRmask1[0]) << 10); break; + case 1: vnapage[i] = CHRptr[0] + (((nt[(i >> 0x01) & 0x01] | 0x80) & CHRmask1[0]) << 10); break; + case 2: vnapage[i] = CHRptr[0] + (((nt[0] | 0x80) & CHRmask1[0]) << 10); break; + case 3: vnapage[i] = CHRptr[0] + (((nt[1] | 0x80) & CHRmask1[0]) << 10); break; + } + } + } +} + +static DECLFR(M68Read) { + if (!(kogame & 0x08)) { + count++; + if (count == 1784) { + setprg16r(0, 0x8000, prg); + } + } + return CartBR(A); +} + +static DECLFW(M68WriteLo) { + if (!V) { + count = 0; + setprg16r((PRGptr[1]) ? kogame : 0, 0x8000, prg); + } + CartBW(A, V); +} + +static DECLFW(M068Write) { + switch (A & 0xF000) { + case 0x8000: + case 0x9000: + case 0xA000: + case 0xB000: + chr[(A >> 12) & 0x03] = V; + Sync(); + break; + case 0xC000: + case 0xD000: + nt[(A >> 12) & 0x01] = V; + Sync(); + break; + case 0xE000: + mirr = V; + Sync(); + break; + case 0xF000: + prg = V & 0x07; + kogame = ((V >> 3) & 0x01) ^ 0x01; + Sync(); + break; + } +} + +static void M68Power(void) { + prg = 0; + kogame = 0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xBFFF, M68Read); + SetReadHandler(0xC000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M068Write); + SetWriteHandler(0x6000, 0x6000, M68WriteLo); + SetWriteHandler(0x6001, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M68Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper068_Init(CartInfo *info) { + info->Power = M68Power; + info->Close = M68Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } +} diff --git a/src/mappers/mapper069.c b/src/mappers/mapper069.c new file mode 100644 index 000000000..07b86688d --- /dev/null +++ b/src/mappers/mapper069.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "s5bsound.h" +#include "fme7.h" + +static void M069PW(uint16 A, uint16 V) { + setprg8(A, V & 0x3F); +} + +static void M069CW(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +void Mapper069_Init(CartInfo *info) { + FME7_Init(info, TRUE, info->battery); + FME7_pwrap = M069PW; + FME7_cwrap = M069CW; +} diff --git a/src/mappers/mapper070.c b/src/mappers/mapper070.c new file mode 100644 index 000000000..d42a50ac4 --- /dev/null +++ b/src/mappers/mapper070.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.data >> 4); + setprg16(0xc000, ~0); + setchr8(latch.data & 0x0F); +} + +void Mapper070_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper071.c b/src/mappers/mapper071.c new file mode 100644 index 000000000..1527dd444 --- /dev/null +++ b/src/mappers/mapper071.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg, mirr; + +static SFORMAT StateRegs[] = { + { &prg, 1, "PREG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, prg); + setprg16(0xC000, ~0); + setchr8(0); + /* Fire Hawk or submapper 1, otherwise hard-mirroring */ + if (mirr) { + setmirror(mirr); + } +} + +static DECLFW(M071Write) { + switch (A & 0xF000) { + case 0x9000: + mirr = MI_0 + ((V >> 4) & 0x01); + Sync(); + break; + case 0xC000: + case 0xD000: + case 0xE000: + case 0xF000: + prg = V; + Sync(); + break; + } +} + +static void M071Power(void) { + prg = 0; + mirr = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x9000, 0xFFFF, M071Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper071_Init(CartInfo *info) { + info->Power = M071Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper072.c b/src/mappers/mapper072.c new file mode 100644 index 000000000..2ba80e790 --- /dev/null +++ b/src/mappers/mapper072.c @@ -0,0 +1,80 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Mapper 72: + * Moero!! Pro Tennis have ADPCM codec on-board, PROM isn't dumped, emulation isn't + * possible just now. + * + * Mapper 092 + * Another two-in-one mapper, two Jaleco carts uses similar + * hardware, but with different wiring. + * Original code provided by LULU + * Additionally, PCB contains DSP extra sound chip, used for voice samples (unemulated) + * This mapper is identical to mapper 072 except for the different PRG Setup. + */ + +#include "mapinc.h" + +static uint8 prg, chr, reg; + +static SFORMAT StateRegs[] = { + { &prg, 1, "PREG" }, + { &chr, 1, "CREG" }, + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (iNESCart.mapper == 92) { + setprg16(0x8000, 0); + setprg16(0xC000, prg); + setchr8(chr); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, ~0); + setchr8(chr); + } +} + +static DECLFW(M072Write) { + V &= CartBR(A); /* bus conflict */ + + reg = (reg ^ V) & V; + if (reg & 0x80) prg = V; + if (reg & 0x40) chr = V; + + Sync(); +} + +static void M072Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M072Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper072_Init(CartInfo *info) { + info->Power = M072Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper073.c b/src/mappers/mapper073.c new file mode 100644 index 000000000..7649d9f32 --- /dev/null +++ b/src/mappers/mapper073.c @@ -0,0 +1,131 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Konami VRC-3 + * + */ + +#include "mapinc.h" + +static uint8 prg; +static uint8 IRQx; /* autoenable */ +static uint8 IRQm; /* mode */ +static uint8 IRQa; +static uint16 IRQLatch, IRQCount; + +static SFORMAT StateRegs[] = { + { &prg, 1, "PREG" }, + { &IRQa, 1, "IRQA" }, + { &IRQx, 1, "IRQX" }, + { &IRQm, 1, "IRQM" }, + { &IRQLatch, 2, "IRQL" }, + { &IRQCount, 2, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, prg); + setprg16(0xC000, ~0); + setchr8(0); +} + +static DECLFW(M073Write) { + switch (A & 0xF000) { + case 0x8000: + IRQLatch &= 0xFFF0; + IRQLatch |= (V & 0x0F) << 0; + break; + case 0x9000: + IRQLatch &= 0xFF0F; + IRQLatch |= (V & 0x0F) << 4; + break; + case 0xA000: + IRQLatch &= 0xF0FF; + IRQLatch |= (V & 0x0F) << 8; + break; + case 0xB000: + IRQLatch &= 0x0FFF; + IRQLatch |= (V & 0x0F) << 12; + break; + case 0xC000: + IRQm = V & 0x04; + IRQx = V & 0x01; + IRQa = V & 0x02; + if (IRQa) { + IRQCount = IRQLatch; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xD000: + X6502_IRQEnd(FCEU_IQEXT); + IRQa = IRQx; + break; + case 0xF000: + prg = V; + Sync(); + break; + } +} + +static void M073IRQHook(int a) { + int32 i; + + if (IRQa) { + for (i = 0; i < a; i++) { + uint32 IRQCountMask = IRQm ? 0xFF : 0xFFFF; + if ((IRQCount & IRQCountMask) == IRQCountMask) { + IRQCount = IRQLatch; + X6502_IRQBegin(FCEU_IQEXT); + } else { + IRQCount++; + } + } + } +} + +static void M073Power(void) { + IRQLatch = IRQm = IRQx = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M073Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M073Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper073_Init(CartInfo *info) { + info->Power = M073Power; + info->Close = M073Close; + MapIRQHook = M073IRQHook; + AddExState(StateRegs, ~0, 0, NULL); + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper074.c b/src/mappers/mapper074.c new file mode 100644 index 000000000..afd48f469 --- /dev/null +++ b/src/mappers/mapper074.c @@ -0,0 +1,45 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M074CW(uint16 A, uint16 V) { + if ((V & ~0x01) == 0x08) { /* Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes, Ji Jia Zhan Shi (As).nes */ + setchr1r(0x10, A, V & 0x01); + } else { + setchr1(A, V); + } +} + +static void M074Close(void) { + MMC3_Close(); +} + +void Mapper074_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + info->Close = M074Close; + MMC3_cwrap = M074CW; + + CHRRAMSIZE = 2048; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper075.c b/src/mappers/mapper075.c new file mode 100644 index 000000000..64488e01b --- /dev/null +++ b/src/mappers/mapper075.c @@ -0,0 +1,91 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Konami VRC-1 + * + */ + +#include "mapinc.h" + +static uint8 prg[3], chr[2], mode; + +static SFORMAT StateRegs[] = { + { &mode, 1, "MODE" }, + { chr, 2, "CREG" }, + { prg, 3, "PREG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, ~0); + + setchr4(0x0000, (chr[0] & 0x0F) | ((mode & 2) << 3)); + setchr4(0x1000, (chr[1] & 0x0F) | ((mode & 4) << 2)); + + if (iNESCart.mirror != 2) { /* VS rom conversion uses 4-screen mirroring */ + setmirror((mode & 1) ^ 1); + } +} + +static DECLFW(M75Write) { + switch (A & 0xF000) { + case 0x8000: + case 0xA000: + case 0xC000: + prg[(A >> 13) & 0x03] = V; + Sync(); + break; + case 0x9000: + mode = V; + Sync(); + break; + case 0xE000: + case 0xF000: + chr[(A >> 12) & 0x01] = V; + Sync(); + break; + } +} + +static void M75Power(void) { + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M75Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper075_Init(CartInfo *info) { + info->Power = M75Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} + +void Mapper151_Init(CartInfo *info) { + Mapper075_Init(info); + /*info->mirror = 2; + setmirror(MI_4);*/ +} + diff --git a/src/mappers/mapper076.c b/src/mappers/mapper076.c new file mode 100644 index 000000000..9426f57fb --- /dev/null +++ b/src/mappers/mapper076.c @@ -0,0 +1,48 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 076 + * iNES Mapper 076 represents NAMCOT-3446, a board used onlyfor the game + * Megami Tensei: Digital Devil Story. + * It rewires the Namcot 108 mapper IC to be able to address 128 KiB of CHR, + * in exchange for coarser CHR banking. + * The PCB also has a 7432 which allows the use of a 28-pin CHR-ROM. + * https://www.nesdev.org/wiki/INES_Mapper_076 + */ + +#include "mapinc.h" +#include "n118.h" + +static void M076PW(uint16 A, uint16 V) { + setprg8(A, V & 0x1F); /* support for PRG bank for fan translations */ +} + +static void M076FixCHR(void) { + setchr2(0x0000, n118.reg[2] & 0x3F); + setchr2(0x0800, n118.reg[3] & 0x3F); + setchr2(0x1000, n118.reg[4] & 0x3F); + setchr2(0x1800, n118.reg[5] & 0x3F); +} + +void Mapper076_Init(CartInfo *info) { + N118_Init(info, 0, 0); + N118_pwrap = M076PW; + N118_FixCHR = M076FixCHR; +} diff --git a/src/mappers/mapper077.c b/src/mappers/mapper077.c new file mode 100644 index 000000000..1c2f4db73 --- /dev/null +++ b/src/mappers/mapper077.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.data & 0x0F); + setchr2(0x0000, latch.data >> 4); + setchr2r(0x10, 0x0800, 2); + setchr4r(0x10, 0x1000, 0); +} + +static void M077Close(void) { + Latch_Close(); +} + +void Mapper077_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Close = M077Close; + + CHRRAMSIZE = 6 * 1024; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); +} diff --git a/src/mappers/mapper078.c b/src/mappers/mapper078.c new file mode 100644 index 000000000..55c63393c --- /dev/null +++ b/src/mappers/mapper078.c @@ -0,0 +1,43 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Map 78 */ +/* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */ +/* Submapper 1 - Uchuusen - Cosmo Carrier ( one-screen mirroring ) */ +/* Submapper 3 - Holy Diver ( horizontal/vertical mirroring ) */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.data & 0x07); + setprg16(0xc000, ~0); + setchr8(latch.data >> 4); + if (iNESCart.submapper == 3) { + setmirror((latch.data >> 3) & 0x01); + } else { + setmirror(MI_0 + ((latch.data >> 3) & 0x01)); + } +} + +void Mapper078_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper079.c b/src/mappers/mapper079.c new file mode 100644 index 000000000..7d1f12595 --- /dev/null +++ b/src/mappers/mapper079.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg >> 3) & 0x01); + setchr8(reg & 0x07); +} + +static DECLFW(M79Write) { + if (A & 0x100) { + reg = V; + Sync(); + } +} + +static void M079Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, M79Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper079_Init(CartInfo *info) { + info->Power = M079Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper080.c b/src/mappers/mapper080.c new file mode 100644 index 000000000..8928dd6f9 --- /dev/null +++ b/src/mappers/mapper080.c @@ -0,0 +1,125 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[3], chr[6], mirr; +static uint8 wram[256]; + +static SFORMAT StateRegs[] = { + { prg, 3, "PREG" }, + { chr, 6, "CREG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, ~0); + + setchr2(0x0000, chr[0] >> 1); + setchr2(0x0800, chr[1] >> 1); + setchr1(0x1000, chr[2]); + setchr1(0x1400, chr[3]); + setchr1(0x1800, chr[4]); + setchr1(0x1C00, chr[5]); + + if (iNESCart.mapper == 207) { + setmirrorw(chr[0] >>7, chr[0] >>7, chr[1] >>7, chr[1] >>7); + } else { + setmirror(mirr & 0x01); + } +} + +static DECLFW(M080RamWrite) { + wram[A & 0xFF] = V; +} + +static DECLFR(M080RamRead) { + return wram[A & 0xFF]; +} + +static DECLFW(M080Write) { + switch (A) { + case 0x7EF0: + case 0x7EF1: + case 0x7EF2: + case 0x7EF3: + case 0x7EF4: + case 0x7EF5: + chr[A & 0x07] = V; + Sync(); + break; + case 0x7EF6: + mirr = V; + Sync(); + break; + case 0x7EF8: + break; + case 0x7EFA: + case 0x7EFB: + case 0x7EFC: + case 0x7EFD: + case 0x7EFE: + case 0x7EFF: + prg[(A - 0x7EFA) >> 1] = V; + Sync(); + break; + } +} + +static void M080Power(void) { + Sync(); + SetReadHandler(0x7F00, 0x7FFF, M080RamRead); + SetWriteHandler(0x7F00, 0x7FFF, M080RamWrite); + SetWriteHandler(0x7EF0, 0x7EFF, M080Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void M207Power(void) { + Sync(); + SetWriteHandler(0x7EF0, 0x7EFF, M080Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper080_Init(CartInfo *info) { + info->Power = M080Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + if (info->battery) { + info->SaveGame[0] = wram; + info->SaveGameLen[0] = 256; + AddExState(wram, sizeof(wram), 0, "WRAM"); + } +} + +void Mapper207_Init(CartInfo *info) { + info->Power = M207Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper081.c b/src/mappers/mapper081.c new file mode 100644 index 000000000..405bd1e46 --- /dev/null +++ b/src/mappers/mapper081.c @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, (latch.addr >> 2) & 3); + setprg16(0xC000, ~0); + setchr8(latch.data & 3); +} + +void Mapper081_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper082.c b/src/mappers/mapper082.c new file mode 100644 index 000000000..7536083b4 --- /dev/null +++ b/src/mappers/mapper082.c @@ -0,0 +1,145 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Taito X1-017 board, battery backed + * NES 2.0 Mapper 552 represents the actual way the mask ROM is connected and is thus + * the correct bank order, while iNES Mapper 082 represents the bank order as it was + * understood before January 2020 when the mapper was reverse-engineered. + */ + +#include "mapinc.h" + +static uint8 chr[6], prg[3], protect[3], ctrl; + +static SFORMAT StateRegs[] = { + { prg, 3, "PREGS" }, + { chr, 6, "CREGS" }, + { protect, 3, "PROT" }, + { &ctrl, 1, "CTRL" }, + + { 0 } +}; + +static uint32 GetPRGBank(uint8 V) { + if (iNESCart.mapper == 552) { + return (((V << 5) & 0x20) | + ((V << 3) & 0x10) | + ((V << 1) & 0x08) | + ((V >> 1) & 0x04) | + ((V >> 3) & 0x02) | + ((V >> 5) & 0x01)); + } + return V >> 2; +} + +static void Sync(void) { + uint32 swap = ((ctrl & 2) << 11); + + setprg8r(0x10, 0x6000, 0); + + setprg8(0x8000, GetPRGBank(prg[0])); + setprg8(0xA000, GetPRGBank(prg[1])); + setprg8(0xC000, GetPRGBank(prg[2])); + setprg8(0xE000, ~0); + + setchr2(0x0000 ^ swap, chr[0] >> 1); + setchr2(0x0800 ^ swap, chr[1] >> 1); + setchr1(0x1000 ^ swap, chr[2]); + setchr1(0x1400 ^ swap, chr[3]); + setchr1(0x1800 ^ swap, chr[4]); + setchr1(0x1C00 ^ swap, chr[5]); + + setmirror(ctrl & 0x01); +} + +static DECLFR(ReadWRAM) { + if (((A >= 0x6000) && (A <= 0x67FF) && (protect[0] == 0xCA)) || + ((A >= 0x6800) && (A <= 0x6FFF) && (protect[1] == 0x69)) || + ((A >= 0x7000) && (A <= 0x73FF) && (protect[2] == 0x84))) { + return CartBR(A); + } + return CPU_OPENBUS; +} + +static DECLFW(WriteWRAM) { + if (((A >= 0x6000) && (A <= 0x67FF) && (protect[0] == 0xCA)) || + ((A >= 0x6800) && (A <= 0x6FFF) && (protect[1] == 0x69)) || + ((A >= 0x7000) && (A <= 0x73FF) && (protect[2] == 0x84))) { + CartBW(A, V); + } +} + +static DECLFW(M082Write) { + switch (A & 0x0F) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: chr[A & 7] = V; break; + case 0x06: ctrl = V & 3; break; + case 0x07: protect[0] = V; break; + case 0x08: protect[1] = V; break; + case 0x09: protect[2] = V; break; + case 0x0A: prg[0] = V; break; + case 0x0B: prg[1] = V; break; + case 0x0C: prg[2] = V; break; + default: + /* IRQ emulation ignored since no commercial games uses it */ + return; + } + Sync(); +} + +static void M082Power(void) { + Sync(); + SetReadHandler(0x6000, 0xffff, CartBR); + SetReadHandler(0x6000, 0x73ff, ReadWRAM); + SetWriteHandler(0x6000, 0x73ff, WriteWRAM); + SetWriteHandler(0x7ef0, 0x7eff, M082Write); /* external WRAM might end at $73FF */ + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M082Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper082_Init(CartInfo *info) { + info->Power = M082Power; + info->Close = M082Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } +} + +void Mapper552_Init(CartInfo *info) { + Mapper082_Init(info); +} diff --git a/src/mappers/mapper083.c b/src/mappers/mapper083.c new file mode 100644 index 000000000..bf833d4b2 --- /dev/null +++ b/src/mappers/mapper083.c @@ -0,0 +1,268 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * YOKO mapper, almost the same as 83, TODO: figure out difference + * Mapper 83 - 30-in-1 mapper, two modes for single game carts, one mode for + * multigame Dragon Ball Z Party + * + * Mortal Kombat 2 YOKO + * N-CXX(M), XX - PRG+CHR, 12 - 128+256, 22 - 256+256, 14 - 128+512 + * + */ + +/* + * iNES Mapper 083 also knows as Yoko + * 256 KiB CHR-ROM => Submapper 0 (1 KiB CHR-ROM banking, no WRAM) + * - Street Fighter II Pro/Street Blaster II Pro + * - Street Fighter IV Pro 10/Street Blaster IV Pro 10 + * - Street Blaster V Turbo 20 + * - Street Fighter X Turbo 40 + * - Fatal Fury 2/餓狼伝説 2 + * - Fatal Fury 2'/餓狼伝説 2' + * 512 KiB CHR-ROM => Submapper 1 (2 KiB CHR-ROM banking, no WRAM) + * - Super Blaster VII Turbo 28 + * - World Heroes 2/快打英雄榜 2 + * - World Heroes 2 Pro//快打英雄榜 2 Pro + * 1024 KiB CHR-ROM => Submapper 2 (1 KiB CHR-ROM banking with outer bank, 32 KiB banked WRAM) + * - Dragon Ball Party + * + * NES 2.0 264 - UNL-Yoko + * - Mortal Kombat II/V Pro + * - Master Fighter VI' +*/ + +#include "mapinc.h" + +static uint8 prg[4], chr[8], low[4]; +static uint8 mode, bank, dip; +static uint8 IRQa; +static int32 IRQCount; + +static uint8 prgMask; +static uint8 chrMode; +static uint16 dipMask; + +static SFORMAT StateRegs[] = +{ + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { &mode, 1, "MODE" }, + { &bank, 1, "BANK" }, + { &IRQCount, 4, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { low, 4, "LOWR" }, + { 0 } +}; + +static void M083Sync(void) { + uint8 prgMode = (mode >> 3) & 0x03; + uint8 mirr = mode & 0x03; + + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, (bank >> 6)); + } else if (mode & 0x20) { + setprg8(0x6000, prg[3]); + } + switch (prgMode) { + case 0: + setprg16(0x8000, bank); + setprg16(0xC000, bank | (prgMask >> 1)); + break; + case 1: + setprg32(0x8000, bank >> 1); + break; + case 2: + case 3: + setprg8(0x8000, ((bank << 1) & ~prgMask) | (prg[0] & prgMask)); + setprg8(0xA000, ((bank << 1) & ~prgMask) | (prg[1] & prgMask)); + setprg8(0xC000, ((bank << 1) & ~prgMask) | (prg[2] & prgMask)); + setprg8(0xE000, ((bank << 1) & ~prgMask) | (~0 & prgMask)); + break; + } + switch (chrMode) { + case 0: + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + break; + case 1: + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr2(0x1000, chr[6]); + setchr2(0x1800, chr[7]); + break; + case 2: + setchr1(0x0000, ((bank << 4) & 0x300) | chr[0]); + setchr1(0x0400, ((bank << 4) & 0x300) | chr[1]); + setchr1(0x0800, ((bank << 4) & 0x300) | chr[2]); + setchr1(0x0C00, ((bank << 4) & 0x300) | chr[3]); + setchr1(0x1000, ((bank << 4) & 0x300) | chr[4]); + setchr1(0x1400, ((bank << 4) & 0x300) | chr[5]); + setchr1(0x1800, ((bank << 4) & 0x300) | chr[6]); + setchr1(0x1C00, ((bank << 4) & 0x300) | chr[7]); + break; + } + switch (mirr) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +static DECLFW(M083Write) { + if (iNESCart.mapper == 264) { + A = ((A >> 2) & 0x3C0) | (A & 0x3F); + } + switch (A & 0x300) { + case 0x000: + bank = V; + break; + case 0x100: + mode = V; + break; + case 0x200: + if (A & 0x01) { + IRQa = mode & 0x80; + IRQCount &= 0xFF; + IRQCount |= V << 8; + } else { + IRQCount &= 0xFF00; + IRQCount |= V; + X6502_IRQEnd(FCEU_IQEXT); + } + break; + case 0x300: + A &= 0x1F; + if (A < 0x10) { + prg[A & 0x03] = V; + } else if (A < 0x18) { + chr[A & 0x07] = V; + } + break; + } + M083Sync(); +} + +static DECLFR(M083ReadLow) { + if (A & dipMask) { + return low[A & 3]; + } + return dip; +} + +static DECLFW(M083WriteLow) { + low[A & 3] = V; +} + +static void M083Power(void) { + mode = 0x10; + bank = 0; + dip = (iNESCart.mapper == 264) ? 0x01 : 0x00; + M083Sync(); + SetReadHandler(0x5000, 0x5FFF, M083ReadLow); + SetWriteHandler(0x5000, 0x5FFF, M083WriteLow); + SetReadHandler(0x6000, 0x7fff, CartBR); + SetReadHandler(0x8000, 0xffff, CartBR); + SetWriteHandler(0x8000, 0xffff, M083Write); + if (WRAMSIZE) { + SetWriteHandler(0x6000, 0x7fff, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + + } +} + +static void M083Reset(void) { + dip++; + if (iNESCart.mapper == 264) { + dip &= 3; + } else { + dip &= 1; + } + mode = bank = 0; + M083Sync(); +} + +static void M083Close(void) { +} + +static void M083IRQHook(int a) { + if (IRQa && (IRQCount > 0)) { + if (mode & 0x40) { + IRQCount -= a; + } else { + IRQCount += a; + } + if (IRQCount <= 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + } + } +} + +static void M083StateRestore(int version) { + M083Sync(); +} + +void Mapper083_Init(CartInfo *info) { + info->Power = M083Power; + info->Reset = M083Reset; + info->Close = M083Close; + MapIRQHook = M083IRQHook; + GameStateRestore = M083StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + if (!info->iNES2) { + if (CHR_ROM_SIZE_8K >= (1024 * 1024)) { + info->submapper = 2; + } else if (CHR_ROM_SIZE_8K >= (512 * 1024)) { + info->submapper = 1; + } + } + + chrMode = info->submapper; + prgMask = 0x1F; + dipMask = 0x100; + + WRAMSIZE = (info->submapper == 2) ? 32768 : 0; + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } +} + +void Mapper264_Init(CartInfo *info) { + info->Power = M083Power; + info->Reset = M083Reset; + info->Close = M083Close; + MapIRQHook = M083IRQHook; + GameStateRestore = M083StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + chrMode = 1; + prgMask = 0x0F; + dipMask = 0x400; +} diff --git a/src/mappers/mapper085.c b/src/mappers/mapper085.c new file mode 100644 index 000000000..37b2888fb --- /dev/null +++ b/src/mappers/mapper085.c @@ -0,0 +1,42 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "vrc7.h" + +static void M085PW(uint16 A, uint16 V) { + setprg8(A, V & 0x3F); +} + +static void M085CW(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +void Mapper085_Init(CartInfo *info) { + switch (info->submapper) { + case 0x01: VRC7_Init(info, 0x08, 0x20); break; + case 0x02: VRC7_Init(info, 0x10, 0x20); break; + default: VRC7_Init(info, 0x18, 0x20); break; + } + VRC7_pwrap = M085PW; + VRC7_cwrap = M085CW; +} diff --git a/src/mappers/mapper086.c b/src/mappers/mapper086.c new file mode 100644 index 000000000..ca40f199c --- /dev/null +++ b/src/mappers/mapper086.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* TODO: ADPCM not emulated */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg >> 4) & 0x03); + setchr8(((reg >> 4) & 0x04) | (reg & 0x03)); +} + +static DECLFW(M086Write) { + reg = V; + Sync(); +} + +static void M086Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x6FFF, M086Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper086_Init(CartInfo *info) { + info->Power = M086Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper087.c b/src/mappers/mapper087.c new file mode 100644 index 000000000..8344b2a3f --- /dev/null +++ b/src/mappers/mapper087.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8(((reg << 1) & 0x02) | ((reg >> 1) & 0x01)); +} + +static DECLFW(M087Write) { + reg = V; + Sync(); +} + +static void M087Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M087Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper087_Init(CartInfo *info) { + info->Power = M087Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper088.c b/src/mappers/mapper088.c new file mode 100644 index 000000000..bf7778bcc --- /dev/null +++ b/src/mappers/mapper088.c @@ -0,0 +1,36 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "n118.h" + +static void M088FixCHR(void) { + setchr2(0x0000, (n118.reg[0] & 0x3F) >> 1); + setchr2(0x0800, (n118.reg[1] & 0x3F) >> 1); + setchr1(0x1000, 0x40 | (n118.reg[2] & 0x3F)); + setchr1(0x1400, 0x40 | (n118.reg[3] & 0x3F)); + setchr1(0x1800, 0x40 | (n118.reg[4] & 0x3F)); + setchr1(0x1C00, 0x40 | (n118.reg[5] & 0x3F)); +} + +void Mapper088_Init(CartInfo *info) { + N118_Init(info, 0, 0); + N118_FixCHR = M088FixCHR; +} diff --git a/src/mappers/mapper089.c b/src/mappers/mapper089.c new file mode 100644 index 000000000..8013a021f --- /dev/null +++ b/src/mappers/mapper089.c @@ -0,0 +1,34 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, (latch.data >> 4) & 0x07); + setprg16(0xC000, ~0); + setchr8((latch.data & 0x07) | ((latch.data >> 4) & 0x08)); + setmirror(MI_0 + ((latch.data >> 3) & 0x01)); +} + +void Mapper089_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper091.c b/src/mappers/mapper091.c new file mode 100644 index 000000000..228057b90 --- /dev/null +++ b/src/mappers/mapper091.c @@ -0,0 +1,162 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2020-2-15 + * Street Fighter 3, Mortal Kombat II, Dragon Ball Z 2, Mario & Sonic 2 (JY-016) + * 1995 Super HIK 4-in-1 (JY-016), 1995 Super HiK 4-in-1 (JY-017) + * submapper 1 - Super Fighter III + * NOTE: nesdev's notes for IRQ is different that whats implemented here + */ + +#include "mapinc.h" + +static uint8 chr[4], prg[2]; +static uint8 outerbank; +static uint8 mirr; + +static uint8 IRQa; +static uint8 IRQPrescaler; +static uint8 IRQCount; +static int16 IRQCount16; + +static SFORMAT StateRegs[] = { + { chr, 4, "CREG" }, + { prg, 2, "PREG" }, + { &IRQa, 1, "IRQA" }, + { &IRQPrescaler, 1, "IRQP" }, + { &IRQCount, 1, "IRQC" }, + { &IRQCount16, 4, "IRQ2" }, + { &outerbank, 1, "OUTB" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + /* FCEU_printf("P0:%02x P1:%02x outerbank:%02x\n", prg[0], prg[1], outerbank);*/ + setprg8(0x8000, ((outerbank << 3) & ~0x0F) | prg[0]); + setprg8(0xa000, ((outerbank << 3) & ~0x0F) | prg[1]); + setprg8(0xc000, ((outerbank << 3) & ~0x0F) | 0x0E); + setprg8(0xe000, ((outerbank << 3) & ~0x0F) | 0x0F); + + setchr2(0x0000, ((outerbank << 8) & 0x100) | chr[0]); + setchr2(0x0800, ((outerbank << 8) & 0x100) | chr[1]); + setchr2(0x1000, ((outerbank << 8) & 0x100) | chr[2]); + setchr2(0x1800, ((outerbank << 8) & 0x100) | chr[3]); + + if (iNESCart.submapper != 0) { + setmirror((mirr & 0x01) ^ 0x01); + } +} + +static DECLFW(M091CHRWrite) { + if (iNESCart.submapper == 1) { + switch (A & 0x07) { + case 0: + case 1: + case 2: + case 3: + chr[A & 0x03] = V; + Sync(); + break; + case 4: + case 5: + mirr = V; + Sync(); + break; + case 6: + IRQCount16 = (IRQCount16 & 0xFF00) | V; + break; + case 7: + IRQCount16 = (IRQCount16 & 0x00FF) | (V << 8); + break; + } + } else { + chr[A & 0x03] = V; + Sync(); + } +} + +static DECLFW(M091IRQWrite) { + switch (A & 0x03) { + case 0: + case 1: + prg[A & 0x01] = V; + Sync(); + break; + case 2: + IRQa = IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 3: + IRQa = 1; + IRQPrescaler = 3; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +static DECLFW(M091OuterBankWrite) { + outerbank = A & 0xFF; + Sync(); +} + +static void M091Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x6FFF, M091CHRWrite); + SetWriteHandler(0x7000, 0x7FFF, M091IRQWrite); + SetWriteHandler(0x8000, 0x9FFF, M091OuterBankWrite); +} + +static void M091HBHook(void) { + if ((IRQCount < 8) && IRQa) { + IRQCount++; + if (IRQCount >= 8) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M091IRQHook(int a) { + IRQPrescaler += a; + if (IRQPrescaler >= 4) { + IRQPrescaler -= 4; + IRQCount16 -= 5; + if ((IRQCount16 <= 0) && IRQa) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper091_Init(CartInfo *info) { + info->Power = M091Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + if (info->submapper == 1) { + MapIRQHook = M091IRQHook; + } else { + GameHBIRQHook = M091HBHook; + } +} diff --git a/src/mappers/mapper093.c b/src/mappers/mapper093.c new file mode 100644 index 000000000..e241352f8 --- /dev/null +++ b/src/mappers/mapper093.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.data >> 4); + setprg16(0xc000, ~0); + setchr8(0); +} + +void Mapper093_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper094.c b/src/mappers/mapper094.c new file mode 100644 index 000000000..132ce5602 --- /dev/null +++ b/src/mappers/mapper094.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.data >> 2); + setprg16(0xc000, ~0); + setchr8(0); +} + +void Mapper094_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper095.c b/src/mappers/mapper095.c new file mode 100644 index 000000000..cbbd87a4f --- /dev/null +++ b/src/mappers/mapper095.c @@ -0,0 +1,121 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* +Mapper 95 represents NAMCOT-3425, a board used only for the game Dragon Buster (J). + +It is to the ordinary Namco 108 family boards (mapper 206) as TKSROM and TLSROM +(mapper 118) is to ordinary MMC3 boards. Instead of having hardwired mirroring +like mapper 206, it has CHR A15 directly controlling CIRAM A10, just as CHR A17 +controls CIRAM A10 on TxSROM. Only horizontal mirroring and 1-screen mirroring +are possible because the Namco 108 lacks the C bit of MMC3. +*/ + +#include "mapinc.h" +#include "n118.h" + +static uint8 mcache[8]; +static uint32 lastppu; + +static SFORMAT StateRegs[] = { + { mcache, 8, "MCCH" }, + { &lastppu, 4, "LPPU" }, + { 0 } +}; + +static void M095FixCHR(void) { + setchr2(0x0000, n118.reg[0] >> 1); + setchr2(0x0800, n118.reg[1] >> 1); + setchr1(0x1000, n118.reg[2]); + setchr1(0x1400, n118.reg[3]); + setchr1(0x1800, n118.reg[4]); + setchr1(0x1C00, n118.reg[5]); + setmirror(MI_0 + mcache[lastppu]); +} + +static DECLFW(M095Write) { + switch (A & 0xE001) { + case 0x8001: + n118.reg[n118.cmd & 0x07] = V & 0x1F; + switch (n118.cmd & 0x07) { + case 0: + mcache[0] = mcache[1] = (V >> 5) & 0x01; + N118_FixCHR(); + break; + case 1: + mcache[2] = mcache[3] = (V >> 5) & 0x01; + N118_FixCHR(); + break; + case 2: + mcache[4] = (V >> 5) & 0x01; + N118_FixCHR(); + break; + case 3: + mcache[5] = (V >> 5) & 0x01; + N118_FixCHR(); + break; + case 4: + mcache[6] = (V >> 5) & 0x01; + N118_FixCHR(); + break; + case 5: + mcache[7] = (V >> 5) & 0x01; + N118_FixCHR(); + break; + case 6: + case 7: + N118_FixPRG(); + break; + } + break; + default: + N118_Write(A, V); + break; + } +} + +static void MExMirrPPU(uint32 A) { + static int8 lastmirr = -1, curmirr; + if (A < 0x2000) { + lastppu = A >> 10; + curmirr = mcache[lastppu]; + if (curmirr != lastmirr) { + setmirror(MI_0 + curmirr); + lastmirr = curmirr; + } + } +} + +static void M095Power(void) { + lastppu = 0; + memset(mcache, 0, sizeof(mcache)); + + N118_Power(); + SetWriteHandler(0x8000, 0x9FFF, M095Write); +} + +void Mapper095_Init(CartInfo *info) { + N118_Init(info, 0, 0); + info->Power = M095Power; + N118_FixCHR = M095FixCHR; + PPU_hook = MExMirrPPU; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper096.c b/src/mappers/mapper096.c new file mode 100644 index 000000000..059eccec7 --- /dev/null +++ b/src/mappers/mapper096.c @@ -0,0 +1,71 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 1998 BERO + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Oeka-kids board + * + * I might want to add some code to the mapper 96 PPU hook function + * to not change CHR banks if the attribute table is being accessed, + * if I make emulation a little more accurate in the future. + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 ppulatch; +static uint16 lastAddr; + +static SFORMAT StateRegs[] = +{ + { &ppulatch, 1, "PPUL" }, + { &lastAddr, 2, "LADR" }, + { 0 } +}; + +static void Sync(void) { + setmirror(MI_0); + setprg32(0x8000, latch.data & 3); + setchr4(0x0000, (latch.data & 4) | ppulatch); + setchr4(0x1000, (latch.data & 4) | 3); +} + +static void M096PPUHook(uint32 A) { + uint16 addr = A & 0x3000; + if ((lastAddr != 0x2000) && ((A & 0x3000) == 0x2000)) { + ppulatch = (A >> 8) & 3; + Sync(); + } + lastAddr = addr; +} + +static void M096Power(void) { + ppulatch = 0; + lastAddr = 0; + Latch_Power(); +} + +void Mapper096_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Power = M096Power; + PPU_hook = M096PPUHook; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper097.c b/src/mappers/mapper097.c new file mode 100644 index 000000000..52369e163 --- /dev/null +++ b/src/mappers/mapper097.c @@ -0,0 +1,34 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, ~0); + setprg16(0xC000, latch.data); + setchr8(0); + setmirror((latch.data >> 7) & 0x01); +} + +void Mapper097_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper099.c b/src/mappers/mapper099.c new file mode 100644 index 000000000..20630c2bb --- /dev/null +++ b/src/mappers/mapper099.c @@ -0,0 +1,73 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 latch; +static writefunc old4016; + +static SFORMAT StateRegs[] = { + { &latch, 1, "LATC" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, 0); + setprg8(0x8000, latch & 4); /* Special for VS Gumshoe */ + setchr8((latch >> 2) & 1); +} + +static DECLFW(M099Write) { + latch = V; + Sync(); + old4016(A, V); +} + +static void M099Power(void) { + latch = 0; + Sync(); + old4016 = GetWriteHandler(0x4016); + SetWriteHandler(0x4016, 0x4016, M099Write); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M099Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper099_Init(CartInfo *info) { + info->Power = M099Power; + info->Close = M099Close; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper100.c b/src/mappers/mapper100.c new file mode 100644 index 000000000..9faf64428 --- /dev/null +++ b/src/mappers/mapper100.c @@ -0,0 +1,167 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 cmd; +static uint8 prg[4]; +static uint8 chr[8]; + +static SFORMAT StateRegs[] = { + { &cmd, 1, "CMD0" }, + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { 0 } +}; + +static void M100PRG(void) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, prg[3]); +} + +static void M100CHR(void) { + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); +} + +static DECLFW(M100WriteCMD) { + switch (A & 0xE001) { + case 0x8000: + cmd = V; + break; + case 0x8001: + switch (cmd) { + case 0x00: + chr[0] = V & 0xFE; + chr[1] = V | 0x01; + break; + case 0x01: + chr[2] = V & 0xFE; + chr[3] = V | 0x01; + break; + case 0x02: + chr[4] = V; + break; + case 0x03: + chr[5] = V; + break; + case 0x04: + chr[6] = V; + break; + case 0x05: + chr[7] = V; + break; + case 0x06: + prg[0] = V; + break; + case 0x07: + prg[1] = V; + break; + case 0x46: + prg[2] = V; + break; + case 0x47: + prg[1] = V; + break; + case 0x80: + chr[4] = V & 0xFE; + chr[5] = V | 0x01; + break; + case 0x81: + chr[6] = V & 0xFE; + chr[7] = V | 0x01; + break; + case 0x82: + chr[0] = V; + break; + case 0x83: + chr[1] = V; + break; + case 0x84: + chr[2] = V; + break; + case 0x85: + chr[3] = V; + break; + } + MMC3_FixPRG(); + MMC3_FixCHR(); + break; + } +} + +static void M100Reset(void) { + cmd = 0; + prg[0] = 0; + prg[1] = 1; + prg[2] = ~1; + prg[3] = ~0; + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + chr[4] = 4; + chr[5] = 5; + chr[6] = 6; + chr[7] = 7; + MMC3_Reset(); +} + +static void M100Power(void) { + cmd = 0; + prg[0] = 0; + prg[1] = 1; + prg[2] = ~1; + prg[3] = ~0; + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + chr[4] = 4; + chr[5] = 5; + chr[6] = 6; + chr[7] = 7; + MMC3_Power(); + SetWriteHandler(0x8000, 0x9FFF, M100WriteCMD); + + if (iNESCart.trainer && MISC_ROM_SIZE) { + if (MISC_ROM_DATA[0] == 0x4C) { + X6502_SetNewPC(0x7000); + } + } +} + +void Mapper100_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_FixPRG = M100PRG; + MMC3_FixCHR = M100CHR; + info->Power = M100Power; + info->Reset = M100Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper101.c b/src/mappers/mapper101.c new file mode 100644 index 000000000..706499dfe --- /dev/null +++ b/src/mappers/mapper101.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8(reg); +} + +static DECLFW(M101Write) { + reg = V; + Sync(); +} + +static void M101Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M101Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper101_Init(CartInfo *info) { + info->Power = M101Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper103.c b/src/mappers/mapper103.c new file mode 100644 index 000000000..b7053ae89 --- /dev/null +++ b/src/mappers/mapper103.c @@ -0,0 +1,110 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion - Doki Doki Panic + * + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg[3]; + +static SFORMAT StateRegs[] = { + { reg, 3, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, 0x0C); + setprg8(0xE000, 0x0F); + if (reg[2] & 0x10) { + setprg8(0x6000, reg[0] & 0x0F); + setprg8(0xA000, 0x0D); + setprg8(0xC000, 0x0E); + } else { + setprg8r(0x10, 0x6000, 0); + setprg4(0xA000, (0x0D << 1)); + setprg2(0xB000, (0x0D << 2) + 2); + setprg2r(0x10, 0xB800, 4); + setprg2r(0x10, 0xC000, 5); + setprg2r(0x10, 0xC800, 6); + setprg2r(0x10, 0xD000, 7); + setprg2(0xD800, (0x0E << 2) + 3); + } + setchr8(0); + setmirror(((reg[1] >> 3) & 0x01) ^ 0x01); +} + +static DECLFW(M103RamWrite0) { + WRAM[A & 0x1FFF] = V; +} + +static DECLFW(M103RamWrite1) { + WRAM[0x2000 + ((A - 0xB800) & 0x1FFF)] = V; +} + +static DECLFW(M103WritePRG) { + reg[0] = V; + Sync(); +} + +static DECLFW(M103WriteMirror) { + reg[1] = V; + Sync(); +} + +static DECLFW(M103WriteRAMEnable) { + reg[2] = V; + Sync(); +} + +static void M103Power(void) { + FDSSound_Power(); + reg[0] = reg[1] = 0; + reg[2] = 0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M103RamWrite0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xB800, 0xD7FF, M103RamWrite1); + SetWriteHandler(0x8000, 0x8FFF, M103WritePRG); + SetWriteHandler(0xE000, 0xEFFF, M103WriteMirror); + SetWriteHandler(0xF000, 0xFFFF, M103WriteRAMEnable); +} + +static void M103Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper103_Init(CartInfo *info) { + info->Power = M103Power; + info->Close = M103Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 16384; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper104.c b/src/mappers/mapper104.c new file mode 100644 index 000000000..a7b0fe1af --- /dev/null +++ b/src/mappers/mapper104.c @@ -0,0 +1,81 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Pegasus 5-in-1 (Golden Five) (Unl) + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, (reg[1] << 4) | (reg[0] & 0x0F)); + setprg16(0xC000, (reg[1] << 4) | 0x0F); + setchr8(0); +} + +static DECLFW(M104Write) { + switch (A & 0xF000) { + case 0x8000: + case 0x9000: + case 0xA000: + case 0xB000: + if (!(reg[1] & 0x08)) { + reg[1] = V; + Sync(); + } + break; + case 0xC000: + case 0xD000: + case 0xE000: + case 0xF000: + reg[0] = V; + Sync(); + break; + } +} + +static void M104Close(void) { +} + +static void M104Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M104Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper104_Init(CartInfo *info) { + info->Power = M104Power; + info->Close = M104Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper105.c b/src/mappers/mapper105.c new file mode 100644 index 000000000..094cd8b8d --- /dev/null +++ b/src/mappers/mapper105.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc1.h" + +static uint32 count; +static uint32 count_target = 0x28000000; + +static void M105IRQHook(int a) { + while (a--) { + if (mmc1.reg[1] & 0x10) { + count = 0; + X6502_IRQEnd(FCEU_IQEXT); + } else { + if (++count == count_target) { + X6502_IRQBegin(FCEU_IQEXT); + } + if ((count % 1789773) == 0) { + uint32 seconds = (count_target - count) / 1789773; + FCEU_DispMessage(RETRO_LOG_INFO, 1000, "Time left: %02i:%02i\n", seconds / 60, seconds % 60); + } + } + } +} + +static void M105CW(uint16 A, uint16 V) { + setchr8r(0, 0); +} + +static void M105PW(uint16 A, uint16 V) { + if (mmc1.reg[1] & 0x08) { + setprg16(A, 8 | (V & 0x7)); + } else { + setprg32(0x8000, (mmc1.reg[1] >> 1) & 0x03); + } +} + +static void M105Power(void) { + count_target = 0x20000000 | ((uint32)GameInfo->cspecial << 25); + MMC1_Power(); +} + +static void M105Reset(void) { + count_target = 0x20000000 | ((uint32)GameInfo->cspecial << 25); + MMC1_Reset(); +} + +void Mapper105_Init(CartInfo *info) { + MMC1_Init(info, 8, 0); + MMC1_cwrap = M105CW; + MMC1_pwrap = M105PW; + MapIRQHook = M105IRQHook; + info->Power = M105Power; + info->Reset = M105Reset; + AddExState(&count, 4, 0, "IRQC"); +} diff --git a/src/mappers/mapper106.c b/src/mappers/mapper106.c new file mode 100644 index 000000000..5fe755c2e --- /dev/null +++ b/src/mappers/mapper106.c @@ -0,0 +1,124 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[4], chr[8]; +static uint8 mirr, IRQa; +static uint32 IRQCount; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREGS" }, + { chr, 8, "CREGS" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, (prg[0] & 0x0F) | 0x10); + setprg8(0xA000, (prg[1] & 0x1F)); + setprg8(0xC000, (prg[2] & 0x1F)); + setprg8(0xE000, (prg[3] & 0x0F) | 0x10); + + setchr1(0x0000, chr[0] & ~1); + setchr1(0x0400, chr[1] | 1); + setchr1(0x0800, chr[2] & ~1); + setchr1(0x0c00, chr[3] | 1); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + setmirror((mirr & 0x01) ^ 0x01); +} + +static DECLFW(M106Write) { + switch (A & 0x0F) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + chr[A & 0x07] = V; + Sync(); + break; + case 0x08: case 0x09: case 0x0A: case 0x0B: + prg[A & 0x03] = V; + Sync(); + break; + case 0x0C: + mirr = V; + Sync(); + break; + case 0x0D: + IRQa = 0; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x0E: + IRQCount = (IRQCount & 0xFF00) | V; + break; + case 0x0F: + IRQCount = (IRQCount & 0x00FF) | (V << 8); + IRQa = 1; + break; + } +} + +static void M106Power(void) { + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M106Write); +} + +static void M106Reset(void) { } + +static void M106Close(void) { +} + +static void M106CpuHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount > 0x10000) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper106_Init(CartInfo *info) { + info->Reset = M106Reset; + info->Power = M106Power; + info->Close = M106Close; + MapIRQHook = M106CpuHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper107.c b/src/mappers/mapper107.c new file mode 100644 index 000000000..abfaacc15 --- /dev/null +++ b/src/mappers/mapper107.c @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.data >> 1); + setchr8(latch.data); +} + +void Mapper107_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper108.c b/src/mappers/mapper108.c new file mode 100644 index 000000000..517b1c27a --- /dev/null +++ b/src/mappers/mapper108.c @@ -0,0 +1,98 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + * Bubble Bobble (LH31) + * - submapper 1: CHR-RAM 8K + * - submapper 2: CHR-ROM 32K - UNIF UNL-BB + * Submapper 3: + * - Falsion (LH54) + * - Meikyuu Jiin Dababa (LH28) + * Submapper 4: UNIF UNL-BB + * - Pro Wrestling (LE05) + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (iNESCart.submapper == 4) { + setprg8(0x6000, ~0); + } else { + setprg8(0x6000, reg); + } + setprg32(0x8000, ~0); + if (CHR_ROM_SIZE_8K) { + setchr8(reg); + } else { + setchr8(0); + } +} + +static DECLFW(M108Write) { + reg = V; + Sync(); +} + +static void M108Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + switch (iNESCart.submapper) { + case 1: SetWriteHandler(0xF000, 0xFFFF, M108Write); break; + case 2: SetWriteHandler(0xE000, 0xFFFF, M108Write); break; + default: SetWriteHandler(0x8000, 0xFFFF, M108Write); break; + } + FDSSound_Power(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper108_Init(CartInfo *info) { + info->Power = M108Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + if (!info->iNES2 || !info->submapper) { + if (!CHR_ROM_SIZE_8K) { + if (info->mirror == MI_H) { + info->submapper = 1; + } else { + info->submapper = 3; + } + } else { + if (CHR_ROM_SIZE_8K <= (32 * 1024)) { + info->submapper = 4; + } else { + info->submapper = 2; + } + } + } +} diff --git a/src/mappers/mapper111.c b/src/mappers/mapper111.c new file mode 100644 index 000000000..3ebf16806 --- /dev/null +++ b/src/mappers/mapper111.c @@ -0,0 +1,178 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* mapper 111 - Cheapocabra board by Memblers + * http://forums.nesdev.com/viewtopic.php?p=146039 + * + * 512k PRG-ROM in 32k pages (flashable if battery backed is specified) + * 32k CHR-RAM used as: + * 2 x 8k pattern pages + * 2 x 8k nametable pages + * + * Notes: + * - CHR-RAM for nametables maps to $3000-3FFF as well, but FCEUX internally mirrors to 4k? + */ + +#include "mapinc.h" +#include "flashrom.h" +#include "mmc1.h" + +static uint8 reg; + +static int m111_mmc1 = FALSE; + +static uint8 *FLASHROM = NULL; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M111MMC1PW(uint16 A, uint16 V) { + setprg16(A, V & 0x0F); +} + +static void M111MMC1CW(uint16 A, uint16 V) { + setchr4(A, V & 0x3F); +} + +static DECLFW(M111Write_mmc1) { + mmc1.reg[(A >> 13) & 0x03] = V; + MMC1_FixPRG(); + MMC1_FixCHR(); + MMC1_FixMIR(); +} + +static void M111Power_mmc1(void) { + MMC1_Power(); + SetWriteHandler(0x8000, 0xFFFF, M111Write_mmc1); +} + +#define VRAM_OFFSET(x) (0x4000 + (0x400 * (x))) + +static void Sync(void) { + /* 7 bit 0 + * ---- ---- + * GRNC PPPP + * |||| |||| + * |||| ++++- Select 32 KB PRG ROM bank for CPU $8000-$FFFF + * |||+------ Select 8 KB CHR RAM bank for PPU $0000-$1FFF + * ||+------- Select 8 KB nametable for PPU $2000-$3EFF + * |+-------- Red LED - 0=On; 1=Off + * +--------- Green LED - 0=On; 1=Off */ + int nt = (reg & 0x20) >> 5; + + setprg32r(FLASHROM ? 0x10 : 0, 0x8000, reg & 0x0F); + setchr8((reg & 0x10) >> 4); + setntamem(CHRptr[0] + VRAM_OFFSET(0) + (nt << 13), 1, 0); + setntamem(CHRptr[0] + VRAM_OFFSET(1) + (nt << 13), 1, 1); + setntamem(CHRptr[0] + VRAM_OFFSET(2) + (nt << 13), 1, 2); + setntamem(CHRptr[0] + VRAM_OFFSET(3) + (nt << 13), 1, 3); +} + +static DECLFR(M111ReadOB) { + reg = CPU_OPENBUS; + Sync(); + return reg; +} + +static DECLFW(M111WriteReg) { + reg = V; + Sync(); +} + +static DECLFR(M111ReadFlash) { + return FlashROM_Read(A); +} + +static DECLFW(M111WriteFlash) { + FlashROM_Write(A, V); +} + +static void M111CPUCycle(int a) { + FlashROM_CPUCyle(a); +} + +static void M111Power(void) { + reg = 0xFF; + Sync(); + + SetReadHandler(0x5000, 0x5FFF, M111ReadOB); + SetReadHandler(0x7000, 0x7FFF, M111ReadOB); + + SetWriteHandler(0x5000, 0x5FFF, M111WriteReg); + SetWriteHandler(0x7000, 0x7FFF, M111WriteReg); + + SetReadHandler(0x8000, 0xFFFF, M111ReadFlash); + SetWriteHandler(0x8000, 0xFFFF, M111WriteFlash); +} + +static void M111Close(void) { + if (FLASHROM) { + FCEU_gfree(FLASHROM); + } + FLASHROM = NULL; +} + +static void StateRestore(int version) { + if (m111_mmc1) { + MMC1_FixPRG(); + MMC1_FixCHR(); + MMC1_FixMIR(); + return; + } + + Sync(); +} + +void Mapper111_Init(CartInfo *info) { + m111_mmc1 = FALSE; + if (CHR_ROM_SIZE_8K) { + /* Prior to the introduction of GTROM, Mapper 111 was assigned to a Chinese Fan Translation + * of Ninja Ryukenden (Japanese Ninja Gaiden). This translation uses a non-serialized + * version of MMC1 and supports 256KiB of CHR-ROM, whereas the official MMC1 is limited to + * 128KiB */ + m111_mmc1 = TRUE; + info->Power = M111Power_mmc1; + MMC1_pwrap = M111MMC1PW; + MMC1_cwrap = M111MMC1CW; + return; + } + + info->Power = M111Power; + info->Close = M111Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + if (info->battery) { + int fsize = PRGsize[0]; + + FLASHROM = (uint8 *)FCEU_gmalloc(fsize); + info->SaveGame[0] = FLASHROM; + info->SaveGameLen[0] = fsize; + AddExState(FLASHROM, fsize, 0, "FROM"); + memcpy(FLASHROM, PRGptr[0], fsize); + SetupCartPRGMapping(0x10, FLASHROM, fsize, 0); + + FlashROM_Init(FLASHROM, fsize, 0xBF, 0xB7, 4096, 0x5555, 0x2AAA); + MapIRQHook = M111CPUCycle; + } +} diff --git a/src/mappers/mapper112.c b/src/mappers/mapper112.c new file mode 100644 index 000000000..0cc0e97e2 --- /dev/null +++ b/src/mappers/mapper112.c @@ -0,0 +1,111 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NTDEC, ASDER games + * + */ + +#include "mapinc.h" + +static uint8 reg[8]; +static uint8 mirror, cmd, chrBase; + +static SFORMAT StateRegs[] = { + { &cmd, 1, "CMD" }, + { &mirror, 1, "MIRR" }, + { &chrBase, 1, "CHRB" }, + { reg, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + + setprg8(0x8000, reg[0]); + setprg8(0xA000, reg[1]); + setprg16(0xC000, ~0); + + setchr2(0x0000, (reg[2] >> 1)); + setchr2(0x0800, (reg[3] >> 1)); + setchr1(0x1000, ((chrBase << 4) & 0x100) | reg[4]); + setchr1(0x1400, ((chrBase << 3) & 0x100) | reg[5]); + setchr1(0x1800, ((chrBase << 2) & 0x100) | reg[6]); + setchr1(0x1C00, ((chrBase << 1) & 0x100) | reg[7]); + + setmirror((mirror & 0x01) ^ 0x01); +} + +static DECLFW(M112Write) { + switch (A & 0xE000) { + case 0x8000: + cmd = V; + break; + case 0xA000: + reg[cmd & 0x07] = V; + Sync(); + break; + case 0xC000: + chrBase = V; + Sync(); + break; + case 0xE000: + mirror = V; + Sync(); + break; + } +} + +static void M112Close(void) { +} + +static void M112Power(void) { + reg[0] = 0; + reg[1] = 1; + reg[2] = 0; + reg[3] = 2; + reg[4] = 4; + reg[5] = 5; + reg[6] = 6; + reg[7] = 7; + chrBase = 0; + Sync(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M112Write); + + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(8, 0x6000, WRAM); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper112_Init(CartInfo *info) { + info->Power = M112Power; + info->Close = M112Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAM = (uint8 *)FCEU_gmalloc(8192); + SetupCartPRGMapping(0x10, WRAM, 8192, 1); + AddExState(WRAM, 8192, 0, "WRAM"); +} diff --git a/src/mappers/mapper113.c b/src/mappers/mapper113.c new file mode 100644 index 000000000..1ef59d4fa --- /dev/null +++ b/src/mappers/mapper113.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg >> 3) & 0x07); + setchr8(((reg >> 3) & 0x08) | (reg & 0x07)); + setmirror(reg >> 0x07); +} + +static DECLFW(M113Write) { + if (A & 0x100) { + reg = V; + Sync(); + } +} + +static void M113Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, M113Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper113_Init(CartInfo *info) { + info->Power = M113Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper114.c b/src/mappers/mapper114.c new file mode 100644 index 000000000..3775db6ee --- /dev/null +++ b/src/mappers/mapper114.c @@ -0,0 +1,117 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static uint32 M114_addr[2][8] = { + { 0xA001, 0xA000, 0x8000, 0xC000, 0x8001, 0xC001, 0xE000, 0xE001 }, /* 0: Aladdin, The Lion King */ + { 0xA001, 0x8001, 0x8000, 0xC001, 0xA000, 0xC000, 0xE000, 0xE001 } /* 1: Boogerman */ +}; + +static uint8 M114_index[2][8] = { + { 0, 3, 1, 5, 6, 7, 2, 4 }, /* 0: Aladdin, The Lion King */ + { 0, 2, 5, 3, 6, 1, 7, 4 }, /* 1: Boogerman */ +}; + +static void M114PW(uint16 A, uint16 V) { + if (reg[0] & 0x80) { + uint8 bank = reg[0] & 0x0F; + + if (reg[0] & 0x20) { + setprg32(0x8000, bank >> 1); + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { + setprg8(A, V & 0x3F); + } +} + +static void M114CW(uint16 A, uint16 V) { + setchr1(A, ((reg[1] << 8) & 0x100) | (V & 0x0FF)); +} + +static DECLFW(M114WriteReg) { + reg[A & 0x01] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static DECLFW(M114Write) { + A = M114_addr[iNESCart.submapper & 0x01][((A >> 12) & 0x06) | (A & 0x01)]; + switch (A & 0xE001) { + case 0x8000: + V = (V & 0xF8) | M114_index[iNESCart.submapper & 0x01][V & 0x07]; + MMC3_CMDWrite(A, V); + break; + default: + MMC3_Write(A, V); + break; + } +} + +static DECLFR(M114ReadDip) { + if ((A & 0x03) == 0x02) { + return (CPU_OPENBUS & ~0x07) | (dipsw & 0x07); + } + return CPU_OPENBUS; +} + +static void M114Power(void) { + reg[0] = reg[1] = 0; + MMC3_Power(); + SetReadHandler(0x6000, 0x7FFF, M114ReadDip); + SetWriteHandler(0x6000, 0x7FFF, M114WriteReg); + SetWriteHandler(0x8000, 0xFFFF, M114Write); +} + +static void M114Reset(void) { + reg[0] = reg[1] = 0; + dipsw++; + MMC3_Reset(); +} + +void Mapper114_Init(CartInfo *info) { + isRevB = 0; + /* Use NES 2.0 submapper to identify scrambling pattern, otherwise CRC32 for Boogerman and test rom */ + if (!info->iNES2) { + if ((info->CRC32 == 0x80eb1839) || (info->CRC32 == 0x071e4ee8)) { + info->submapper = 1; + } + } + + MMC3_Init(info, 0, 0); + MMC3_pwrap = M114PW; + MMC3_cwrap = M114CW; + info->Power = M114Power; + info->Reset = M114Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper115.c b/src/mappers/mapper115.c new file mode 100644 index 000000000..ab08b318b --- /dev/null +++ b/src/mappers/mapper115.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void M115PW(uint16 A, uint16 V) { + if (reg[0] & 0x80) { + uint8 bank = reg[0] & 0x0F; + + if (reg[0] & 0x20) { + setprg32(0x8000, bank >> 1); + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { + setprg8(A, V & 0x3F); + } +} + +static void M115CW(uint16 A, uint16 V) { + setchr1(A, ((reg[1] << 8) & 0x100) | (V & 0xFF)); +} + +static DECLFW(M115WriteReg) { + reg[A & 0x01] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M115Power(void) { + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M115WriteReg); +} + +void Mapper115_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M115CW; + MMC3_pwrap = M115PW; + info->Power = M115Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper116.c b/src/mappers/mapper116.c new file mode 100644 index 000000000..a1ceed70c --- /dev/null +++ b/src/mappers/mapper116.c @@ -0,0 +1,208 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1) + * the same as 603-5052 board (TODO: add reading registers, merge) + * SL1632 2-in-1 protected board, similar to SL12 (TODO: find difference) + * + * Known PCB: + * + * Garou Densetsu Special (G0904.PCB, Huang-1, GAL dip: W conf.) + * Kart Fighter (008, Huang-1, GAL dip: W conf.) + * Somari (008, C5052-13, GAL dip: P conf., GK2-P/GK2-V maskroms) + * Somari (008, Huang-1, GAL dip: W conf., GK1-P/GK1-V maskroms) + * AV Mei Shao Nv Zhan Shi (aka AV Pretty Girl Fighting) (SL-12 PCB, Hunag-1, GAL dip: unk conf. SL-11A/SL-11B maskroms) + * Samurai Spirits (Full version) (Huang-1, GAL dip: unk conf. GS-2A/GS-4A maskroms) + * Contra Fighter (603-5052 PCB, C5052-3, GAL dip: unk conf. SC603-A/SCB603-B maskroms) + * + */ + +#include "mapinc.h" +#include "vrc24.h" +#include "mmc3.h" +#include "mmc1.h" + +#define MODE_MMC1 mode & 0x02 +#define MODE_MMC3 mode & 0x01 + +static uint8 mode = 0; +static uint8 game = 0; + +static SFORMAT StateRegs[] = { + { &mode, 1, "MODE"}, + { &game, 1, "GAME"}, + { 0 } +}; + +static uint32 GetPRGMask(void) { + if (iNESCart.submapper != 3) { + return 0x3F; + } + return (game ? 0x0F : 0x1F); +} + +static uint32 GetPRGBase(void) { + if (game) { + return (game + 1) * 0x10; + } + return 0; +} + +static uint32 GetCHRMask(void) { + return (game ? 0x7F : 0xFF); +} + +static uint32 GetCHRBase(void) { + return (game ? (game + 1) * 0x80 : 0); +} + +static void M116VRC24PW(uint16 A, uint16 V) { + setprg8(A, GetPRGBase() | (V & GetPRGMask())); +} + +static void M116VRC24CW(uint16 A, uint16 V) { + setchr1(A, ((mode << 6) & 0x100) | GetCHRBase() | (V & GetCHRMask())); +} + +static void M116MMC3PW(uint16 A, uint16 V) { + setprg8(A, GetPRGBase() | (V & GetPRGMask())); +} + +static void M116MMC3CW(uint16 A, uint16 V) { + setchr1(A, ((mode << 6) & 0x100) | GetCHRBase() | (V & GetCHRMask())); +} + +static void M116MMC1PW(uint16 A, uint16 V) { + if (iNESCart.submapper == 2) { + setprg16(A, V >> 1); + } else { + setprg16(A, (GetPRGBase() >> 1) | (V & (GetPRGMask() >> 1))); + } +} + +static void M116MMC1CW(uint16 A, uint16 V) { + setchr4(A, (GetCHRBase() >> 2) | (V & (GetCHRMask() >> 2))); +} + +static void Sync(void) { + if (MODE_MMC1) { + MMC1_FixPRG(); + MMC1_FixCHR(); + MMC1_FixMIR(); + } else if (MODE_MMC3) { + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } else { + VRC24_FixPRG(); + VRC24_FixCHR(); + VRC24_FixMIR(); + } +} + +static void applyMode(void) { + if (MODE_MMC1) { + SetWriteHandler(0x8000, 0xFFFF, MMC1_Write); + if (iNESCart.submapper != 1) { + MMC1_Write(0x8000, 0x80); + } + } else if (MODE_MMC3) { + SetWriteHandler(0x8000, 0xFFFF, MMC3_Write); + } else { + SetWriteHandler(0x8000, 0xFFFF, VRC24_Write); + } +} + +static DECLFW(M116ModeWrite) { + if (A & 0x100) { + mode = V; + applyMode(); + Sync(); + } +} + +static void M116HBIRQ(void) { + if ((mode & 0x03) == 0x01) { + MMC3_IRQHBHook(); + } +} + +static void StateRestore(int version) { + Sync(); +} + +static void M116Reset(void) { + if (iNESCart.submapper == 3) { + game = game + 1; + if (game > 4) { + game = 0; + } + } + applyMode(); + Sync(); +} + +static void M116Power(void) { + game = (iNESCart.submapper == 3) ? 4 : 0; + mode = 1; + + MMC3_Power(); + MMC1_Reset(); + VRC24_Power(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, M116ModeWrite); + + vrc24.chr[0] = ~0; + vrc24.chr[1] = ~0; + vrc24.chr[2] = ~0; + vrc24.chr[3] = ~0; + + applyMode(); + Sync(); +} + +void Mapper116_Init(CartInfo *info) { + VRC24_Init(info, VRC2, 0x01, 0x02, FALSE, TRUE); + VRC24_pwrap = M116VRC24PW; + VRC24_cwrap = M116VRC24CW; + + MMC3_Init(info, FALSE, FALSE); + MMC3_pwrap = M116MMC3PW; + MMC3_cwrap = M116MMC3CW; + + MMC1_Init(info, FALSE, FALSE); + MMC1_pwrap = M116MMC1PW; + MMC1_cwrap = M116MMC1CW; + mmc1_type = MMC1A; + + info->Power = M116Power; + info->Reset = M116Reset; + + GameHBIRQHook = M116HBIRQ; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + /* PRG 128K and CHR 128K is Huang-2 (iNESCart.submapper 2) */ + if ((info->submapper != 2) && (PRG_ROM_SIZE_16K == (128 * 1024)) && (CHR_ROM_SIZE_8K == (128 * 1024))) { + info->submapper = 2; + } +} diff --git a/src/mappers/mapper117.c b/src/mappers/mapper117.c new file mode 100644 index 000000000..15ded86d5 --- /dev/null +++ b/src/mappers/mapper117.c @@ -0,0 +1,123 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[4], chr[8], mirr; +static uint8 IRQa, IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { &mirr, 1, "MREG" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 1, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, ~0); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + setmirror(mirr ^ 1); +} + +static DECLFW(M117Write) { + switch (A & 0xF000) { + case 0x8000: + prg[A & 0x03] = V; + Sync(); + break; + case 0xA000: + switch (A & 0x0F) { + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + chr[A & 0x07] = V; + Sync(); + break; + } + break; + case 0xC000: + switch (A & 0x03) { + case 1: + IRQLatch = V; + break; + case 3: + IRQCount = IRQLatch; + IRQa |= 2; + break; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xD000: + mirr = V & 1; + Sync(); + break; + case 0xE000: + IRQa &= ~1; + IRQa |= V & 1; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +static void M117Power(void) { + prg[0] = ~3; + prg[1] = ~2; + prg[2] = ~1; + prg[3] = ~0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M117Write); +} + +static void M117IRQHook(void) { + if (IRQa == 3 && IRQCount) { + IRQCount--; + if (!IRQCount) { + IRQa &= 1; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper117_Init(CartInfo *info) { + info->Power = M117Power; + GameHBIRQHook = M117IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper118.c b/src/mappers/mapper118.c new file mode 100644 index 000000000..a6be1fa8f --- /dev/null +++ b/src/mappers/mapper118.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M118MIR(void) { + if (mmc3.cmd & 0x80) { + setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); + } else { + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); + } +} + +static DECLFW(M118Write) { + switch (A & 0xE001) { + case 0x8001: + switch (mmc3.cmd & 0x07) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + mmc3.reg[mmc3.cmd & 0x07] = V; + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + default: + MMC3_CMDWrite(A, V); + break; + } + case 0xA000: + /* MMC3 mirroring not used in favor of nametable mirroring */ + break; + default: + MMC3_CMDWrite(A, V); + break; + } +} + +static void M118Power(void) { + MMC3_Power(); + SetWriteHandler(0x8000, 0xBFFF, M118Write); +} + +void Mapper118_Init(CartInfo *info) { + uint8 ws = info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) / 1024 : 8; + MMC3_Init(info, ws, info->battery); + info->Power = M118Power; + MMC3_FixMIR = M118MIR; +} diff --git a/src/mappers/mapper119.c b/src/mappers/mapper119.c new file mode 100644 index 000000000..f2f16276b --- /dev/null +++ b/src/mappers/mapper119.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M119CW(uint16 A, uint16 V) { + if (V & 0x40) { + setchr1r(0x10, A, V & 0x07); + } else { + setchr1(A, V); + } +} + +static void M119Close(void) { + MMC3_Close(); +} + +void Mapper119_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + info->Close = M119Close; + MMC3_cwrap = M119CW; + CHRRAMSIZE = 8192; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper120.c b/src/mappers/mapper120.c new file mode 100644 index 000000000..f99abd7d4 --- /dev/null +++ b/src/mappers/mapper120.c @@ -0,0 +1,62 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, reg); + setprg32(0x8000, 2); + setchr8(0); +} + +static DECLFW(M120Write) { + if ((A & 0xE100) == 0x4100) { + reg = V & 0x07; + Sync(); + } +} + +static void M120Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, M120Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper120_Init(CartInfo *info) { + info->Power = M120Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper121.c b/src/mappers/mapper121.c new file mode 100644 index 000000000..e0f08d041 --- /dev/null +++ b/src/mappers/mapper121.c @@ -0,0 +1,129 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007-2008 Mad Dumper, CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Panda prince pirate. + * MK4, MK6, A9711/A9713 board + * 6035052 seems to be the same too, but with prot array in reverse + * A9746 seems to be the same too, check + * 187 seems to be the same too, check (A98402 board) + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 prg[3]; +static uint8 reg; +static uint8 readIndex; +static uint8 protIndex; +static uint8 protLatch; + +static SFORMAT StateRegs[] = { + { prg, 3, "PREG" }, + { ®, 2, "REGS" }, + { &readIndex, 1, "PRRD" }, + { &protIndex, 1, "PRID" }, + { &protLatch, 1, "PRLT" }, + { 0 } +}; + +static void M121CW(uint16 A, uint16 V) { + if (PRG_ROM_SIZE_16K > (256 * 1024)) { + setchr1(A, ((reg & 0x80) << 1) | V); + } else { + if ((A & 0x1000) == (uint32)((mmc3.cmd & 0x80) << 5)){ + setchr1(A, 0x100 | V); + } else { + setchr1(A, V); + } + } +} + +static void M121PW(uint16 A, uint16 V) { + uint8 mask = 0x1F; + uint8 base = ((reg & 0x80) >> 2); + + if ((protIndex & 0x20) && (A > 0x8000)) { + mask = 0xFF; + V = prg[((A >> 13) & 0x03) - 1]; + } + + setprg8(A, base | (V & mask)); +} + +static const uint8 prot_array[] = { 0x83, 0x83, 0x42, 0x00, 0x00, 0x02, 0x02, 0x03 }; +static DECLFR(M121ReadLUT) { + return prot_array[readIndex]; +} + +static DECLFW(M121WriteLUT) { + readIndex = ((A >> 6) & 0x04) | (V & 0x03); + if (A & 0x0100) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static DECLFW(M121Write) { + switch (A & 0xE001) { + case 0x8001: + switch (A & 0x03) { + case 0x01: + protLatch = ((V & 0x01) << 5) | ((V & 0x02) << 3) | + ((V & 0x04) << 1) | ((V & 0x08) >> 1) | + ((V & 0x10) >> 3) | ((V & 0x20) >> 5); + if ((protIndex == 0x26) || (protIndex == 0x28) || (protIndex == 0x2A)) { + prg[0x15 - (protIndex >> 1)] = protLatch; + } + break; + case 0x03: + protIndex = V & 0x3F; + if ((protIndex & 0x20) && protLatch) { + prg[2] = protLatch; + } + break; + } + mmc3.reg[mmc3.cmd & 0x07] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + break; + default: + MMC3_CMDWrite(A, V); + break; + } +} + +static void M121Power(void) { + memset(prg, 0, sizeof(prg)); + reg = readIndex = protIndex = protLatch = 0; + MMC3_Power(); + SetReadHandler(0x5000, 0x5FFF, M121ReadLUT); + SetWriteHandler(0x5000, 0x5FFF, M121WriteLUT); + SetWriteHandler(0x8000, 0x9FFF, M121Write); +} + +void Mapper121_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M121PW; + MMC3_cwrap = M121CW; + info->Power = M121Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper123.c b/src/mappers/mapper123.c new file mode 100644 index 000000000..b80257b2f --- /dev/null +++ b/src/mappers/mapper123.c @@ -0,0 +1,73 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 123 - UNL-H2288 */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M123PW(uint16 A, uint16 V) { + if (reg & 0x40) { + uint8 bank = ((reg & 0x28) >> 2) | (reg & 0x05); + + if (reg & 2) { + setprg32(0x8000, bank >> 1); + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { + setprg8(A, V & 0x3F); + } +} + +static DECLFW(M123WriteHi) { + static const uint8 m114_perm[8] = { 0, 3, 1, 5, 6, 7, 2, 4 }; + + if (!(A & 0x01)) { + V = (V & 0xC0) | m114_perm[V & 0x07]; + } + + MMC3_CMDWrite(A, V); +} + +static DECLFW(M123WriteLo) { + if (A & 0x800) { + reg = V; + MMC3_FixPRG(); + } +} + +static void M123Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x5000, 0x5FFF, M123WriteLo); + SetWriteHandler(0x8000, 0x9FFF, M123WriteHi); +} + +void Mapper123_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M123PW; + info->Power = M123Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper124.c b/src/mappers/mapper124.c new file mode 100644 index 000000000..cfe11442c --- /dev/null +++ b/src/mappers/mapper124.c @@ -0,0 +1,234 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* iNES mapper 124 is assigned to the Super Game Mega Type III pirate arcade board. */ + +#include "mapinc.h" +#include "mmc1.h" +#include "mmc3.h" +#include "latch.h" + +#define MAPPER_UNROM 0 +#define MAPPER_AMROM 1 +#define MAPPER_MMC1 2 +#define MAPPER_MMC3 3 + +static uint8 reg[2]; +static uint8 mapper; +static uint8 dipsw; + +static uint8 audioEnable; +static uint8 *ExRAM; + +static SFORMAT StateRegs[] = { + { reg, 2, "MODE" }, + { &mapper, 1, "MAPR" }, + { 0 } +}; + +static uint32 GetPRGBase(void) { + return ((reg[1] << 4) & 0x1F0); +} + +static uint32 GetCHRBase(void) { + return ((reg[0] << 7) & 0x780); +} + +static void M124MMC1PW(uint16 A, uint16 V) { + setprg16(A, (GetPRGBase() >> 1) | (V & 0x07)); +} + +static void M124MMC1CW(uint16 A, uint16 V) { + setchr4(A, (GetCHRBase() >> 2) | (V & 0x1F)); +} + +static void M124MMC3PW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x20) ? 0x0F : 0x1F; + setprg8(A, GetPRGBase() | (V & mask)); +} + +static void M124MMC3CW(uint16 A, uint16 V) { + uint16 mask = (reg[0] & 0x40) ? 0x7F : 0xFF; + setchr1(A, GetCHRBase() | (V & mask)); +} + +static void Sync(void) { + switch (mapper) { + case MAPPER_UNROM: + setprg16(0x8000, (GetPRGBase() >> 1) | (latch.data & 0x07)); + setprg16(0xC000, (GetPRGBase() >> 1) | 0x07); + setchr8(0); + setmirror(MI_V); + break; + case MAPPER_AMROM: + setprg32(0x8000, (GetPRGBase() >> 2) | (latch.data & 0x07)); + setchr8(0); + setmirror(MI_0 + ((latch.data >> 4) & 1)); + break; + case MAPPER_MMC1: + setprg16r(0x10, 0x6000, 0); + MMC1_FixPRG(); + MMC1_FixCHR(); + MMC1_FixMIR(); + break; + case MAPPER_MMC3: + setprg16r(0x10, 0x6000, 0); + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + } + setprg4(0x5000, 0x380 + 0x05); + if (reg[1] & 0x20) { + setprg8(0x6000, (0x380 + 0x06) >> 1); + } + if (!(reg[1] & 0x80)) { + setprg32(0x8000, (0x380 + 0x08) >> 3); + } + if (!(reg[1] & 0x40)) { + setchr8r(0x10, 0); + } +} + +static void applyMode(void) { + mapper = (reg[0] >> 4) & 0x03; +} + +static DECLFR(ReadRAM) { + return ExRAM[A]; +} + +static DECLFW(WriteRAM) { + ExRAM[A] = V; +} + +extern uint8 coinon; +static DECLFR(M124ReadCoinDIP) { + if ((A & 0x0F) == 0x0F) { + /* TODO: Hack to use VS' coin insert map to use as mappers coin insert trigger */ + return ((coinon ? 0x80 : 0x00) | (dipsw & 0x7F)); + } + return CPU_OPENBUS; +} + +static DECLFW(M124WriteReg) { + if (A & 0x10) { + audioEnable = V; + } else { + reg[A & 0x01] = V; + applyMode(); + Sync(); + } +} + +static DECLFW(M124Write) { + switch (mapper) { + case MAPPER_UNROM: + case MAPPER_AMROM: + Latch_Write(A, V); + break; + case MAPPER_MMC3: + MMC3_Write(A, V); + break; + case MAPPER_MMC1: + MMC1_Write(A, V); + break; + } +} + +static void M124Close(void) { + if (ExRAM) { + FCEU_gfree(ExRAM); + ExRAM = NULL; + } +} + +static void M124Reset(void) { + dipsw++; + Sync(); +} + +static void M124Power(void) { + memset(reg, 0, sizeof(reg)); + mapper = 0; + dipsw = 0; + + MMC1_Reset(); + MMC3_Reset(); + Latch_RegReset(); + + SetReadHandler(0x0800, 0x0FFF, ReadRAM); + SetWriteHandler(0x800, 0x0FFF, WriteRAM); + + SetReadHandler(0x4F00, 0x4FFF, M124ReadCoinDIP); + + SetReadHandler(0x5000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, M124WriteReg); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M124Write); + + applyMode(); + Sync(); +} + +static void M124HBIRQHook(void) { + if (mapper == MAPPER_MMC3) { + MMC3_IRQHBHook(); + } +} + +static void StateRestore(int version) { + applyMode(); + Sync(); +} + +void Mapper124_Init(CartInfo *info) { + MMC1_Init(info, FALSE, FALSE); + MMC1_pwrap = M124MMC1PW; + MMC1_cwrap = M124MMC1CW; + mmc1_type = MMC1A; + + MMC3_Init(info, FALSE, FALSE); + MMC3_pwrap = M124MMC3PW; + MMC3_cwrap = M124MMC3CW; + + Latch_Init(info, Sync, NULL, FALSE, TRUE); + + info->Power = M124Power; + info->Reset = M124Reset; + info->Close = M124Close; + GameHBIRQHook = M124HBIRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + ExRAM = (uint8 *)FCEU_gmalloc(4096); + AddExState(ExRAM, 4096, 0, "ExRAM"); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, TRUE); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper125.c b/src/mappers/mapper125.c new file mode 100644 index 000000000..e8c0f29d9 --- /dev/null +++ b/src/mappers/mapper125.c @@ -0,0 +1,76 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 125 - UNL-M125 + * FDS Conversion - Monty no Doki Doki Daisassō, Monty on the Run, cartridge code M125 + * + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 prg; + +static SFORMAT StateRegs[] = { + { &prg, 1, "PREG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, prg); + setprg8(0x8000, ~3); + setprg8(0xa000, ~2); + setprg8r(0x10, 0xC000, 0); + setprg8(0xE000, ~0); + setchr8(0); +} + +static DECLFW(M125WritePRG) { + prg = V; + Sync(); +} + +static void M125Power(void) { + prg = 0; + Sync(); + FDSSound_Power(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x6000, M125WritePRG); + SetWriteHandler(0xC000, 0xDFFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M125Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper125_Init(CartInfo *info) { + info->Power = M125Power; + info->Close = M125Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper126.c b/src/mappers/mapper126.c new file mode 100644 index 000000000..11c5b38eb --- /dev/null +++ b/src/mappers/mapper126.c @@ -0,0 +1,201 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 422: "Normal" version of the mapper. Represents UNIF boards BS-400R and BS-4040R. + * Mapper 126: Power Joy version of the mapper, connecting CHR A18 and A19 in reverse order. + * Mapper 534: Waixing version of the mapper, inverting the reload V of the MMC3 scanline counter. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; +static uint8 dipsw; +static uint8 oldump = FALSE; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M126PW(uint16 A, uint16 V) { + uint8 reg0 = reg[0] ^ (oldump ? 0 : 0x20); + uint16 mask = (reg0 & 0x40) ? 0x0F : 0x1F; + uint16 base = (((reg0 << 4) & 0x70) | ((reg0 << 3) & 0x180)) & ~mask; + + switch (iNESCart.submapper) { + case 1: base |= ((base & 0x100) >> 1); break; + case 2: base |= ((reg[1] & 0x02) << 5); break; + } + + if (reg[3] & 0x08) { + uint8 b = (A >> 13) & 0x03; + V = MMC3_GetPRGBank(b & (((reg[3] & 0x0D) == 0x0D) ? 0x02 : ((reg[3] & 0x01) ? 0 : 0x03))); + switch (reg[3] & 0x03) { + case 0: V = ((V << 1) & ~0x03) | (V & 0x03); break; + case 1: V = ((V << 1) & ~0x01) | (b & 0x03); break; + case 2: V = ((V << 2) & ~0x03) | (V & 0x03); break; + case 3: V = ((V << 2) & ~0x03) | (b & 0x03); break; + } + } else { + switch (reg[3] & 0x03) { + case 1: + case 2: + base = base | (mmc3.reg[6] & mask); + V = (A >> 13) & 0x01; + mask = 0x01; + break; + case 3: + base = base | (mmc3.reg[6] & mask); + V = (A >> 13) & 0x03; + mask = 0x03; + break; + } + } + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M126CW(uint16 A, uint16 V) { + uint8 reg0 = reg[0] ^ (oldump ? 0 : 0x20); + uint16 mask = (reg0 & 0x80) ? 0x7F : 0xFF; + uint16 base = (reg0 << 4) & 0x380; + + if (iNESCart.mapper == 126) { + base = ((reg0 << 4) & 0x080) | ((reg0 << 3) & 0x100) | ((reg0 << 5) & 0x200); + } + if (reg[3] & 0x10) { + base = (((base & ~mask) >> 3) | (reg[2] & (mask >> 3))) << 3; + V = (A >> 10) & 0x07; + mask = 0x07; + } + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M126MIR(void) { + if (reg[3] & 0x20) { + setmirror(MI_0 + ((mmc3.reg[6] & 0x10) >> 4)); + } else if (reg[1] & 0x02) { + switch (mmc3.mirr & 0x03) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } + } else { + setmirror((mmc3.mirr & 0x01) ^ 0x01); + } +} + +static DECLFR(M126ReadDIP) { + if (reg[1] & 0x01) { + return CartBR((A & ~0x01) | (dipsw & 0x01)); + } + return CartBR(A); +} + +static DECLFW(M126WriteWRAM) { + CartBW(A, V); + if (!(reg[3] & 0x80)) { + reg[A & 0x03] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } else if ((A & 0x03) == 0x02) { + const uint8 mask = 0xFF & ~(reg[2] & 0x80 ? 0xF0 : 0x00) & ~((reg[2]) >> 3 & 0x0E); + reg[2] = (reg[2] & ~mask) | (V & mask); + MMC3_FixCHR(); + } +} + +static DECLFW(M534IRQWrite) { + V ^= 0xFF; + MMC3_IRQWrite(A, V); +} + +static DECLFW(M126MMC3Write) { + if ((reg[3] & 0x09) == 0x09) { + MMC3_Write(0x8000 | (((reg[3] & 0x08) ? 0x01 : A) & 0x01), V); + } else { + MMC3_Write(A, V); + } +} + +static void M126Reset(void) { + dipsw++; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Reset(); +} + +static void M126Power(void) { + dipsw = 0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M126WriteWRAM); + SetWriteHandler(0x8000, 0xFFFF, M126MMC3Write); + SetReadHandler(0x8000, 0xFFFF, M126ReadDIP); + if (iNESCart.mapper == 534) { + SetWriteHandler(0xC000, 0xDFFF, M534IRQWrite); + } +} + +static void InitCommon(CartInfo *info) { + uint8 ws = 8; + if (info->iNES2) { + ws = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; + } + MMC3_Init(info, ws, info->battery); + MMC3_FixMIR = M126MIR; + MMC3_cwrap = M126CW; + MMC3_pwrap = M126PW; + info->Power = M126Power; + info->Reset = M126Reset; + AddExState(StateRegs, ~0, 0, NULL); + + switch (iNESCart.CRC32) { + case 0xEAD80031: /* Gamezone 118-in-1 (AT-207) */ + case 0x6FCBC309: /* Power Joy Classic TV Game 84-in-1 (PJ-008) */ + case 0x6D61FE21: /* 1998 4000000-in-1 (BS-400 PCB) */ + case 0x3FF46175: + case 0xA3FF9D9B: + case 0x2BDD0FC2: + case 0x5789017D: /* (GD-106) 18-in-1 */ + case 0x46A01871: /* 3000000-in-1 (BS-300 PCB) */ + case 0x2466B80A: /* 700000-in-1 (BS-400 PCB) */ + case 0x871CFD16: + case 0xB2724618: + case 0x42A9219D: + oldump = TRUE; + break; + } +} + +void Mapper126_Init(CartInfo *info) { + InitCommon(info); +} + +void Mapper422_Init(CartInfo *info) { + InitCommon(info); +} + +void Mapper534_Init(CartInfo *info) { + InitCommon(info); +} diff --git a/src/mappers/mapper127.c b/src/mappers/mapper127.c new file mode 100644 index 000000000..a1c15ea7b --- /dev/null +++ b/src/mappers/mapper127.c @@ -0,0 +1,116 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[4], chr[8], nt[4]; +static uint8 IRQCount, IRQa; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { nt, 4, "NTAM" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 1, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + prg[3] |= 0x0C; + setprg8(0x8000, prg[0] & 0x0F); + setprg8(0xA000, prg[1] & 0x0F); + setprg8(0xC000, prg[2] & 0x0F); + setprg8(0xE000, prg[3] & 0x0F); + + setchr1(0x0000, chr[0] & 0x7F); + setchr1(0x0400, chr[1] & 0x7F); + setchr1(0x0800, chr[2] & 0x7F); + setchr1(0x0C00, chr[3] & 0x7F); + setchr1(0x1000, chr[4] & 0x7F); + setchr1(0x1400, chr[5] & 0x7F); + setchr1(0x1800, chr[6] & 0x7F); + setchr1(0x1C00, chr[7] & 0x7F); + + setmirrorw(nt[0] & 0x01, nt[1] & 0x01, nt[2] & 0x01, nt[3] & 0x01); +} + +static DECLFW(M127Write) { + switch (A & 0x73) { + case 0x00: case 0x01: case 0x02: case 0x03: + prg[A & 3] = V; + Sync(); + break; + + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x20: case 0x21: case 0x22: case 0x23: + chr[((A >> 3) & 4) | (A & 3)] = V; + Sync(); + break; + + case 0x30: case 0x31: case 0x32: case 0x33: + IRQa = 1; + break; + + case 0x40: case 0x41: case 0x42: case 0x43: + IRQa = 0; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + + case 0x50: case 0x51: case 0x52: case 0x53: + nt[A & 3] = V; + Sync(); + break; + } +} + +static void M127Power(void) { + prg[0] = prg[1] = prg[2] = prg[3] = ~0; + chr[0] = chr[1] = chr[2] = chr[3] = 0; + chr[4] = chr[5] = chr[6] = chr[7] = 0; + nt[0] = nt[1] = nt[2] = nt[3] = 0; + IRQa = IRQCount = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M127Write); +} + +static void M127IRQHook(int a) { + int count = a; + while (count--) { + if (IRQa) { + IRQCount--; + if (!IRQCount) { + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper127_Init(CartInfo *info) { + info->Power = M127Power; + MapIRQHook = M127IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper128.c b/src/mappers/mapper128.c new file mode 100644 index 000000000..9669c5673 --- /dev/null +++ b/src/mappers/mapper128.c @@ -0,0 +1,61 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static uint16 reg = 0; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, (reg >> 2) | (latch.data & 0x07)); + setprg16(0xC000, (reg >> 2) | 0x07); + setchr8(0); + setmirror(((reg >> 1) & 0x01) ^ 0x01); +} + +static DECLFW(M128Write) { + if (reg < 0xF000) { + reg = A & 0xFFFF; + } + Latch_Write(A, V); +} + +static void M128Reset(void) { + reg = 0; + Latch_RegReset(); +} + +static void M128Power(void) { + reg = 0; + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M128Write); +} + +void Mapper128_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M128Power; + info->Reset = M128Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper132.c b/src/mappers/mapper132.c new file mode 100644 index 000000000..3f01e5958 --- /dev/null +++ b/src/mappers/mapper132.c @@ -0,0 +1,98 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "txc.h" + +/**** LEGACY MAPPER IMPLEMENTATION ****/ + +static uint8 reg[4]; + +static SFORMAT UNL22211StateRegs[] = { + { reg, 4, "REGS" }, + { 0 } +}; + +static void UNL22211Sync(void) { + setprg32(0x8000, (reg[2] >> 2) & 1); + setchr8(reg[2] & 3); +} + +static DECLFW(UNL22211WriteLo) { + if (A & 0x100) { + reg[A & 3] = V; + UNL22211Sync(); + } +} + +static DECLFR(UNL22211ReadLo) { + return ((reg[1] ^ reg[2]) | 0x40); +} + +static void UNL22211Power(void) { + UNL22211Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x4100, UNL22211ReadLo); + SetWriteHandler(0x4100, 0x4FFF, UNL22211WriteLo); +} + +static void UNL22211StateRestore(int version) { + UNL22211Sync(); +} + +static void UNL22211_Init(CartInfo *info) { + info->Power = UNL22211Power; + GameStateRestore = UNL22211StateRestore; + AddExState(&UNL22211StateRegs, ~0, 0, 0); +} + +/* Mapper 132 */ + +static void M132Sync(void) { + setprg32(0x8000, (txc.output >> 2) & 0x01); + setchr8(txc.output & 0x03); +} + +static DECLFW(M132Write) { + TXC_Write(A, V & 0x0F); +} + +static DECLFR(M132Read) { + return ((CPU_OPENBUS & 0xF0) | (TXC_Read(A) & 0x0F)); +} + +static void M132Power(void) { + TXC_Power(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M132Read); + SetWriteHandler(0x4100, 0xFFFF, M132Write); +} + +void Mapper132_Init(CartInfo *info) { + if ((info->CRC32) == 0x2A5F4C5A) { + /* Jin Gwok Sei Chuen Saang (Ch) [U][!] */ + FCEU_printf(" WARNING: Using alternate mapper implementation.\n"); + UNL22211_Init(info); + return; + } + TXC_Init(info, M132Sync); + info->Power = M132Power; +} diff --git a/src/mappers/mapper133.c b/src/mappers/mapper133.c new file mode 100644 index 000000000..a0217d7f3 --- /dev/null +++ b/src/mappers/mapper133.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 133 - Sachen 3009 */ + +#include "mapinc.h" + +static uint8 reg = 0; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg >> 2) & 0x01); + setchr8(reg & 0x03); +} + +static DECLFW(M133Write) { + if (A & 0x100) { + reg = V; + Sync(); + } +} + +static void M133Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, M133Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper133_Init(CartInfo *info) { + info->Power = M133Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper134.c b/src/mappers/mapper134.c new file mode 100644 index 000000000..09ca3975a --- /dev/null +++ b/src/mappers/mapper134.c @@ -0,0 +1,112 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Chipset used on various PCBs named WX-KB4K, T4A54A, BS-5652... */ +/* "Rockman 3" on YH-322 and "King of Fighters 97" on "Super 6-in-1" enable interrupts without initializing the frame IRQ register and therefore freeze on real hardware. + They can run if another game is selected that does initialize the frame IRQ register, then soft-resetting to the menu and selecting the previously-freezing games. */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M134PW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x04) ? 0x0F : 0x1F; + uint16 base = ((reg[1] << 4) & 0x30) | ((reg[0] << 2) & 0x40); + + if (reg[1] & 0x80) { /* NROM mode */ + if (reg[1] & 0x08) { /* NROM-128 mode */ + setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~1) | 0); + setprg8(0xA000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~1) | 1); + setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~1) | 0); + setprg8(0xE000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~1) | 1); + } else { /* NROM-256 mode */ + setprg8(0x8000, (base & ~mask) | (((mmc3.reg[6] & ~0x02) & mask) & ~1) | 0); + setprg8(0xA000, (base & ~mask) | (((mmc3.reg[6] & ~0x02) & mask) & ~1) | 1); + setprg8(0xC000, (base & ~mask) | (((mmc3.reg[6] | 0x02) & mask) & ~1) | 0); + setprg8(0xE000, (base & ~mask) | (((mmc3.reg[6] | 0x02) & mask) & ~1) | 1); + } + } else { /* MMC3 */ + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static void M134CW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x40) ? 0x7F : 0xFF; + uint16 base = ((reg[1] << 3) & 0x180) | ((reg[0] << 4) & 0x200); + + if (reg[0] & 0x08) { /* In CNROM mode, outer bank register 2 replaces the MMC3's CHR registers, and CHR A10-A12 are PPU A10-A12. */ + setchr8(((base & ~mask) >> 3) | (reg[2] & (mask >> 3))); + } else { + setchr1(A, (base & ~mask) | (V & mask)); + } +} + +static DECLFR(M134Read) { + if (reg[0] & 0x40) { + return dipsw; + } + return CartBR(A); +} + +static DECLFW(M134Write) { + if (MMC3_WramIsWritable()) { + CartBW(A, V); + if (!(reg[0] & 0x80)) { + reg[A & 0x03] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } else if ((A & 0x03) == 2) { + reg[2] = (reg[2] & ~0x03) | (V & 0x03); + MMC3_FixCHR(); + } + } +} + +static void M134Reset(void) { + dipsw++; + dipsw &= 15; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Reset(); +} + +static void M134Power(void) { + dipsw = 0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M134Write); + SetReadHandler(0x8000, 0xFFFF, M134Read); +} + +void Mapper134_Init(CartInfo *info) { + MMC3_Init(info, info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) / 1024 : 8, info->battery); + MMC3_cwrap = M134CW; + MMC3_pwrap = M134PW; + info->Power = M134Power; + info->Reset = M134Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper136.c b/src/mappers/mapper136.c new file mode 100644 index 000000000..a7db207e1 --- /dev/null +++ b/src/mappers/mapper136.c @@ -0,0 +1,48 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "jv001.h" + +static void M136Sync(void) { + setprg32(0x8000, (jv001.output >> 4) & 0x01); + setchr8(jv001.output & 0x07); +} + +static DECLFW(M136Write) { + JV001_Write(A, V & 0x3F); +} + +static DECLFR(M136Read) { + return ((CPU_OPENBUS & 0xC0) | (JV001_Read(A) & 0x3F)); +} + +static void M136Power(void) { + JV001_Power(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M136Read); + SetWriteHandler(0x4100, 0xFFFF, M136Write); +} + +void Mapper136_Init(CartInfo *info) { + JV001_Init(info, M136Sync); + info->Power = M136Power; +} diff --git a/src/mappers/mapper137.c b/src/mappers/mapper137.c new file mode 100644 index 000000000..a1def8670 --- /dev/null +++ b/src/mappers/mapper137.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 137 - Sachen 8259D */ + +#include "mapinc.h" + +static uint8 cmd; +static uint8 reg[8]; + +static SFORMAT StateRegs[] = { + { reg, 8, "REGS" }, + { &cmd, 1, "CMD0" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg[5]); + setchr1(0x0000, (reg[0] & 0x07)); + setchr1(0x0400, ((reg[4] << 4) & 0x10) | (reg[(reg[7] & 0x01) ? 0 : 1] & 0x07)); + setchr1(0x0800, ((reg[4] << 3) & 0x10) | (reg[(reg[7] & 0x01) ? 0 : 2] & 0x07)); + setchr1(0x0C00, ((reg[4] << 2) & 0x10) | ((reg[6] << 3) & 0x08) | (reg[(reg[7] & 0x01) ? 0 : 3] & 0x07)); + setchr4(0x1000, ~0); + switch (reg[7] & 0x07) { + default: setmirror(MI_H); break; + case 2: setmirror(MI_V); break; + case 4: setmirrorw(0, 0, 0, 1); break; + case 6: setmirror(MI_0); break; + } +} + +static DECLFW(M137Write) { + if ((A & 0x4000) && (A & 0x100)) { + if (A & 0x01) { + reg[cmd & 0x07] = V; + Sync(); + } else { + cmd = V; + } + } +} + +static void M137Reset(void) { + cmd = 0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + reg[4] = reg[5] = reg[6] = reg[7] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0xFFFF, M137Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper137_Init(CartInfo *info) { + info->Power = M137Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper138.c b/src/mappers/mapper138.c new file mode 100644 index 000000000..bf8c45ee5 --- /dev/null +++ b/src/mappers/mapper138.c @@ -0,0 +1,76 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 138 - Sachen 8259B */ + +#include "mapinc.h" + +static uint8 cmd; +static uint8 reg[8]; + +static SFORMAT StateRegs[] = { + { reg, 8, "REGS" }, + { &cmd, 1, "CMD0" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg[5]); + setchr2(0x0000, ((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 0] & 0x07))); + setchr2(0x0800, ((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 1] & 0x07))); + setchr2(0x1000, ((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 2] & 0x07))); + setchr2(0x1800, ((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 3] & 0x07))); + switch (reg[7] & 0x07) { + case 0: setmirrorw(0, 0, 0, 1); break; + case 2: setmirror(MI_H); break; + default: setmirror(MI_V); break; + case 6: setmirror(MI_0); break; + } +} + +static DECLFW(M138Write) { + if ((A & 0x4000) && (A & 0x100)) { + if (A & 0x01) { + reg[cmd & 0x07] = V; + Sync(); + } else { + cmd = V; + } + } +} + +static void M138Reset(void) { + cmd = 0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + reg[4] = reg[5] = reg[6] = reg[7] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0xFFFF, M138Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper138_Init(CartInfo *info) { + info->Power = M138Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper139.c b/src/mappers/mapper139.c new file mode 100644 index 000000000..490fc999b --- /dev/null +++ b/src/mappers/mapper139.c @@ -0,0 +1,76 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 139 - Sachen 8259C */ + +#include "mapinc.h" + +static uint8 cmd; +static uint8 reg[8]; + +static SFORMAT StateRegs[] = { + { reg, 8, "REGS" }, + { &cmd, 1, "CMD0" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg[5]); + setchr2(0x0000, ((((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 0] & 0x07)) << 2) | 0)); + setchr2(0x0800, ((((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 1] & 0x07)) << 2) | 1)); + setchr2(0x1000, ((((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 2] & 0x07)) << 2) | 2)); + setchr2(0x1800, ((((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 3] & 0x07)) << 2) | 3)); + switch (reg[7] & 0x07) { + case 0: setmirrorw(0, 0, 0, 1); break; + case 2: setmirror(MI_H); break; + default: setmirror(MI_V); break; + case 6: setmirror(MI_0); break; + } +} + +static DECLFW(M139Write) { + if ((A & 0x4000) && (A & 0x100)) { + if (A & 0x01) { + reg[cmd & 0x07] = V; + Sync(); + } else { + cmd = V; + } + } +} + +static void M139Reset(void) { + cmd = 0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + reg[4] = reg[5] = reg[6] = reg[7] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0xFFFF, M139Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper139_Init(CartInfo *info) { + info->Power = M139Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper140.c b/src/mappers/mapper140.c new file mode 100644 index 000000000..18c54929e --- /dev/null +++ b/src/mappers/mapper140.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg >> 4); + setchr8(reg & 0x0F); +} + +static DECLFW(M140Write) { + reg = V; + Sync(); +} + +static void M140Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M140Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper140_Init(CartInfo *info) { + info->Power = M140Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper141.c b/src/mappers/mapper141.c new file mode 100644 index 000000000..8a271b7b3 --- /dev/null +++ b/src/mappers/mapper141.c @@ -0,0 +1,80 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 141 - Sachen 8259A */ + +#include "mapinc.h" + +static uint8 cmd; +static uint8 reg[8]; + +static SFORMAT StateRegs[] = { + { reg, 8, "REGS" }, + { &cmd, 1, "CMD0" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg[5]); + if (!CHR_ROM_SIZE_8K) { + setchr8(0); + } else { + setchr2(0x0000, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 0] & 0x07)) << 1) | 0); + setchr2(0x0800, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 1] & 0x07)) << 1) | 1); + setchr2(0x1000, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 2] & 0x07)) << 1) | 0); + setchr2(0x1800, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 3] & 0x07)) << 1) | 1); + } + switch (reg[7] & 0x07) { + case 0: setmirrorw(0, 0, 0, 1); break; + case 2: setmirror(MI_H); break; + default: setmirror(MI_V); break; + case 6: setmirror(MI_0); break; + } +} + +static DECLFW(M141Write) { + if ((A & 0x4000) && (A & 0x100)) { + if (A & 0x01) { + reg[cmd & 0x07] = V; + Sync(); + } else { + cmd = V; + } + } +} + +static void M141Reset(void) { + cmd = 0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + reg[4] = reg[5] = reg[6] = reg[7] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0xFFFF, M141Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper141_Init(CartInfo *info) { + info->Power = M141Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper142.c b/src/mappers/mapper142.c new file mode 100644 index 000000000..55b519d9d --- /dev/null +++ b/src/mappers/mapper142.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 142 - UNL KS7032 */ + + #include "mapinc.h" + #include "ks202.h" + + static void Sync(void) { + setprg8(0x6000, ks202.reg[4] & 0x0F); + setprg8(0x8000, ks202.reg[1] & 0x0F); + setprg8(0xA000, ks202.reg[2] & 0x0F); + setprg8(0xC000, ks202.reg[3] & 0x0F); + setprg8(0xE000, ~0 & 0x0F); + setchr8(0); +} + +void Mapper142_Init(CartInfo *info) { + KS202_Init(info, Sync, 0, 0); +} diff --git a/src/mappers/mapper143.c b/src/mappers/mapper143.c new file mode 100644 index 000000000..2f724de3c --- /dev/null +++ b/src/mappers/mapper143.c @@ -0,0 +1,41 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 143 - TC-A01 */ + +#include "mapinc.h" + +static DECLFR(M143Read) { + if ((A & 0x100) == 0x100) { + return (CPU_OPENBUS & 0xC0) | ((~A) & 0x3F); + } + return CPU_OPENBUS; +} + +static void M143Power(void) { + setprg32(0x8000, 0); + setchr8(0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M143Read); +} + +void Mapper143_Init(CartInfo *info) { + info->Power = M143Power; +} diff --git a/src/mappers/mapper144.c b/src/mappers/mapper144.c new file mode 100644 index 000000000..982c0bee6 --- /dev/null +++ b/src/mappers/mapper144.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.data); + setchr8(latch.data >> 4); +} + +static DECLFW(M144Write) { + uint8 reg = CartBR(A); + latch.data = reg & ((V & reg) | 0x01); + Sync(); +} + +static void M144Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M144Write); +} + +void Mapper144_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Power = M144Power; +} diff --git a/src/mappers/mapper145.c b/src/mappers/mapper145.c new file mode 100644 index 000000000..ecad0f046 --- /dev/null +++ b/src/mappers/mapper145.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 145 - Sachen SA-72007 */ + +#include "mapinc.h" + +static uint8 reg = 0; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8(reg >> 7); +} + +static DECLFW(M145Write) { + if (A & 0x100) { + reg = V; + Sync(); + } +} + +static void M145Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, M145Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper145_Init(CartInfo *info) { + info->Power = M145Power; + GameStateRestore = StateRestore; + AddExState(®, 1, 0, "REG0"); +} diff --git a/src/mappers/mapper147.c b/src/mappers/mapper147.c new file mode 100644 index 000000000..94900d3b1 --- /dev/null +++ b/src/mappers/mapper147.c @@ -0,0 +1,49 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "jv001.h" + +static void M147Sync(void) { + setprg32(0x8000, ((jv001.output >> 4) & 0x02) | (jv001.output & 0x01)); + setchr8((jv001.output >> 1) & 0x0F); +} + +static DECLFW(M147Write) { + JV001_Write(A, ((V >> 2) & 0x3F) | ((V << 6) & 0xC0)); +} + +static DECLFR(M147Read) { + uint8 ret = JV001_Read(A); + return ((ret << 2) | ((ret >> 6) & 0x03)); +} + +static void M147Power(void) { + JV001_Power(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M147Read); + SetWriteHandler(0x4100, 0xFFFF, M147Write); +} + +void Mapper147_Init(CartInfo *info) { + JV001_Init(info, M147Sync); + info->Power = M147Power; +} diff --git a/src/mappers/mapper148.c b/src/mappers/mapper148.c new file mode 100644 index 000000000..31bd13291 --- /dev/null +++ b/src/mappers/mapper148.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 148 - Sachen SA-008-A and Tengen 800008 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, (latch.data >> 3) & 0x01); + setchr8(latch.data & 0x07); +} + +void Mapper148_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper149.c b/src/mappers/mapper149.c new file mode 100644 index 000000000..59db1366f --- /dev/null +++ b/src/mappers/mapper149.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 149 - Sachen SA-0036 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8(latch.data >> 7); +} + +void Mapper149_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper150.c b/src/mappers/mapper150.c new file mode 100644 index 000000000..14fac6e67 --- /dev/null +++ b/src/mappers/mapper150.c @@ -0,0 +1,102 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 150 - SA-015 / SA-630 / Unif UNL-Sachen-74LS374N */ +/* Mapper 243 - SA-020A */ + +#include "mapinc.h" + +static uint8 dipsw; +static uint8 cmd; +static uint8 reg[8]; + +static SFORMAT StateRegs[] = { + { reg, 8, "REGS" }, + { &dipsw, 1, "DPSW" }, + { &cmd, 1, "CMD0" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg[2] & 0x01) | reg[5]); + if (iNESCart.mapper == 243) { + setchr8((reg[2] & 0x01) | ((reg[4] << 1) & 0x02) | (reg[6] << 2)); + } else { + setchr8((reg[6] & 0x03) | ((reg[4] << 2) & 0x04) | (reg[2] << 3)); + } + switch ((reg[7] >> 1) & 0x03) { + case 0: setmirrorw(0, 1, 1, 1); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_0); break; + } +} + +static DECLFR(M150Read) { + if ((A & 0x101) == 0x101) { + if (dipsw & 1) + return (reg[cmd] & 0x03) | (CPU_OPENBUS & 0xFC); + else + return (reg[cmd] & 0x07) | (CPU_OPENBUS & 0xF8); + } + return CPU_OPENBUS; +} + +static DECLFW(M150Write) { + if (dipsw & 0x01) + V |= 0x04; + switch (A & 0x101) { + case 0x100: + cmd = V & 0x07; + break; + case 0x101: + reg[cmd] = V & 0x07; + Sync(); + break; + } +} + +static void M150Restore(int version) { + Sync(); +} + +static void M150Reset(void) { + dipsw ^= 0x01; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + reg[4] = reg[5] = reg[6] = reg[7] = 0; + Sync(); +} + +static void M150Power(void) { + dipsw = 0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + reg[4] = reg[5] = reg[6] = reg[7] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M150Read); + SetWriteHandler(0x4100, 0x5FFF, M150Write); +} + +void Mapper150_Init(CartInfo *info) { + info->Power = M150Power; + info->Reset = M150Reset; + GameStateRestore = M150Restore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper152.c b/src/mappers/mapper152.c new file mode 100644 index 000000000..4f251843a --- /dev/null +++ b/src/mappers/mapper152.c @@ -0,0 +1,34 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.data >> 4); + setprg16(0xc000, ~0); + setchr8(latch.data & 0x0F); + setmirror(MI_0 + ((latch.data >> 7) & 0x01)); /* Saint Seiya...hmm. */ +} + +void Mapper152_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper153.c b/src/mappers/mapper153.c new file mode 100644 index 000000000..9eb432e90 --- /dev/null +++ b/src/mappers/mapper153.c @@ -0,0 +1,91 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "eeprom_x24c0x.h" +#include "bandai.h" + +static uint8 outer; + +/* Famicom jump 2: + * 0-7: Lower bit of data selects which 256KB PRG block is in use. + * This seems to be a hack on the developers' part, so I'll make emulation + * of it a hack(I think the current PRG block would depend on whatever the + * lowest bit of the CHR bank switching register that corresponds to the + * last CHR address read). + */ + +static SFORMAT StateRegs[] = { + { &outer, 1, "OUTB" }, + { 0 } +}; + +static void M153PW(uint16 A, uint16 V) { + setprg16(A, ((outer << 4) & 0x10) | (V & 0x0F)); +} + +static void M153CW(uint16 A, uint16 V) { + setchr8(0); +} + +static DECLFW(M153Write) { + if ((A & 0x0F) <= 0x03) { + outer = V; + BANDAI_FixPRG(); + } + BANDAI_Write(A, V); +} + +static void M153Power(void) { + BANDAI_Power(); + SetWriteHandler(0x8000, 0xFFFF, M153Write); + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } +} + +static void M153Close(void) { +} + +void Mapper153_Init(CartInfo *info) { + BANDAI_Init(info, EEPROM_NONE, FALSE); + info->Power = M153Power; + info->Close = M153Close; + BANDAI_pwrap = M153PW; + BANDAI_cwrap = M153CW; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } +} diff --git a/src/mappers/mapper154.c b/src/mappers/mapper154.c new file mode 100644 index 000000000..f3f8fc3a5 --- /dev/null +++ b/src/mappers/mapper154.c @@ -0,0 +1,73 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 154 It is identical to Mapper 88, but with the addition of a single bit allowing for mapper-controlled one-screen regoring: */ + +#include "mapinc.h" +#include "n118.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M154Mirroring(void) { + setmirror(MI_0 + ((reg >> 6) & 0x01)); +} + +static void M154FixCHR(void) { + setchr2(0x0000, (n118.reg[0] & 0x3F) >> 1); + setchr2(0x0800, (n118.reg[1] & 0x3F) >> 1); + setchr1(0x1000, 0x40 | (n118.reg[2] & 0x3F)); + setchr1(0x1400, 0x40 | (n118.reg[3] & 0x3F)); + setchr1(0x1800, 0x40 | (n118.reg[4] & 0x3F)); + setchr1(0x1C00, 0x40 | (n118.reg[5] & 0x3F)); +} + +static DECLFW(M154Write) { + if (A < 0xA000) { + N118_Write(A, V); + } + reg = V; /* mirroring latch */ + M154Mirroring(); +} + +static void M154Power(void) { + reg = 0; + N118_Power(); + SetWriteHandler(0x8000, 0xFFFF, M154Write); +} + +static void StateRestore(int version) { + N118_FixPRG(); + N118_FixCHR(); + M154Mirroring(); +} + +void Mapper154_Init(CartInfo *info) { + N118_Init(info, 0, 0); + info->Power = M154Power; + N118_FixCHR = M154FixCHR; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper155.c b/src/mappers/mapper155.c new file mode 100644 index 000000000..16a9906bb --- /dev/null +++ b/src/mappers/mapper155.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc1.h" + +static void M155PW(uint16 A, uint16 V) { + setprg16(A, (MMC1_GetCHRBank(0) & 0x10) | (V & 0x0F)); +} + +/* Same as mapper 1, without respect for WRAM enable bit. */ +void Mapper155_Init(CartInfo *info) { + MMC1_Init(info, 8, info->battery ? 8 : 0); + MMC1_pwrap = M155PW; + mmc1_type = MMC1A; +} diff --git a/src/mappers/mapper156.c b/src/mappers/mapper156.c new file mode 100644 index 000000000..423d93ff7 --- /dev/null +++ b/src/mappers/mapper156.c @@ -0,0 +1,128 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * DIS23C01 DAOU ROM CONTROLLER, Korea + * Metal Force (K) + * Buzz and Waldog (K) + * General's Son (K) + * + */ + +#include "mapinc.h" + +static uint8 prg, mirr; +static uint16 chr[8]; + +static SFORMAT StateRegs[] = { + { chr, 16, "CREG" }, + { &prg, 1, "PREG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, prg); + setprg16(0xC000, ~0); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + switch (mirr) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + default: setmirror(MI_0); break; + } +} + +static DECLFW(M156Write) { + uint8 index = A & 0x03; + + switch (A & 0xCFFC) { + case 0xC000: + chr[0 | index] = (chr[0 | index] & 0xFF00) | V; + Sync(); + break; + case 0xC004: + chr[0 | index] = (chr[0 | index] & 0x00FF) | V << 8; + Sync(); + break; + case 0xC008: + chr[4 | index] = (chr[4 | index] & 0xFF00) | V; + Sync(); + break; + case 0xC00C: + chr[4 | index] = (chr[4 | index] & 0x00FF) | V << 8; + Sync(); + break; + case 0xC010: + prg = V; + Sync(); + break; + case 0xC014: + mirr = V; + Sync(); + break; + } +} + +static void M156Reset(void) { + int i; + for (i = 0; i < 8; i++) { + chr[i] = 0; + } + prg = 0; + mirr = 2; +} + +static void M156Power(void) { + M156Reset(); + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0xC000, 0xCFFF, M156Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M156Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper156_Init(CartInfo *info) { + info->Reset = M156Reset; + info->Power = M156Power; + info->Close = M156Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper157.c b/src/mappers/mapper157.c new file mode 100644 index 000000000..24d63fa99 --- /dev/null +++ b/src/mappers/mapper157.c @@ -0,0 +1,290 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* FIXME: Bar code input interface not attached yet */ + +#include "mapinc.h" +#include "eeprom_x24c0x.h" +#include "bandai.h" + +/* Datach Barcode Battler */ + +static uint8 BarcodeData[256]; +static int BarcodeReadPos; +static int BarcodeCycleCount; +static uint32 BarcodeOut; + +/* #define INTERL2OF5 */ + +int FCEUI_DatachSet(uint8 *rcode) { + int prefix_parity_type[10][6] = { + { 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1 }, { 0, 0, 1, 1, 0, 1 }, { 0, 0, 1, 1, 1, 0 }, + { 0, 1, 0, 0, 1, 1 }, { 0, 1, 1, 0, 0, 1 }, { 0, 1, 1, 1, 0, 0 }, { 0, 1, 0, 1, 0, 1 }, + { 0, 1, 0, 1, 1, 0 }, { 0, 1, 1, 0, 1, 0 } + }; + int data_left_odd[10][7] = { + { 0, 0, 0, 1, 1, 0, 1 }, { 0, 0, 1, 1, 0, 0, 1 }, { 0, 0, 1, 0, 0, 1, 1 }, { 0, 1, 1, 1, 1, 0, 1 }, + { 0, 1, 0, 0, 0, 1, 1 }, { 0, 1, 1, 0, 0, 0, 1 }, { 0, 1, 0, 1, 1, 1, 1 }, { 0, 1, 1, 1, 0, 1, 1 }, + { 0, 1, 1, 0, 1, 1, 1 }, { 0, 0, 0, 1, 0, 1, 1 } + }; + int data_left_even[10][7] = { + { 0, 1, 0, 0, 1, 1, 1 }, { 0, 1, 1, 0, 0, 1, 1 }, { 0, 0, 1, 1, 0, 1, 1 }, { 0, 1, 0, 0, 0, 0, 1 }, + { 0, 0, 1, 1, 1, 0, 1 }, { 0, 1, 1, 1, 0, 0, 1 }, { 0, 0, 0, 0, 1, 0, 1 }, { 0, 0, 1, 0, 0, 0, 1 }, + { 0, 0, 0, 1, 0, 0, 1 }, { 0, 0, 1, 0, 1, 1, 1 } + }; + int data_right[10][7] = { + { 1, 1, 1, 0, 0, 1, 0 }, { 1, 1, 0, 0, 1, 1, 0 }, { 1, 1, 0, 1, 1, 0, 0 }, { 1, 0, 0, 0, 0, 1, 0 }, + { 1, 0, 1, 1, 1, 0, 0 }, { 1, 0, 0, 1, 1, 1, 0 }, { 1, 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 0, 0 }, + { 1, 0, 0, 1, 0, 0, 0 }, { 1, 1, 1, 0, 1, 0, 0 } + }; + uint8 code[13 + 1]; + uint32 tmp_p = 0; + uint32 csum = 0; + int i, j; + int len; + + for (i = len = 0; i < 13; i++) { + if (!rcode[i]) break; + if ((code[i] = rcode[i] - '0') > 9) + return(0); + len++; + } + if (len != 13 && len != 12 && len != 8 && len != 7) return(0); + + #define BS(x) BarcodeData[tmp_p] = x; tmp_p++ + + for (j = 0; j < 32; j++) { /* delay before sending a code */ + BS(0x00); + } + +#ifdef INTERL2OF5 + + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 cs */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + +#else + /* Left guard bars */ + BS(1); BS(0); BS(1); + + if (len == 13 || len == 12) { + + for (i = 0; i < 6; i++) { + if (prefix_parity_type[code[0]][i]) { + for (j = 0; j < 7; j++) { + BS(data_left_even[code[i + 1]][j]); + } + } else { + for (j = 0; j < 7; j++) { + BS(data_left_odd[code[i + 1]][j]); + } + } + } + + /* Center guard bars */ + BS(0); BS(1); BS(0); BS(1); BS(0); + + for (i = 7; i < 12; i++) { + for (j = 0; j < 7; j++) { + BS(data_right[code[i]][j]); + } + } + /* Calc and write down the control code if not assigned, instead, send code as is + Battle Rush uses modified type of codes with different control code calculation */ + if (len == 12) { + for (i = 0; i < 12; i++) { + csum += code[i] * ((i & 1) ? 3 : 1); + } + csum = (10 - (csum % 10)) % 10; + rcode[12] = csum + 0x30; /* update check code to the input string as well */ + rcode[13] = 0; + code[12] = csum; + } + for (j = 0; j < 7; j++) { + BS(data_right[code[12]][j]); + } + } else if (len == 8 || len == 7) { + for (i = 0; i < 4; i++) { + for (j = 0; j < 7; j++) { + BS(data_left_odd[code[i]][j]); + } + } + + /* Center guard bars */ + BS(0); BS(1); BS(0); BS(1); BS(0); + + for (i = 4; i < 7; i++) { + for (j = 0; j < 7; j++) { + BS(data_right[code[i]][j]); + } + } + csum = 0; + for (i = 0; i < 7; i++) { + csum += (i & 1) ? code[i] : (code[i] * 3); + } + csum = (10 - (csum % 10)) % 10; + rcode[7] = csum + 0x30; /* update check code to the input string as well */ + rcode[8] = 0; + for (j = 0; j < 7; j++) { + BS(data_right[csum][j]); + } + } + + /* Right guard bars */ + BS(1); BS(0); BS(1); +#endif + + for (j = 0; j < 32; j++) { + BS(0x00); + } + + BS(0xFF); + + #undef BS + + BarcodeReadPos = 0; + BarcodeOut = 0x8; + BarcodeCycleCount = 0; + return(1); +} + +static uint8 latch; +static uint8 hasExternalEEPROM = FALSE; +/* first 256K is internal eeprom data, 2nd 256 is for external eeprom if used. + * Combined here for simplicity and frontend save compatibility */ +static uint8 eeprom[512]; + +static void M157PW(uint16 A, uint16 V) { + setprg16(A, V & 0x0F); +} + +static void M157CW(uint16 A, uint16 V) { + setchr8(0); +} + +static DECLFW(M157Write) { + switch (A & 0x0F) { + case 0x00: + if (hasExternalEEPROM) { + latch = (latch & ~0x20) | ((V << 2) & 0x20); + x24c01_write(latch); + } + break; + case 0x0D: + if (hasExternalEEPROM) { + latch = (V & ~0x20) | (latch & 0x20); + x24c01_write(latch); + } + x24c02_write(V); + break; + default: + BANDAI_Write(A, V); + break; + } +} + +static void M157IRQHook(int a) { + BANDAI_IRQHook(a); + + BarcodeCycleCount += a; + if (BarcodeCycleCount >= 1000) { + BarcodeCycleCount -= 1000; + if (BarcodeData[BarcodeReadPos] == 0xFF) { + BarcodeOut = 0; + } else { + BarcodeOut = (BarcodeData[BarcodeReadPos] ^ 1) << 3; + BarcodeReadPos++; + } + } +} + +static DECLFR(M157Read) { + return ((CPU_OPENBUS & 0xE7) | ((x24c02_read() | x24c01_read()) << 4) | BarcodeOut); +} + +static void M157Power(void) { + BANDAI_Reset(); + + BarcodeData[0] = 0xFF; + BarcodeReadPos = 0; + BarcodeOut = 0; + BarcodeCycleCount = 0; + + SetReadHandler(0x6000, 0x7FFF, M157Read); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M157Write); +} + +void Mapper157_Init(CartInfo *info) { + BANDAI_Init(info, EEPROM_NONE, FALSE); + BANDAI_pwrap = M157PW; + BANDAI_cwrap = M157CW; + + info->Power = M157Power; + MapIRQHook = M157IRQHook; + + GameInfo->cspecial = SIS_DATACH; + + /* internal eeprom shared among all games + and always enabled regardless of battery flag */ + info->battery = 1; + x24c02_init(eeprom); + AddExState(&x24c02_StateRegs, ~0, 0, 0); + + if (info->PRGRamSaveSize && info->PRGRamSaveSize <= 128) { + /* additional 128 external eeprom */ + x24c01_init(&eeprom[256]); + AddExState(&x24c01_StateRegs, ~0, 0, 0); + AddExState(&latch, 1, 0, "LATC"); + hasExternalEEPROM = TRUE; + } + + if (hasExternalEEPROM) { + info->SaveGame[0] = eeprom; + info->SaveGameLen[0] = 512; + } else { + info->SaveGame[0] = eeprom; + info->SaveGameLen[0] = 256; + } +} diff --git a/src/mappers/mapper159.c b/src/mappers/mapper159.c new file mode 100644 index 000000000..91d8e0bd1 --- /dev/null +++ b/src/mappers/mapper159.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "eeprom_x24c0x.h" +#include "bandai.h" + +static void M159PW(uint16 A, uint16 V) { + setprg16(A, V & 0x1F); /* map upto 512K PRG for fan translations etc */ +} + +static void M159CW(uint16 A, uint16 V) { + setchr1(A, V); +} + +void Mapper159_Init(CartInfo *info) { + BANDAI_Init(info, EEPROM_X24C01, FALSE); + BANDAI_pwrap = M159PW; + BANDAI_cwrap = M159CW; +} diff --git a/src/mappers/mapper160.c b/src/mappers/mapper160.c new file mode 100644 index 000000000..cbcb3f993 --- /dev/null +++ b/src/mappers/mapper160.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +/* +iNES Mapper 160 appeared to describe variant behavior of iNES Mapper 090, but +Mapper 90 fully encompasses the behavior Mapper 160 was intended to emulate. +*/ + +#if 0 +static uint8 reg = 0; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8(reg & 1); +} + +static DECLFW(SAWrite) { + if (A & 0x100) { + reg = V; + Sync(); + } +} + +static void M160Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, SAWrite); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper160_Init(CartInfo *info) { + GameStateRestore = StateRestore; + info->Power = M160Power; + AddExState(®, 1, 0, "LATC"); +} +#endif \ No newline at end of file diff --git a/src/mappers/mapper162.c b/src/mappers/mapper162.c new file mode 100644 index 000000000..dab0b3bd1 --- /dev/null +++ b/src/mappers/mapper162.c @@ -0,0 +1,108 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2019 Libretro Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Waixing FS304 PCB */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static SFORMAT StateRegs[] = +{ + { reg, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, + (reg[2] << 4) | (reg[0] & 0x0C) /* PRG A17-A20 always normal from $5000 and $5200 */ + | ((reg[3] & 0x04) ? 0x00 : 0x02) /* PRG A16 is 1 if $5300.2=0 */ + | ((reg[3] & 0x04) ? (reg[0] & 0x02) : 0x00) /* PRG A16 is $5000.1 if %5300.2=1 */ + | ((reg[3] & 0x01) ? 0x00 : reg[1] >> 1 & 0x01) /* PRG A15 is $5100.1 if $5300.0=0 */ + | ((~reg[3] & 0x04) && (reg[3] & 0x01) ? 0x01 : 0x00) /* PRG A15 is 1 if $5300.2=0 and $5300.0=1 */ + | ((reg[3] & 0x04) && (reg[3] & 0x01) ? (reg[0] & 0x01) : 0x00) /* PRG A15 is $5000.0 if $5300.2=1 and $5300.0=1 */ + ); + setprg8r(0x10, 0x6000, 0); + if (~reg[0] & 0x80) + setchr8(0); +} + +static void M162HBIRQHook(void) { + if ((reg[0] & 0x80) && + scanline < 239) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on + PA13 rises. This does not seem possible with the current PPU emulation however. */ + setchr4(0x0000, (scanline >= 127) ? 1 : 0); + setchr4(0x1000, (scanline >= 127) ? 1 : 0); + } else + setchr8(0); +} + +static DECLFR(readReg) { + return 0x00; +} + +static DECLFW(writeReg) { + reg[(A >> 8) & 3] = V; + Sync(); +} + +static void M162Power(void) { + memset(reg, 0, sizeof(reg)); + Sync(); + SetReadHandler(0x5000, 0x57FF, readReg); + SetWriteHandler(0x5000, 0x57FF, writeReg); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); +} + +static void M162Reset(void) { + memset(reg, 0, sizeof(reg)); + Sync(); +} + +static void M162Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper162_Init(CartInfo *info) { + info->Power = M162Power; + info->Reset = M162Reset; + info->Close = M162Close; + GameHBIRQHook = M162HBIRQHook; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) : 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } +} diff --git a/src/mappers/mapper163.c b/src/mappers/mapper163.c new file mode 100644 index 000000000..08be1e076 --- /dev/null +++ b/src/mappers/mapper163.c @@ -0,0 +1,114 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2019 Libretro Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Nanjing FC-001 PCB */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg[2] << 4) | (reg[0] & 0x0F) | ((reg[3] & 0x04) ? 0x00 : 0x03)); + setprg8r(0x10, 0x6000, 0); + if (~reg[0] & 0x80) + setchr8(0); +} + +static void M163HBIRQHook(void) { + if ((reg[0] & 0x80) && + (scanline < 239)) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on + PA13 rises. This does not seem possible with the current PPU emulation however. */ + setchr4(0x0000, (scanline >= 127) ? 1 : 0); + setchr4(0x1000, (scanline >= 127) ? 1 : 0); + } else { + setchr8(0); + } +} + +static DECLFR(readReg) { + return ~reg[1] & 0x04; +} + +static DECLFW(writeReg) { + uint8 index = (A >> 8) & 0x03; + + /* Swap bits of registers 0-2 again if the "swap bits" bit is set. Exclude register 2 on when PRG-ROM is 1 MiB. */ + if ((reg[3] & 0x01) && (index <= (PRG_ROM_SIZE_16K < (2024 * 1024)))) { + V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); + } + + if (A & 0x01) { + if ((reg[1] & 0x01) && (~V & 0x01)) { + reg[1] ^= 0x04; /* If A0=1, flip feedback bit on falling edges of D0 */ + } /* If A0=0, write to register */ + } else { + reg[index] = V; + Sync(); + } +} + +static void M163Power(void) { + memset(reg, 0, sizeof(reg)); + Sync(); + SetReadHandler(0x5000, 0x57FF, readReg); + SetWriteHandler(0x5000, 0x57FF, writeReg); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); +} + +static void M163Reset(void) { + memset(reg, 0, sizeof(reg)); + Sync(); +} + +static void M163Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper163_Init(CartInfo *info) { + info->Power = M163Power; + info->Reset = M163Reset; + info->Close = M163Close; + GameHBIRQHook = M163HBIRQHook; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) : 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } +} diff --git a/src/mappers/mapper164.c b/src/mappers/mapper164.c new file mode 100644 index 000000000..7366c2c68 --- /dev/null +++ b/src/mappers/mapper164.c @@ -0,0 +1,146 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Dongda PEC-9588 educational computer. Provides the same 1bpp all-points-addressable graphics mode. + Its chipset was later used for the Yancheng cy2000-3 PCB, used on most of the games that display "Union Bond" at the start. + Some of them also use the 1bpp mode for a few screens! +*/ + +#include "mapinc.h" +#include "eeprom_93Cx6.h" + +static uint8 reg[4]; +static uint8 eeprom_data[512]; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { eeprom_data, 512, "EEPR" }, + { 0 } +}; + +static void Sync(void) { + uint8 prgLow = (reg[0] & 0x0F) | ((reg[0] >> 1) & 0x10); + uint8 prgHigh = reg[1] << 5; + + uint8 mode = ((reg[0] >> 5) & 0x02) | ((reg[0] >> 4) & 0x01); + uint8 mirr = ((reg[0] & 0x10) && !(reg[3] & 0x80)) ? MI_H : MI_V; + + switch (mode) { + case 0: /* UNROM-512 */ + setprg16(0x8000, prgHigh | prgLow); + setprg16(0xC000, prgHigh | 0x1F); + break; + case 1: /* Open Bus on Yancheng cy2000-3 PCB, expansion cartridge on the Dongda PEC-9588 */ + break; + case 2: /* UNROM-448+64. Very strange mode, used for the LOGO program on the Dongda PEC-9588 */ + setprg16(0x8000, prgHigh | prgLow); + setprg16(0xC000, prgHigh | ((prgLow >= 0x1C) ? 0x1C : 0x1E)); + break; + case 3: /* UNROM-128 or BNROM */ + if (prgLow & 0x10) { + setprg16(0x8000, prgHigh | ((prgLow << 1) & 0x10) | (prgLow & 0x0F)); + setprg16(0xC000, prgHigh | ((prgLow << 1) & 0x10) | 0x0F); + } else { + setprg32(0x8000, (prgHigh >> 1) | prgLow); + } + break; + } + + setprg8r(0x10, 0x6000, 0); + + setchr8(0); + PEC586Hack = (reg[0] & 0x80) ? TRUE : FALSE; + + setmirror(mirr); +} + +static DECLFR(readReg) { + return eeprom_93Cx6_read() ? 0x00 : 0x04; +} + +static DECLFW(writeReg) { + switch (A & 0xFF00) { + case 0x5000: + reg[0] = V; + Sync(); + break; + case 0x5100: + reg[1] = V; + Sync(); + break; + case 0x5200: + reg[2] = V; + eeprom_93Cx6_write((reg[2] & 0x10), (reg[2] & 0x04), (reg[2] & 0x01)); + break; + case 0x5300: + reg[3] = V; + Sync(); + break; + } +} + +static void M164Power(void) { + memset(reg, 0, sizeof(reg)); + Sync(); + SetReadHandler(0x5400, 0x57FF, readReg); + SetWriteHandler(0x5000, 0x57FF, writeReg); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M164Reset(void) { + memset(reg, 0, sizeof(reg)); + Sync(); +} + +static void M164Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper164_Init(CartInfo *info) { + info->Power = M164Power; + info->Reset = M164Reset; + info->Close = M164Close; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + if (info->iNES2) { + WRAMSIZE = info->iNES2 ? (info->PRGRamSize + (info->PRGRamSaveSize & ~0x7FF)) : 8192; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + + eeprom_93Cx6_init(eeprom_data, 512, 8); + info->battery = 1; + info->SaveGame[0] = eeprom_data; + info->SaveGameLen[0] = 512; +} diff --git a/src/mappers/mapper165.c b/src/mappers/mapper165.c new file mode 100644 index 000000000..5962a380b --- /dev/null +++ b/src/mappers/mapper165.c @@ -0,0 +1,87 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M165CW(uint16 A, uint16 V) { + if (V == 0) { + setchr4r(0x10, A, 0); + } else { + setchr4(A, V >> 2); + } +} + +static void M165PPUFD(void) { + if (reg == 0xFD) { + M165CW(0x0000, mmc3.reg[0]); + M165CW(0x1000, mmc3.reg[2]); + } +} + +static void M165PPUFE(void) { + if (reg == 0xFE) { + M165CW(0x0000, mmc3.reg[1]); + M165CW(0x1000, mmc3.reg[4]); + } +} + +static void M165CWM(uint16 A, uint16 V) { + if (((mmc3.cmd & 0x7) == 0) || ((mmc3.cmd & 0x7) == 2)) { + M165PPUFD(); + } + if (((mmc3.cmd & 0x7) == 1) || ((mmc3.cmd & 0x7) == 4)) { + M165PPUFE(); + } +} + +static void M165PPU(uint32 A) { + if ((A & 0x1FF0) == 0x1FD0) { + reg = 0xFD; + M165PPUFD(); + } else if ((A & 0x1FF0) == 0x1FE0) { + reg = 0xFE; + M165PPUFE(); + } +} + +static void M165Close(void) { + MMC3_Close(); +} + +static void M165Power(void) { + reg = 0xFD; + MMC3_Power(); +} + +void Mapper165_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + info->Close = M165Close; + MMC3_cwrap = M165CWM; + PPU_hook = M165PPU; + info->Power = M165Power; + CHRRAMSIZE = 4096; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); + AddExState(®, 1, 0, "EXPR"); +} \ No newline at end of file diff --git a/src/mappers/mapper166.c b/src/mappers/mapper166.c new file mode 100644 index 000000000..3ce2b56db --- /dev/null +++ b/src/mappers/mapper166.c @@ -0,0 +1,88 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint16 base = ((reg[0] ^ reg[1]) & 0x10) << 1; + uint16 bank = (reg[2] ^ reg[3]) & 0x1f; + + if (reg[1] & 0x08) { + bank &= 0xFE; + setprg16(0x8000, base + bank + 0); + setprg16(0xC000, base + bank + 1); + } else { + if (reg[1] & 0x04) { + setprg16(0x8000, 0x1F); + setprg16(0xC000, base + bank); + } else { + setprg16(0x8000, base + bank); + setprg16(0xC000, 0x07); + } + } + setchr8(0); +} + +static DECLFW(M166Write) { + reg[(A >> 13) & 0x03] = V; + Sync(); +} + +static void M166Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M166Write); + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper166_Init(CartInfo *info) { + info->Power = M166Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8 * 1024; + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } +} diff --git a/src/mappers/mapper167.c b/src/mappers/mapper167.c new file mode 100644 index 000000000..1cfd7674d --- /dev/null +++ b/src/mappers/mapper167.c @@ -0,0 +1,88 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static SFORMAT StateRegs[] = { + { reg, 4, "DREG" }, + { 0 } +}; + +static void Sync(void) { + uint16 base = ((reg[0] ^ reg[1]) & 0x10) << 1; + uint16 bank = (reg[2] ^ reg[3]) & 0x1f; + + if (reg[1] & 0x08) { + bank &= 0xFE; + setprg16(0x8000, base + bank + 1); + setprg16(0xC000, base + bank + 0); + } else { + if (reg[1] & 0x04) { + setprg16(0x8000, 0x1F); + setprg16(0xC000, base + bank); + } else { + setprg16(0x8000, base + bank); + setprg16(0xC000, 0x20); + } + } + setchr8(0); +} + +static DECLFW(M167Write) { + reg[(A >> 13) & 0x03] = V; + Sync(); +} + +static void M167Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M167Write); + if (WRAMSIZE) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper167_Init(CartInfo *info) { + info->Power = M167Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8 * 1024; + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } +} diff --git a/src/mappers/mapper168.c b/src/mappers/mapper168.c new file mode 100644 index 000000000..aaa98c36a --- /dev/null +++ b/src/mappers/mapper168.c @@ -0,0 +1,75 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * RacerMate Challenge II + * + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setchr4r(0x10, 0x0000, 0); + setchr4r(0x10, 0x1000, reg & 0x0f); + setprg16(0x8000, reg >> 6); + setprg16(0xc000, ~0); +} + +static DECLFW(M168Write) { + reg = V; + Sync(); +} + +static DECLFW(M168Dummy) { } + +static void M168Power(void) { + reg = 0; + Sync(); + SetWriteHandler(0x4020, 0x7fff, M168Dummy); + SetWriteHandler(0xB000, 0xB000, M168Write); + SetWriteHandler(0xF000, 0xF000, M168Dummy); + SetWriteHandler(0xF080, 0xF080, M168Dummy); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void M168Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper168_Init(CartInfo *info) { + info->Power = M168Power; + info->Close = M168Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAMSIZE = 8192 * 8; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); +} diff --git a/src/mappers/mapper170.c b/src/mappers/mapper170.c new file mode 100644 index 000000000..7830e0a47 --- /dev/null +++ b/src/mappers/mapper170.c @@ -0,0 +1,52 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static DECLFW(M170ProtW) { + reg = ((V << 1) & 0x80); +} + +static DECLFR(M170ProtR) { + return (reg | (CPU_OPENBUS & 0x7F)); +} + +static void M170Power(void) { + setprg32(0x8000, 0); + setchr8(0); + SetReadHandler(0x7001, 0x7001, M170ProtR); + SetReadHandler(0x7777, 0x7777, M170ProtR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6502, 0x6502, M170ProtW); + SetWriteHandler(0x7000, 0x7000, M170ProtW); +} + +void Mapper170_Init(CartInfo *info) { + info->Power = M170Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper171.c b/src/mappers/mapper171.c new file mode 100644 index 000000000..cef5c3698 --- /dev/null +++ b/src/mappers/mapper171.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 171 - Kaiser KS-7058 */ + +#include "mapinc.h" + +static uint8 chr[2]; + +static SFORMAT StateRegs[] = { + { chr, 2, "CREG" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr4(0x0000, chr[0]); + setchr4(0x1000, chr[1]); +} + +static DECLFW(M171Write) { + chr[A & 0x01] = V; + Sync(); +} + +static void M171Power(void) { + chr[0] = chr[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M171Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper171_Init(CartInfo *info) { + info->Power = M171Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper172.c b/src/mappers/mapper172.c new file mode 100644 index 000000000..2bdb29e6c --- /dev/null +++ b/src/mappers/mapper172.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "jv001.h" + +static void M172Sync(void) { + setprg32(0x8000, 0); + setchr8(jv001.output); + setmirror((jv001.X & 1) ^ 1); +} + +static uint8 GetVal(uint8 V) { + return (((V << 5) & 0x20) | ((V << 3) & 0x10) | ((V << 1) & 0x08) | ((V >> 1) & 0x04) | + ((V >> 3) & 0x02) | ((V >> 5) & 0x01)); +} + +static DECLFW(M172Write) { + JV001_Write(A, GetVal(V)); +} + +static DECLFR(M172Read) { + return (CPU_OPENBUS & 0xC0) | GetVal(JV001_Read(A)); +} + +static void M172Power(void) { + JV001_Power(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M172Read); + SetWriteHandler(0x4100, 0xFFFF, M172Write); +} + +void Mapper172_Init(CartInfo *info) { + JV001_Init(info, M172Sync); + info->Power = M172Power; +} diff --git a/src/mappers/mapper173.c b/src/mappers/mapper173.c new file mode 100644 index 000000000..cf608d5fd --- /dev/null +++ b/src/mappers/mapper173.c @@ -0,0 +1,52 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "txc.h" + +static void M173Sync(void) { + setprg32(0x8000, 0); + if (CHR_ROM_SIZE_8K >= (16 * 1024)) { + setchr8(((txc.output & 0x01) | (txc.Y ? 0x02 : 0x00) | ((txc.output & 2) << 0x01))); + } else { + setchr8(0); + } +} + +static DECLFW(M173Write) { + TXC_Write(A, V & 0x0F); +} + +static DECLFR(M173Read) { + return ((CPU_OPENBUS & 0xF0) | (TXC_Read(A) & 0x0F)); +} + +static void M173Power(void) { + TXC_Power(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, M173Read); + SetWriteHandler(0x4100, 0xFFFF, M173Write); +} + +void Mapper173_Init(CartInfo *info) { + TXC_Init(info, M173Sync); + info->Power = M173Power; +} diff --git a/src/mappers/mapper174.c b/src/mappers/mapper174.c new file mode 100644 index 000000000..114262eff --- /dev/null +++ b/src/mappers/mapper174.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x80) { + setprg32(0x8000, (latch.addr >> 5) & 0x03); + } else { + setprg16(0x8000, (latch.addr >> 4) & 0x07); + setprg16(0xC000, (latch.addr >> 4) & 0x07); + } + setchr8((latch.addr >> 1) & 0x07); + setmirror((latch.addr & 0x01) ^ 0x01); +} + +void Mapper174_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper175.c b/src/mappers/mapper175.c new file mode 100644 index 000000000..a0f896e7f --- /dev/null +++ b/src/mappers/mapper175.c @@ -0,0 +1,78 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2], mirr; + +static SFORMAT StateRegs[] = { + { reg, 2, "REG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, reg[0]); + setprg16(0xC000, reg[0]); + setchr8(reg[0]); + setmirror(((mirr >> 2) & 0x01) ^ 0x01); +} + +static DECLFR(M175Read) { + switch (A & 0xF000) { + case 0xF000: + if (reg[0] != reg[1]) { + reg[0] = reg[1]; + Sync(); + } + break; + } + return CartBR(A); +} + +static DECLFW(M175Write) { + switch (A & 0xF000) { + case 0x8000: + mirr = V; + Sync(); + break; + case 0xA000: + reg[1] = V; + break; + } +} + +static void M175Power(void) { + reg[0] = reg[1] = mirr = 0; + SetReadHandler(0x8000, 0xFFFF, M175Read); + SetWriteHandler(0x8000, 0xFFFF, M175Write); + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper175_Init(CartInfo *info) { + info->Power = M175Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper176.c b/src/mappers/mapper176.c new file mode 100644 index 000000000..d470b7a91 --- /dev/null +++ b/src/mappers/mapper176.c @@ -0,0 +1,599 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2020 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mappers: + 176 - Standard + 523 - Jncota KT-xxx, re-release of 封神榜꞉ 伏魔三太子: 1 KiB->2 KiB, 2 KiB->4 KiB CHR, hard-wired nametable mirroring) + + Submappers: + 0 - Standard + 1 - FK-xxx + 2 - 外星 FS005/FS006 + 3 - JX9003B + 4 - GameStar Smart Genius Deluxe + 5 - HST-162 + + Verified on real hardware: + "Legend of Kage" sets CNROM latch 1 and switches between CHR bank 0 and 1 using 5FF2, causing the wrong bank (1 instead of 0) during gameplay. + + Heuristic for detecting whether the DIP switch should be changed on every soft reset: + The first write to the $5xxx range is to $501x => ROM always addresses $501x; changing the DIP switch on reset would break the emulation after reset, so don't do it. + The first write to the $5xxx range is to $5020 or higher => ROM either uses a DIP switch or writes to $5FFx for safety; changing the DIP switch on reset is possible. + Exclude the $5FF3 address as well as $5000-$500F from this heuristic. +*/ + +#include "mapinc.h" + +static uint8 fk23_regs[8] = { 0 }; /* JX9003B has eight registers, all others have four */ +static uint8 mmc3_regs[12] = { 0 }; +static uint8 mmc3_ctrl = 0; +static uint8 mmc3_mirr = 0; +static uint8 mmc3_wram = 0; +static uint8 reg4800 = 0; + +static uint8 irq_count = 0; +static uint8 irq_latch = 0; +static uint8 irq_enabled = 0; +static uint8 irq_reload = 0; +static uint8 latch = 0; +static uint8 dipswitch = 0; +static uint8 subType = 0; /* NES 2.0 Submapper, denoting PCB variants */ +static uint8 dipsw_enable = 0; /* Change the address mask on every reset? */ +static uint8 after_power = 0; /* Used for detecting whether a DIP switch is used or not (see above) */ + +static void (*FK23_cwrap)(uint16 A, uint16 V); +static void (*SyncMIRR)(void); + +static SFORMAT StateRegs[] = { + { fk23_regs, 8, "EXPR" }, + { mmc3_regs, 12, "M3RG" }, + { &latch, 1, "LATC" }, + { &dipswitch, 1, "DPSW" }, + { &mmc3_ctrl, 1, "M3CT" }, + { &mmc3_mirr, 1, "M3MR" }, + { &mmc3_wram, 1, "M3WR" }, + { ®4800, 1, "REG4" }, + { &irq_reload, 1, "IRQR" }, + { &irq_count, 1, "IRQC" }, + { &irq_latch, 1, "IRQL" }, + { &irq_enabled, 1, "IRQA" }, + { &subType, 1, "SUBT" }, + { 0 } +}; + +#define INVERT_PRG !!(mmc3_ctrl & 0x40) +#define INVERT_CHR !!(mmc3_ctrl & 0x80) +#define WRAM_ENABLED !!(mmc3_wram & 0x80) +#define WRAM_EXTENDED (!!(mmc3_wram & 0x20) && subType == 2) /* Extended A001 register. Only available on FS005 PCB. */ +#define FK23_ENABLED (!!(mmc3_wram & 0x40) || !WRAM_EXTENDED) /* Enable or disable registers in the $5xxx range. Only available on FS005 PCB. */ +#define PRG_MODE ( fk23_regs[0] & 0x07) +#define MMC3_EXTENDED !!( fk23_regs[3] & 0x02) /* Extended MMC3 mode, adding extra registers for switching the normally-fixed PRG banks C and E and for eight independent 1 KiB CHR banks. Only available on FK- and FS005 PCBs. */ +#define CHR_8K_MODE !!( fk23_regs[0] & 0x40) /* MMC3 CHR registers are ignored, apply outer bank only, and CNROM latch if it exists */ +#define CHR_CNROM_MODE (~fk23_regs[0] & 0x20 && (subType == 1 || subType == 5)) /* Only subtypes 1 and 5 have a CNROM latch, which can be disabled */ +#define CHR_OUTER_BANK_SIZE !!( fk23_regs[0] & 0x10) /* Switch between 256 and 128 KiB CHR, or 32 and 16 KiB CHR in CNROM mode */ +#define CHR_MIXED !!(WRAM_EXTENDED && mmc3_wram &0x04) /* First 8 KiB of CHR address space are RAM, then ROM */ + +static void CHRWRAP(uint16 A, uint16 V) { + uint8 bank = 0; + + /* some workaround for chr rom / ram access */ + if (!CHR_ROM_SIZE_8K) { + /* CHR-RAM only */ + bank = 0; + } else if (CHRRAMSIZE) { + /* Mixed CHR-ROM + CHR-RAM */ + if ((fk23_regs[0] & 0x20) && ((subType == 0) || (subType == 1))) { + bank = 0x10; + } else if (CHR_MIXED && (V < 8)) { + /* first 8K of chr bank is RAM */ + bank = 0x10; + } + } + setchr1r(bank, A, V); +} + +static void SyncCHR(void) { + uint32 outer = fk23_regs[2] | + (subType == 3 ? (fk23_regs[6] << 8) : 0); /* Outer 8 KiB CHR bank. Subtype 3 has an MSB register providing more bits. */ + if (CHR_8K_MODE) { + uint32 mask = (CHR_CNROM_MODE ? (CHR_OUTER_BANK_SIZE ? 0x01 : 0x03) : 0x00); + /* In Submapper 1, address bits come either from outer bank or from latch. In Submapper 5, they are OR'd. Both + * verified on original hardware. */ + uint32 bank = ((subType == 5 ? outer : (outer & ~mask)) | (latch & mask)) << 3; + + FK23_cwrap(0x0000, bank + 0); + FK23_cwrap(0x0400, bank + 1); + FK23_cwrap(0x0800, bank + 2); + FK23_cwrap(0x0C00, bank + 3); + + FK23_cwrap(0x1000, bank + 4); + FK23_cwrap(0x1400, bank + 5); + FK23_cwrap(0x1800, bank + 6); + FK23_cwrap(0x1C00, bank + 7); + } else { + uint32 cbase = (INVERT_CHR ? 0x1000 : 0); + uint32 mask = (CHR_OUTER_BANK_SIZE ? 0x7F : 0xFF); + + outer = (outer << 3) & ~mask; /* From 8 KiB to 1 KiB banks. Address bits are never OR'd; they either come from + the outer bank or from the MMC3. */ + + if (MMC3_EXTENDED) { + FK23_cwrap(cbase ^ 0x0000, (mmc3_regs[0] & mask) | outer); + FK23_cwrap(cbase ^ 0x0400, (mmc3_regs[10] & mask) | outer); + FK23_cwrap(cbase ^ 0x0800, (mmc3_regs[1] & mask) | outer); + FK23_cwrap(cbase ^ 0x0c00, (mmc3_regs[11] & mask) | outer); + + FK23_cwrap(cbase ^ 0x1000, (mmc3_regs[2] & mask) | outer); + FK23_cwrap(cbase ^ 0x1400, (mmc3_regs[3] & mask) | outer); + FK23_cwrap(cbase ^ 0x1800, (mmc3_regs[4] & mask) | outer); + FK23_cwrap(cbase ^ 0x1c00, (mmc3_regs[5] & mask) | outer); + } else { + FK23_cwrap(cbase ^ 0x0000, ((mmc3_regs[0] & 0xFE) & mask) | outer); + FK23_cwrap(cbase ^ 0x0400, ((mmc3_regs[0] | 0x01) & mask) | outer); + FK23_cwrap(cbase ^ 0x0800, ((mmc3_regs[1] & 0xFE) & mask) | outer); + FK23_cwrap(cbase ^ 0x0C00, ((mmc3_regs[1] | 0x01) & mask) | outer); + + FK23_cwrap(cbase ^ 0x1000, (mmc3_regs[2] & mask) | outer); + FK23_cwrap(cbase ^ 0x1400, (mmc3_regs[3] & mask) | outer); + FK23_cwrap(cbase ^ 0x1800, (mmc3_regs[4] & mask) | outer); + FK23_cwrap(cbase ^ 0x1c00, (mmc3_regs[5] & mask) | outer); + } + } +} + +static void SyncPRG(void) { + const static int mask_lut[8] ={ 0x3F, 0x1F, 0x0F, 0x00, 0x00, 0x00, 0x7F, 0xFF}; + uint32 mask = mask_lut[PRG_MODE]; /* For PRG modes 0-2, the mode# decides how many bits of the inner 8 KiB bank are used. This + is greatly relevant to map the correct bank that contains the reset vectors. */ + uint32 prg_base = fk23_regs[1] & 0x7F; /* The bits for the first 2 MiB are the same between all the variants. */ + uint32 cbase = 0; + switch (subType) { + case 1: /* FK-xxx */ + if (PRG_MODE == 0 && MMC3_EXTENDED) { + mask = 0xFF; /* Mode 7 allows the MMC3 to address 2 MiB rather than the usual 512 KiB. */ + } + break; + case 2: /* FS005 */ + prg_base |= ((fk23_regs[0] << 4) & 0x080) | ((fk23_regs[0] << 1) & 0x100) | ((fk23_regs[2] << 3) & 0x600) | + ((fk23_regs[2] << 6) & 0x800); + break; + case 3: /* JX9003B */ + if (PRG_MODE == 0) { + mask = 0xFF; /* Mode 7 allows the MMC3 to address 2 MiB rather than the usual 512 KiB. */ + } + prg_base |= fk23_regs[5] << 7; + break; + case 4: /* GameStar Smart Genius Deluxe */ + prg_base |= (fk23_regs[2] & 0x80); + break; + case 5: /* HST-162 */ + prg_base = (prg_base & 0x1F) | (reg4800 << 5); + break; + } + + switch (PRG_MODE) { + default: + /* 0: MMC3 with 512 KiB addressable */ + /* 1: MMC3 with 256 KiB addressable */ + /* 2: MMC3 with 128 KiB addressable */ + /* 7: MMC3 with 2 MB addressable. Used byc at least on 2 games: + - 最终幻想 2 - 光明篇 (Final Fantasy 2 - Arc of Light) + - 梦幻仙境 - (Fantasy Wonderworld) */ + cbase = (INVERT_PRG ? 0x4000 : 0); + prg_base = (prg_base << 1) & ~mask; /* from 16 to 8 KiB. Address bits are never OR'd; they either come from + the outer bank or from the MMC3. */ + if (MMC3_EXTENDED) { + setprg8(0x8000 ^ cbase, (mmc3_regs[6] & mask) | prg_base); + setprg8(0xA000, (mmc3_regs[7] & mask) | prg_base); + setprg8(0xC000 ^ cbase, (mmc3_regs[8] & mask) | prg_base); + setprg8(0xE000, (mmc3_regs[9] & mask) | prg_base); + } else { + setprg8(0x8000 ^ cbase, (mmc3_regs[6] & mask) | prg_base); + setprg8(0xA000, (mmc3_regs[7] & mask) | prg_base); + setprg8(0xC000 ^ cbase, (0xFE & mask) | prg_base); + setprg8(0xE000, (0xFF & mask) | prg_base); + } + break; + case 3: /* NROM-128 */ + setprg16(0x8000, prg_base); + setprg16(0xC000, prg_base); + break; + case 4: /* NROM-256 */ + setprg32(0x8000, (prg_base >> 1)); + break; + case 5: /* UNROM */ + setprg16(0x8000, (latch & 0x07) | (prg_base & ~0x07)); + setprg16(0xC000, 0x07 | prg_base); + break; + } +} + +static void SyncWRAM(void) { + /* TODO: WRAM Protected mode when not in extended mode */ + if (WRAM_ENABLED || WRAM_EXTENDED) { + if (WRAM_EXTENDED) { + setprg8r(0x10, 0x4000, (mmc3_wram + 1) & 0x03); + setprg8r(0x10, 0x6000, (mmc3_wram + 0) & 0x03); + } else { + setprg8r(0x10, 0x6000, 0); + } + } +} + +static void FixMir(void) { + switch (mmc3_mirr & (subType == 2 ? 0x03 : 0x01)) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +static void Sync(void) { + SyncPRG(); + SyncCHR(); + SyncWRAM(); + SyncMIRR(); +} + +static DECLFW(Write4800) { /* Only used by submapper 5 (HST-162) */ + reg4800 = V; + SyncPRG(); +} + +static DECLFW(Write5000) { + if (after_power && A > 0x5010 && A != 0x5FF3) { /* Ignore writes from $5000-$500F, in particular to $5008, but not $5FF3 */ + after_power = 0; + dipsw_enable = A >= 0x5020; /* The DIP switch change on soft-reset is enabled if the first write after power-on + is not to $501x */ + } + if (FK23_ENABLED && (A & (0x10 << dipswitch))) { + fk23_regs[A & (subType == 3 ? 7 : 3)] = V; + SyncPRG(); + SyncCHR(); + } else { + /* FK23C Registers disabled, $5000-$5FFF maps to the second 4 KiB of the 8 KiB WRAM bank 2 */ + CartBW(A, V); + } +} + +static DECLFW(Write8000) { + uint8 old_ctrl = 0; + uint8 ctrl_mask = 0; + + latch = V; + if (CHR_8K_MODE) { + SyncCHR(); /* CNROM latch updated */ + } + if (PRG_MODE == 5) { + SyncPRG(); /* UNROM latch has been updated */ + } + + switch (A & 0xE001) { + case 0x8000: + if (A & 2) { + return; /* Confirmed on real hardware: writes to 8002 and 8003, or 9FFE and 9FFF, are ignored. Needed + for Dr. Mario on some of the "bouncing ball" multis. */ + } + old_ctrl = mmc3_ctrl; + /* Subtype 2, 8192 or more KiB PRG-ROM, no CHR-ROM: Like Subtype 0, + * but MMC3 registers $46 and $47 swapped. */ + if (subType == 2) { + if (V == 0x46) { + V = 0x47; + } else if (V == 0x47) { + V = 0x46; + } + } + mmc3_ctrl = V; + if (INVERT_PRG != (old_ctrl & 0x40)) { + SyncPRG(); + } + if (INVERT_CHR != (old_ctrl & 0x80)) { + SyncCHR(); + } + break; + case 0x8001: + if (A & 2) { + return; /* Confirmed on real hardware: writes to 8002 and 8003, or 9FFE and 9FFF, are ignored. Needed + for Dr. Mario on some of the "bouncing ball" multis. */ + } + ctrl_mask = MMC3_EXTENDED ? 0x0F : 0x07; + if ((mmc3_ctrl & ctrl_mask) < 12) { + mmc3_regs[mmc3_ctrl & ctrl_mask] = V; + + switch (mmc3_ctrl & ctrl_mask) { + case 6: + case 7: + case 8: + case 9: + SyncPRG(); + break; + default: + SyncCHR(); + break; + } + } + break; + case 0xA000: + mmc3_mirr = V; + SyncMIRR(); + break; + case 0xA001: + /* ignore bits when ram config register is disabled */ + if ((V & 0x20) == 0) { + V &= 0xC0; + } + mmc3_wram = V; + Sync(); + break; + case 0xC000: + irq_latch = V; + break; + case 0xC001: + irq_reload = 1; + break; + case 0xE000: + X6502_IRQEnd(FCEU_IQEXT); + irq_enabled = 0; + break; + case 0xE001: + irq_enabled = 1; + break; + default: + break; + } +} + +static void M176HBIRQHook(void) { + if (!irq_count || irq_reload) { + irq_count = irq_latch; + } else { + irq_count--; + } + if (!irq_count && irq_enabled) { + X6502_IRQBegin(FCEU_IQEXT); + } + irq_reload = 0; +} + +static void RegReset(void) { + fk23_regs[0] = fk23_regs[1] = fk23_regs[2] = fk23_regs[3] = 0; + fk23_regs[4] = fk23_regs[5] = fk23_regs[6] = fk23_regs[7] = 0; + mmc3_regs[0] = 0; + mmc3_regs[1] = 2; + mmc3_regs[2] = 4; + mmc3_regs[3] = 5; + mmc3_regs[4] = 6; + mmc3_regs[5] = 7; + mmc3_regs[6] = 0; + mmc3_regs[7] = 1; + mmc3_regs[8] = ~1; + mmc3_regs[9] = ~0; + mmc3_regs[10] = ~0; + mmc3_regs[11] = ~0; + mmc3_ctrl = mmc3_mirr = irq_count = irq_latch = irq_enabled = 0; + reg4800 = 0; + + if (subType == 2) { + mmc3_wram = 0xC0; + } else { + mmc3_wram = 0x80; + } + + if (subType == 1) { + fk23_regs[1] = ~0; + } + + Sync(); +} + +static void M176Reset(void) { + /* this little hack makes sure that we try all the dip switch settings eventually, if we reset enough */ + if (dipsw_enable) { + dipswitch = (dipswitch + 1) & 7; + FCEU_printf("BMCFK23C dipswitch set to $%04x\n", 0x5000 | 0x10 << dipswitch); + } + + RegReset(); +} + +static void M176Power(void) { + RegReset(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, Write5000); + SetWriteHandler(0x8000, 0xFFFF, Write8000); + + if (subType == 5) { + SetWriteHandler(0x4800, 0x4FFF, Write4800); + } + + if (WRAMSIZE) { + if (subType == 2) { + SetReadHandler(0x5000, 0x5FFF, CartBR); + } + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + } +} + +static void M176Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +static void Init(CartInfo *info) { + /* Setup default function wrappers */ + FK23_cwrap = CHRWRAP; + SyncMIRR = FixMir; + + /* Initialization for iNES and UNIF. subType and dipsw_enable must have been set. */ + info->Power = M176Power; + info->Reset = M176Reset; + info->Close = M176Close; + GameHBIRQHook = M176HBIRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + if (CHRRAMSIZE) { + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + } + + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + if (info->iNES2 && info->PRGRamSaveSize) { + info->SaveGameLen[0] = info->PRGRamSaveSize; + } else { + info->SaveGameLen[0] = WRAMSIZE; + } + } + } +} + +void Mapper176_Init(CartInfo *info) { /* .NES file */ + dipsw_enable = 0; + if (info->iNES2) { + subType = info->submapper; + after_power = subType != 2; /* FS005 never has DIP switches, the others may have one, so use the heuristic. */ + if (CHR_ROM_SIZE_8K) { + CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; + } + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } else { + /* Waixing boards have 32K battery backed wram */ + if (info->battery) { + subType = 2; + after_power = 0; + WRAMSIZE = 32 * 1024; + } else { + /* Always enable WRAM for iNES-headered files */ + WRAMSIZE = 8 * 1024; + + if ((PRG_ROM_SIZE_16K == (1024 * 1024)) && (CHR_ROM_SIZE_8K == (1024 * 1024))) { + subType = 1; + } else if ((PRG_ROM_SIZE_16K == (256 * 1024)) && (CHR_ROM_SIZE_8K == (128 * 1024))) { + subType = 1; + } else if ((PRG_ROM_SIZE_16K == (128 * 1024)) && (CHR_ROM_SIZE_8K == (64 * 1024))) { + subType = 1; + } else if ((PRG_ROM_SIZE_16K >= (8192 * 1024)) && (CHR_ROM_SIZE_8K == (0 * 1024))) { + subType = 2; + } else if ((PRG_ROM_SIZE_16K == (4096 * 1024)) && (CHR_ROM_SIZE_8K == (0 * 1024))) { + subType = 3; + } + + /* Detect heuristically whether the address mask should be changed on every soft reset */ + after_power = 1; + + if (CHRRAMSIZE && !CHR_ROM_SIZE_8K) { + /* FIXME: CHR-RAM is already set in iNES mapper initializer when there is no CHR ROM present */ + /* so avoid reallocation it. */ + CHRRAMSIZE = 0; + } + } + } + Init(info); +} + +/* UNIF FK23C. Also includes mislabelled WAIXING-FS005, recognizable by their PRG-ROM size. */ +void BMCFK23C_Init(CartInfo *info) { + if (CHR_ROM_SIZE_8K) { + /* Rockman I-VI uses mixed chr rom/ram */ + if (PRG_ROM_SIZE_16K == (2048 * 1024) && CHR_ROM_SIZE_8K == (512 * 1024)) { + CHRRAMSIZE = 8 * 1024; + } + } + WRAMSIZE = 8 * 1024; + + dipsw_enable = 0; + after_power = 1; + subType = (PRG_ROM_SIZE_16K >= (4096 * 1024)) ? 2 : (PRG_ROM_SIZE_16K == (64 * 1024) && CHR_ROM_SIZE_8K == (128 * 1024)) ? 1 : 0; + if (subType == 2) { + CHRRAMSIZE = 256 * 1024; + } + + Init(info); +} + + /* UNIF FK23CA. Also includes mislabelled WAIXING-FS005, recognizable by their PRG-ROM size. */ +void BMCFK23CA_Init(CartInfo *info) { + WRAMSIZE = 8 * 1024; + + dipsw_enable = 0; + after_power = 1; + subType = (PRG_ROM_SIZE_16K >= (2048 * 1024)) ? 2 : 1; + if (subType == 2) { + CHRRAMSIZE = 256 * 1024; + } + + Init(info); +} + +/* UNIF BMC-Super24in1SC03 */ +void Super24_Init(CartInfo *info) { + CHRRAMSIZE = 8 * 1024; + dipsw_enable = 0; + after_power = 0; + subType = 0; + Init(info); +} + +/* UNIF WAIXING-FS005 */ +void WAIXINGFS005_Init(CartInfo *info) { + CHRRAMSIZE = 8 * 1024; + WRAMSIZE = 32 * 1024; + dipsw_enable = 0; + after_power = 0; + subType = 2; + Init(info); +} + +static void M523CW(uint16 A, uint16 V) { + if (~A & 0x0400) { + setchr2(A, V); + } +} + +static void M523MIR(void) { + /* Jncota board has hard-wired mirroring */ +} + +/* Jncota board with unusual wiring that turns 1 KiB CHR banks into 2 KiB banks, and has hard-wired nametable mirroring. */ +void Mapper523_Init(CartInfo *info) { /* Jncota Fengshengban */ + WRAMSIZE = 8 * 1024; + dipsw_enable = 0; + after_power = 0; + subType = 1; + + Init(info); + SyncMIRR = M523MIR; + FK23_cwrap = M523CW; +} diff --git a/src/mappers/mapper177.c b/src/mappers/mapper177.c new file mode 100644 index 000000000..936f8ffcc --- /dev/null +++ b/src/mappers/mapper177.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 177 - Oversized BNROM without bus conflict */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, latch.data & 0x1F); + setchr8(0); + setmirror(((latch.data & 0x20) >> 5) ^ 1); +} + +void Mapper177_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper178.c b/src/mappers/mapper178.c new file mode 100644 index 000000000..ae2050e8d --- /dev/null +++ b/src/mappers/mapper178.c @@ -0,0 +1,107 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2013 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * DSOUNDV1/FL-TR8MA boards (32K WRAM, 8/16M), 178 mapper boards (8K WRAM, 4/8M) + * Various Education Cartridges + * + * mapper 551 + * Compared to INES Mapper 178, mirroring is hard-wired, and the chipset's internal CHR-RAM is not used in favor of CHR-ROM. + * + */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint16 base = (reg[1] & 0x07) | (reg[2] << 3); + + if ((reg[0] & 0x02)) { + setprg16(0x8000, base); + setprg16(0xC000, base | ((reg[0] & 0x04) ? 0x06 : 0x07)); + } else { + if (reg[0] & 0x04) { + setprg16(0x8000, base); + setprg16(0xC000, base); + } else { + setprg32(0x8000, base >> 1); + } + } + + if (iNESCart.mapper == 551) { + setprg8r(0x10, 0x6000, 0); + setchr8(reg[3]); + } else { + setchr8(0); + setprg8r(0x10, 0x6000, reg[3] & 3); + setmirror((reg[0] & 1) ^ 1); + } +} + +static DECLFW(M178Write) { + reg[A & 3] = V; +/* FCEU_printf("cmd %04x:%02x\n", A, V); */ + Sync(); +} + +static void M178Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + Sync(); + SetWriteHandler(0x4800, 0x4FFF, M178Write); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M178Reset(void) { + /* Always reset to menu */ + reg[0] = reg[1] = reg[2] = reg[3] = 0; + Sync(); +} + +static void M178Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper178_Init(CartInfo *info) { + info->Power = M178Power; + info->Reset = M178Reset; + info->Close = M178Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } +} diff --git a/src/mappers/mapper180.c b/src/mappers/mapper180.c new file mode 100644 index 000000000..ea396672e --- /dev/null +++ b/src/mappers/mapper180.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, 0); + setprg16(0xC000, latch.data); + setchr8(0); +} + +void Mapper180_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper183.c b/src/mappers/mapper183.c new file mode 100644 index 000000000..95eda4cab --- /dev/null +++ b/src/mappers/mapper183.c @@ -0,0 +1,87 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * iNES mapper 183 + * Gimmick Bootleg (VRC4 mapper) + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 prg[4]; + +static SFORMAT StateRegs[] = { + { prg, 4, "PRG" }, + { 0 } +}; + +static void M183PRG(void) { + setprg8(0x6000, prg[0] & 0x3F); + setprg8(0x8000, prg[1] & 0x3F); + setprg8(0xA000, prg[2] & 0x3F); + setprg8(0xC000, prg[3] & 0x3F); + setprg8(0xE000, (~0) & 0x3F); +} + +static DECLFW(M183Write) { + switch (A & 0xF800) { + case 0x6800: + prg[0] = A; + VRC24_FixPRG(); + break; + case 0x8800: + prg[1] = V; + VRC24_FixPRG(); + break; + case 0xA800: + prg[2] = V; + VRC24_FixPRG(); + break; + case 0xA000: + prg[3] = V; + VRC24_FixPRG(); + break; + case 0x9800: + VRC24_Write(0x9000, V); + break; + case 0x6000: + case 0x7000: + case 0x7800: + case 0x8000: + case 0x9000: + return; + default: + VRC24_Write(A, V); + return; + } +} + +static void M183Power(void) { + VRC24_Power(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, M183Write); +} + +void Mapper183_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x04, 0x08, 0, 1); + info->Power = M183Power; + VRC24_FixPRG = M183PRG; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper184.c b/src/mappers/mapper184.c new file mode 100644 index 000000000..654123182 --- /dev/null +++ b/src/mappers/mapper184.c @@ -0,0 +1,56 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr4(0x0000, reg & 0x0F); + setchr4(0x1000, (reg >> 4) & 0x0F); +} + +static DECLFW(M184Write) { + reg = V; + Sync(); +} + +static void M184Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M184Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper184_Init(CartInfo *info) { + info->Power = M184Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper185.c b/src/mappers/mapper185.c new file mode 100644 index 000000000..e26337c43 --- /dev/null +++ b/src/mappers/mapper185.c @@ -0,0 +1,63 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 *DummyCHR = NULL; + +static void Sync(void) { + /* on off + 1 0x0F, 0xF0 - Bird Week + 2 0x33, 0x00 - B-Wings + 3 0x11, 0x00 - Mighty Bomb Jack + 4 0x22, 0x20 - Sansuu 1 Nen, Sansuu 2 Nen + 5 0xFF, 0x00 - Sansuu 3 Nen + 6 0x21, 0x13 - Spy vs Spy + 7 0x20, 0x21 - Seicross */ + uint8 chrEnable = ( + ((iNESCart.submapper != 4) && ((latch.data & 3) != 0) && (latch.data != 0x13)) || /* 1, 2, 3, 4, 5, 6 */ + ((iNESCart.submapper == 4) && ((latch.data & 1) == 0)) /* 7 */ + ) ? 0 : 0x10; + setprg32(0x8000, 0); + setchr8r(chrEnable, 0); +} + +static void M185Close(void) { + Latch_Close(); + if (DummyCHR) { + FCEU_gfree(DummyCHR); + } + DummyCHR = NULL; +} + +void Mapper185_Init(CartInfo *info) { + int x; + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Close = M185Close; + + DummyCHR = (uint8 *)FCEU_gmalloc(8192); + SetupCartCHRMapping(0x10, DummyCHR, 8192, 0); + for (x = 0; x < 8192; x++) { + DummyCHR[x] = 0xff; + } +} diff --git a/src/mappers/mapper186.c b/src/mappers/mapper186.c new file mode 100644 index 000000000..2c10a1d0b --- /dev/null +++ b/src/mappers/mapper186.c @@ -0,0 +1,95 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Family Study Box by Fukutake Shoten + */ + +#include "mapinc.h" + +static uint8 SWRAM[3072]; +static uint8 reg[4]; + +static SFORMAT StateRegs[] = { + { reg, 4, "DREG" }, + { SWRAM, 3072, "SWRM" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, reg[0] >> 6); + setprg16(0x8000, reg[1]); + setprg16(0xc000, 0); + setchr8(0); +} + +static DECLFW(M186Write) { + if (A & 0x4203) + reg[A & 3] = V; + Sync(); +} + +static DECLFR(M186Read) { + switch (A) { + case 0x4200: + return 0x00; + case 0x4201: + return 0x00; + case 0x4202: + return 0x40; + case 0x4203: + return 0x00; + } + return 0xFF; +} + +static DECLFR(ASWRAM) { + return (SWRAM[A - 0x4400]); +} +static DECLFW(BSWRAM) { + SWRAM[A - 0x4400] = V; +} + +static void M186Power(void) { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, CartBW); + SetReadHandler(0x4200, 0x43FF, M186Read); + SetWriteHandler(0x4200, 0x43FF, M186Write); + SetReadHandler(0x4400, 0x4FFF, ASWRAM); + SetWriteHandler(0x4400, 0x4FFF, BSWRAM); + FCEU_CheatAddRAM(32, 0x6000, WRAM); + reg[0] = reg[1] = reg[2] = reg[3]; + Sync(); +} + +static void M186Close(void) { +} + +static void M186Restore(int version) { + Sync(); +} + +void Mapper186_Init(CartInfo *info) { + info->Power = M186Power; + info->Close = M186Close; + GameStateRestore = M186Restore; + WRAM = (uint8 *)FCEU_gmalloc(32768); + SetupCartPRGMapping(0x10, WRAM, 32768, 1); + AddExState(WRAM, 32768, 0, "WRAM"); + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper187.c b/src/mappers/mapper187.c new file mode 100644 index 000000000..248a48de0 --- /dev/null +++ b/src/mappers/mapper187.c @@ -0,0 +1,78 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * A98402 board, A9711, A9746 similar + * King of Fighters 96, The (Unl), Street Fighter Zero 2 (Unl) + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M187CW(uint16 A, uint16 V) { + if ((A & 0x1000) == ((mmc3.cmd & 0x80) << 5)) { + setchr1(A, V | 0x100); + } else { + setchr1(A, V); + } +} + +static void M187PW(uint16 A, uint16 V) { + if (reg & 0x80) { + uint8 bank = (reg >> 1) & 0x0F; + + if (reg & 0x20) { + setprg32(0x8000, bank >> 1); + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { + setprg8(A, V & 0x3F); + } +} + +static DECLFW(M187Write) { + if (!(A & 0x01)) { + reg = V; + MMC3_FixPRG(); + } +} + +static DECLFR(M187Read) { + return CPU_OPENBUS | 0x80; +} + +static void M187Power(void) { + reg = 0; + MMC3_Power(); + SetReadHandler(0x5000, 0x5FFF, M187Read); + SetWriteHandler(0x5000, 0x5FFF, M187Write); +} + +void Mapper187_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M187PW; + MMC3_cwrap = M187CW; + info->Power = M187Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper188.c b/src/mappers/mapper188.c new file mode 100644 index 000000000..95d1fbc5f --- /dev/null +++ b/src/mappers/mapper188.c @@ -0,0 +1,47 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.data & 0x10) { + setprg16(0x8000, (latch.data & 0x07)); + } else { + setprg16(0x8000, (0x08 | latch.data)); + } + setprg16(0xC000, 0x07); + setchr8(0); +} + +static DECLFR(ExtDev) { + return(3); +} + +static void M118Power(void) { + Latch_Power(); + SetReadHandler(0x6000, 0x7FFF, ExtDev); +} + +void Mapper188_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M118Power; +} diff --git a/src/mappers/mapper189.c b/src/mappers/mapper189.c new file mode 100644 index 000000000..85b9fe4af --- /dev/null +++ b/src/mappers/mapper189.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M189PW(uint16 A, uint16 V) { + setprg32(0x8000, reg | (reg >> 4)); +} + +static DECLFW(M189Write4) { + if (A & 0x100) { + reg = V; + MMC3_FixPRG(); + } +} + +static DECLFW(M189Write6) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + } +} + +static void M189Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x4120, 0x5FFF, M189Write4); + SetWriteHandler(0x6000, 0x7FFF, M189Write6); +} + +void Mapper189_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M189PW; + info->Power = M189Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper190.c b/src/mappers/mapper190.c new file mode 100644 index 000000000..d66e546ae --- /dev/null +++ b/src/mappers/mapper190.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2017 FCEUX Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Magic Kid GooGoo + */ + +#include "mapinc.h" + +static uint8 prg, chr[4]; + +static SFORMAT StateRegs[] = { + { &prg, 1, "PREG" }, + { chr, 4, "CREG" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, prg); + setprg16(0xC000, 0); + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr2(0x1000, chr[2]); + setchr2(0x1800, chr[3]); +} + +static DECLFW(M190Write) { + switch (A & 0xE000) { + case 0x8000: + case 0xC000: + prg = (A << 11) | (V & 0x07); + Sync(); + break; + case 0xA000: + chr[A & 0x03] = V; + Sync(); + break; + } +} + +static void M190Power(void) { + chr[0] = chr[1] = chr[2] = chr[3] = 0; + prg = 0; + setmirror(MI_V); + Sync(); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M190Write); + FCEU_CheatAddRAM(0x2000 >> 10, 0x6000, WRAM); +} + +static void M190Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper190_Init(CartInfo *info) { + info->Power = M190Power; + info->Close = M190Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAM = (uint8 *)FCEU_gmalloc(0x2000); + SetupCartPRGMapping(0x10, WRAM, 0x2000, 1); + AddExState(WRAM, 0x2000, 0, "WRAM"); +} diff --git a/src/mappers/mapper191.c b/src/mappers/mapper191.c new file mode 100644 index 000000000..7492bb6ea --- /dev/null +++ b/src/mappers/mapper191.c @@ -0,0 +1,45 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M191CW(uint16 A, uint16 V) { + if (V & 0x80) { + setchr1r(0x10, A, V & 0x01); + } else { + setchr1(A, V); + } +} + +static void M191Close(void) { + MMC3_Close(); +} + +void Mapper191_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + info->Close = M191Close; + MMC3_cwrap = M191CW; + + CHRRAMSIZE = 2048; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} \ No newline at end of file diff --git a/src/mappers/mapper192.c b/src/mappers/mapper192.c new file mode 100644 index 000000000..97b476343 --- /dev/null +++ b/src/mappers/mapper192.c @@ -0,0 +1,46 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M192CW(uint16 A, uint16 V) { + if ((V & ~0x03) == 0x08) { + setchr1r(0x10, A, V & 0x03); + } else { + setchr1(A, V); + } +} + +static void M192Close(void) { + MMC3_Close(); +} + +void Mapper192_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + info->Close = M192Close; + MMC3_cwrap = M192CW; + + CHRRAMSIZE = 4096; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} + diff --git a/src/mappers/mapper193.c b/src/mappers/mapper193.c new file mode 100644 index 000000000..2f279731d --- /dev/null +++ b/src/mappers/mapper193.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * MEGA-SOFT WAR IN THE GULF + * + */ + +#include "mapinc.h" + +static uint8 reg[8]; +static uint8 mirror; + +static SFORMAT StateRegs[] = { + { &mirror, 1, "MIRR" }, + { reg, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, reg[3]); + setprg8(0xA000, ~2); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + setchr4(0x0000, reg[0] >> 2); + setchr2(0x1000, reg[1] >> 1); + setchr2(0x1800, reg[2] >> 1); + setmirror((mirror & 0x01) ^ 0x01); +} + +static DECLFW(M193Write) { + reg[A & 7] = V; + Sync(); +} + +static void M193Power(void) { + memset(reg, 0, sizeof(reg)); + Sync(); + SetWriteHandler(0x6000, 0x7FFF, M193Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, CartBW); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper193_Init(CartInfo *info) { + info->Power = M193Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper194.c b/src/mappers/mapper194.c new file mode 100644 index 000000000..f9ce0a4df --- /dev/null +++ b/src/mappers/mapper194.c @@ -0,0 +1,45 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M194CW(uint16 A, uint16 V) { + if ((V & ~0x01) == 0x00) { /* Dai-2-Ji - Super Robot Taisen (As).nes */ + setchr1r(0x10, A, V & 0x01); + } else { + setchr1(A, V); + } +} + +static void M194Close(void) { + MMC3_Close(); +} + +void Mapper194_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + info->Close = M194Close; + MMC3_cwrap = M194CW; + + CHRRAMSIZE = 2048; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} \ No newline at end of file diff --git a/src/mappers/mapper195.c b/src/mappers/mapper195.c new file mode 100644 index 000000000..2b76644e4 --- /dev/null +++ b/src/mappers/mapper195.c @@ -0,0 +1,103 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 chrRamMask; +static uint8 chrRamBankSelect; + +static writefunc writePPU; +extern uint32 RefreshAddr; + +static void M195CW(uint16 A, uint16 V) { + if ((V & chrRamMask) == chrRamBankSelect) { + setchr1r(0x10, A, V); + } else { + setchr1(A, V); + } +} + +static const uint8 chrRamLut[8] = { + 0x28, 0x00, 0x4C, 0x64, 0x46, 0x7C, 0x04, 0xFF, +}; + +static DECLFW(M195PPUWrite) { + if (RefreshAddr < 0x2000) { + uint8 reg, chrBank; + uint32 addr = RefreshAddr; + + if (mmc3.cmd & 0x80) { + addr ^= 0x1000; + } + if (addr & 0x1000) { + reg = (addr >> 10) - 2; + } else { + reg = addr >> 11; + } + + chrBank = mmc3.reg[reg]; + if (chrBank & 0x80) { + if (chrBank & 0x10) { + /* CHR-RAM disable */ + chrRamMask = 0x00; + chrRamBankSelect = 0xFF; + } else { + uint8 index = ((chrBank >> 4) & 0x04) | ((chrBank >> 2) & 0x02) | ((chrBank >> 1) & 0x01); + + chrRamMask = (chrBank & 0x40) ? 0xFE : 0xFC; + chrRamBankSelect = chrRamLut[index]; + } + MMC3_FixCHR(); + } + } + writePPU(A, V); +} + +static void M195Power(void) { + chrRamMask = 0xFC; + chrRamBankSelect = 0x00; + MMC3_Power(); + setprg4r(0x10, 0x5000, 2); + SetWriteHandler(0x5000, 0x5FFF, CartBW); + SetReadHandler(0x5000, 0x5FFF, CartBR); + + writePPU = GetWriteHandler(0x2007); + SetWriteHandler(0x2007, 0x2007, M195PPUWrite); +} + +static void M195Close(void) { + MMC3_Close(); +} + +void Mapper195_Init(CartInfo *info) { + MMC3_Init(info, 16, info->battery); + info->Power = M195Power; + info->Close = M195Close; + MMC3_cwrap = M195CW; + + CHRRAMSIZE = 4096; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); + + AddExState(&chrRamMask, 1, 0, "CHRM"); + AddExState(&chrRamBankSelect, 1, 0, "CHRB"); +} diff --git a/src/mappers/mapper196.c b/src/mappers/mapper196.c new file mode 100644 index 000000000..bbd378b79 --- /dev/null +++ b/src/mappers/mapper196.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +/* MMC3 board with optional command address line connection, allows to + * make three-four different wirings to IRQ address lines and separately to + * CMD address line, Mali Boss additionally check if wiring are correct for + * game + */ + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void M196PW(uint16 A, uint16 V) { + if (reg[0]) { + setprg32(0x8000, reg[1]); + } else { + setprg8(A, V); + } +} + +static DECLFW(M196Write) { + A = (A & 0xF000) | (!!(A & 0x0E) ^ (A & 0x01)); + MMC3_Write(A, V); +} + +static DECLFW(M196WriteNROM) { + reg[0] = 1; + reg[1] = V | (V >> 4); + MMC3_FixPRG(); +} + +static void M196Power(void) { + reg[0] = reg[1] = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M196WriteNROM); + SetWriteHandler(0x8000, 0xFFFF, M196Write); +} + +void Mapper196_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M196PW; + info->Power = M196Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper197.c b/src/mappers/mapper197.c new file mode 100644 index 000000000..5cab3fa19 --- /dev/null +++ b/src/mappers/mapper197.c @@ -0,0 +1,121 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M197PW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x08) ? 0x0F : 0x1F; + + switch (iNESCart.submapper) { + case 3: + setprg8(A, (reg << 4) | (V & mask)); + break; + default: + setprg8(A, V & 0x3F); + break; + } +} + +static void M197CHR(void) { + switch (iNESCart.submapper) { + case 1: + setchr2(0x0000, mmc3.reg[1] & ~0x01); + setchr2(0x0800, mmc3.reg[1] | 0x01); + setchr2(0x1000, mmc3.reg[4]); + setchr2(0x1800, mmc3.reg[5]); + break; + case 2: + setchr2(0x0000, mmc3.reg[0] & ~0x01); + setchr2(0x0800, mmc3.reg[1] | 0x01); + setchr2(0x1000, mmc3.reg[2]); + setchr2(0x1800, mmc3.reg[5]); + break; + case 0: + case 3: + default: + setchr2(0x0000, mmc3.reg[0] & ~0x01); + setchr2(0x0800, mmc3.reg[0] | 0x01); + setchr2(0x1000, mmc3.reg[2]); + setchr2(0x1800, mmc3.reg[3]); + break; + } +} + +static DECLFW(M197WriteReg) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + } +} + +static DECLFW(M197Write) { + switch (A & 0xE001) { + case 0x8001: + switch (mmc3.cmd & 0x07) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + mmc3.reg[mmc3.cmd & 0x07] = V; + MMC3_FixCHR(); + break; + default: + MMC3_CMDWrite(A, V); + break; + } + break; + default: + MMC3_CMDWrite(A, V); + break; + } +} + +static void M197Reset(void) { + reg = 0; + MMC3_FixCHR(); + MMC3_FixPRG(); + MMC3_FixMIR(); +} + +static void M197Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M197WriteReg); + SetWriteHandler(0x8000, 0x9FFF, M197Write); +} + +void Mapper197_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + info->Power = M197Power; + info->Reset = M197Reset; + MMC3_FixCHR = M197CHR; + MMC3_pwrap = M197PW; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper198.c b/src/mappers/mapper198.c new file mode 100644 index 000000000..09a557a8a --- /dev/null +++ b/src/mappers/mapper198.c @@ -0,0 +1,42 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M198PW(uint16 A, uint16 V) { + if (V >= 0x40) { + V = (0x40 | (V & 0x0F)); + } + setprg8(A, V); +} + +static void M198Power(void) { + MMC3_Power(); + setprg4r(0x10, 0x5000, 2); + SetWriteHandler(0x5000, 0x5fff, CartBW); + SetReadHandler(0x5000, 0x5fff, CartBR); +} + +void Mapper198_Init(CartInfo *info) { + MMC3_Init(info, 16, info->battery); + MMC3_pwrap = M198PW; + info->Power = M198Power; +} diff --git a/src/mappers/mapper199.c b/src/mappers/mapper199.c new file mode 100644 index 000000000..456543b66 --- /dev/null +++ b/src/mappers/mapper199.c @@ -0,0 +1,40 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M199CW(uint16 A, uint16 V) { + setchr8(0); +} + +static void M199Power(void) { + MMC3_Power(); + setprg4r(0x10, 0x5000, 2); + SetReadHandler(0x5000, 0x5FFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, CartBW); +} + +void Mapper199_Init(CartInfo *info) { + MMC3_Init(info, 16, info->battery); + MMC3_cwrap = M199CW; + info->Power = M199Power; + info->Reset = MMC3_Reset; +} diff --git a/src/mappers/mapper200.c b/src/mappers/mapper200.c new file mode 100644 index 000000000..8a015a472 --- /dev/null +++ b/src/mappers/mapper200.c @@ -0,0 +1,38 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.addr & 0x07); + setprg16(0xC000, latch.addr & 0x07); + setchr8(latch.addr & 0x07); + if (iNESCart.submapper == 1) { + setmirror(((latch.addr >> 2) & 0x01) ^ 0x01); + } else { + setmirror(((latch.addr >> 3) & 0x01) ^ 0x01); + } +} + +void Mapper200_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper201.c b/src/mappers/mapper201.c new file mode 100644 index 000000000..7bc6c8b11 --- /dev/null +++ b/src/mappers/mapper201.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.addr); + setchr8(latch.addr); +} + +void Mapper201_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper202.c b/src/mappers/mapper202.c new file mode 100644 index 000000000..1fbf5d941 --- /dev/null +++ b/src/mappers/mapper202.c @@ -0,0 +1,38 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if ((latch.addr & 0x09) == 0x09) { + setprg32(0x8000, latch.addr >> 2); + } else { + setprg16(0x8000, latch.addr >> 1); + setprg16(0xC000, latch.addr >> 1); + } + setchr8(latch.addr >> 1); + setmirror((latch.addr & 0x01) ^ 0x01); +} + +void Mapper202_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper203.c b/src/mappers/mapper203.c new file mode 100644 index 000000000..7a0aedac8 --- /dev/null +++ b/src/mappers/mapper203.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.data >> 2); + setprg16(0xC000, latch.data >> 2); + setchr8(latch.data & 0x03); +} + +void Mapper203_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper204.c b/src/mappers/mapper204.c new file mode 100644 index 000000000..74d95d53d --- /dev/null +++ b/src/mappers/mapper204.c @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x20) { + setprg32(0x8000, latch.addr >> 1); + setchr8(latch.addr & 0x0E); + } else { + setprg16(0x8000, latch.addr); + setprg16(0xC000, latch.addr); + setchr8(latch.addr & 0x0F); + } + setmirror(((latch.addr >> 4) & 0x01) ^ 0x01); +} + +void Mapper204_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper205.c b/src/mappers/mapper205.c new file mode 100644 index 000000000..3e7b146c2 --- /dev/null +++ b/src/mappers/mapper205.c @@ -0,0 +1,78 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* iNES Mapper 205 + * UNIF boardname BMC-JC-016-2 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M205PW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x02) ? 0x0F : 0x1F; + + setprg8(A, (reg << 4) | (V & mask)); +} + +static void M205CW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x02) ? 0x7F : 0xFF; + + setchr1(A, (reg << 7) | (V & mask)); +} + +static DECLFW(M205Write) { + CartBW(A, V); + reg = V & 0x03; + if ((V & 0x01) && dipsw) { + reg |= 0x02; + } + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M205Reset(void) { + reg = 0; + dipsw = (dipsw + 1) & 0x01; /* solder pad */ + MMC3_Reset(); +} + +static void M205Power(void) { + reg = dipsw = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M205Write); +} + +void Mapper205_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = M205PW; + MMC3_cwrap = M205CW; + info->Power = M205Power; + info->Reset = M205Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper206.c b/src/mappers/mapper206.c new file mode 100644 index 000000000..57edd8194 --- /dev/null +++ b/src/mappers/mapper206.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "n118.h" + +static void M206PW(uint16 A, uint16 V) { + if (iNESCart.submapper == 1) { + /* 3407, 3417 and 3451 PCBs */ + setprg32(0x8000, 0); + } else { + setprg8(A, V & 0x0F); + } +} + +void Mapper206_Init(CartInfo *info) { + N118_Init(info, 0, 0); + N118_pwrap = M206PW; +} diff --git a/src/mappers/mapper208.c b/src/mappers/mapper208.c new file mode 100644 index 000000000..0038ace56 --- /dev/null +++ b/src/mappers/mapper208.c @@ -0,0 +1,132 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + /* 2022-2-14 + * - add support for iNESCart.submapper 1, Mortal Kombat (JJ-01) (Ch) [!] + * - add mirroring + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 protIndex; +static uint8 protReg[4]; + +static const uint8 lut[256] = { + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09, + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01, + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09, + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01, + 0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08, + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00, + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08, + 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00, + 0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static void M208PRG(void) { + setprg32(0x8000, (reg & 0x01) | ((reg >> 3) & 0x02)); +} + +static void M208MIR(void) { + setmirror(((reg >> 5) & 0x01) ^ 0x01); +} + +static void M208PRG_Sub1(void) { + setprg32(0x8000, mmc3.reg[6] >> 2); +} + +static void M208MIR_Sub1(void) { + setmirror((mmc3.mirr & 0x01) ^ 0x01); +} + +static DECLFW(M208Write) { + reg = V; + MMC3_FixPRG(); + MMC3_FixMIR(); +} + +static DECLFW(M208ProtWrite) { + if (A & 0x800) { + protReg[(A & 0x03)] = V ^ lut[protIndex]; + } else { + protIndex = V; + } +} + +static DECLFR(M208ProtRead) { + return (protReg[(A & 0x3)]); +} + +static DECLFW(M208WriteCMD) { + switch (A & 0xE001) { + case 0x8001: + switch (mmc3.cmd & 0x07) { + case 6: + case 7: + mmc3.reg[mmc3.cmd & 0x07] = V; + MMC3_FixPRG(); + break; + default: + MMC3_CMDWrite(A, V); + break; + } + break; + default: + MMC3_CMDWrite(A, V); + break; + } +} + +static void M208Power(void) { + reg = 0x11; + MMC3_Power(); + SetWriteHandler(0x4800, 0x4FFF, M208Write); + SetWriteHandler(0x6800, 0x6FFF, M208Write); + SetWriteHandler(0x5000, 0x5FFF, M208ProtWrite); + SetReadHandler(0x5800, 0x5FFF, M208ProtRead); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + if (iNESCart.submapper == 1) { + SetWriteHandler(0x8000, 0x9FFF, M208WriteCMD); + MMC3_FixPRG = M208PRG_Sub1; + MMC3_FixMIR = M208MIR_Sub1; + MMC3_Reset(); + } +} + +void Mapper208_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_FixPRG = M208PRG; + MMC3_FixMIR = M208MIR; + info->Power = M208Power; + AddExState(®, 1, 0, "EXPR"); + AddExState(&protIndex, 1, 0, "PRID"); + AddExState(&protReg, 4, 0, "PRRG"); +} diff --git a/src/mappers/mapper209.c b/src/mappers/mapper209.c new file mode 100644 index 000000000..f6faa3634 --- /dev/null +++ b/src/mappers/mapper209.c @@ -0,0 +1,62 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +static uint32 GetPRGBank(uint32 V) { + return (((jyasic.mode[3] << 5) & ~0x3F) | (V & 0x3F)); +} + +static uint32 GetCHRBank(uint32 V) { + if (jyasic.mode[3] & 0x20) { + return (((jyasic.mode[3] << 6) & 0x600) | (V & 0x1FF)); + } else { + return (((jyasic.mode[3] << 6) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); + } +} + +void Mapper035_Init(CartInfo *info) { + /* Basically mapper 90/209/211 with WRAM */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} + +void Mapper090_Init(CartInfo *info) { + /* Single cart, extended mirroring and ROM nametables disabled */ + JYASIC_Init(info, FALSE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} + +void Mapper209_Init(CartInfo *info) { + /* Single cart, extended mirroring and ROM nametables enabled */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} + +void Mapper211_Init(CartInfo *info) { + /* Duplicate of mapper 209 */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} diff --git a/src/mappers/mapper210.c b/src/mappers/mapper210.c new file mode 100644 index 000000000..b84579164 --- /dev/null +++ b/src/mappers/mapper210.c @@ -0,0 +1,146 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 210 - simplified version of Mapper 19 + * Namco 175 - submapper 1 - optional wram, hard-wired mirroring + * Namco 340 - submapper 2 - selectable H/V/0 mirroring + */ + +#include "mapinc.h" + +static uint8 prg[4]; +static uint8 chr[8]; +static uint8 wram_enable; + +static SFORMAT StateRegs[] = { + { prg, 3, "PRG" }, + { chr, 8, "CHR" }, + { &wram_enable, 1, "WREN" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0] & 0x3F); + setprg8(0xA000, prg[1] & 0x3F); + setprg8(0xC000, prg[2] & 0x3F); + setprg8(0xE000, prg[3] & 0x3F); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + if (iNESCart.submapper != 1) { + switch((prg[0] >> 6) & 0x03) { + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_V); break; + case 2: setmirror(MI_H); break; + case 3: setmirror(MI_0); break; + } + } +} + +static DECLFR(AWRAM) { + A = ((A - 0x6000) & (WRAMSIZE -1)); + return WRAM[A]; +} + +static DECLFW(BWRAM) { + if (wram_enable) { + A = ((A - 0x6000) & (WRAMSIZE -1)); + WRAM[A] = V; + } +} + +static DECLFW(M210Write) { + switch (A & 0xF800) { + case 0x8000: + case 0x8800: + case 0x9000: + case 0x9800: + case 0xA000: + case 0xA800: + case 0xB000: + case 0xB800: + chr[(A - 0x8000) >> 11] = V; + Sync(); + break; + case 0xC000: + wram_enable = V & 0x01; + break; + case 0xE000: + case 0xE800: + case 0xF000: + prg[(A - 0xE000) >> 11] = V; + Sync(); + break; + } +} + +static void M210Power(void) { + int i; + for (i = 0; i < 4; i++) prg[i] = 0xFC | i; + for (i = 0; i < 4; i++) chr[0 | i] = 0 | i; + for (i = 0; i < 4; i++) chr[4 | i] = 4 | i; + wram_enable = 0; + Sync(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xffff, M210Write); + + if (WRAM) { + SetReadHandler(0x6000, 0x7FFF, AWRAM); + SetWriteHandler(0x6000, 0x7FFF, BWRAM); + FCEU_CheatAddRAM(8, 0x6000, WRAM); + } + + if (WRAM && !iNESCart.battery) { + FCEU_MemoryRand(WRAM, sizeof(WRAM)); + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper210_Init(CartInfo *info) { + GameStateRestore = StateRestore; + info->Power = M210Power; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } + + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } +} diff --git a/src/mappers/mapper212.c b/src/mappers/mapper212.c new file mode 100644 index 000000000..5967eb4e5 --- /dev/null +++ b/src/mappers/mapper212.c @@ -0,0 +1,48 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x4000) { + setprg32(0x8000, latch.addr >> 1); + } else { + setprg16(0x8000, latch.addr); + setprg16(0xC000, latch.addr); + } + setchr8(latch.addr); + setmirror(((latch.addr >> 3) & 0x01) ^ 0x01); +} + +static DECLFR(M212Read) { + return (CPU_OPENBUS & ~0x80) | ((A & 0x10) ? 0 : 0x80); +} + +static void M212Power(void) { + Latch_Power(); + SetReadHandler(0x6000, 0x7FFF, M212Read); +} + +void Mapper212_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M212Power; +} diff --git a/src/mappers/mapper214.c b/src/mappers/mapper214.c new file mode 100644 index 000000000..818c3d39c --- /dev/null +++ b/src/mappers/mapper214.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.addr >> 2); + setprg16(0xC000, latch.addr >> 2); + setchr8(latch.addr >> 2); +} + +void Mapper214_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper215.c b/src/mappers/mapper215.c new file mode 100644 index 000000000..4fcfd258f --- /dev/null +++ b/src/mappers/mapper215.c @@ -0,0 +1,184 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Submapper 0, UNIF board name UNL-8237: + * Earthworm Jim 2 + * Mortal Kombat 3 (SuperGame, not Extra 60, not to be confused by similarly-named games from other developers) + * Mortal Kombat 3 Extra 60 (both existing ROM images are just extracts of the 2-in-1 multicart containing this game) + * Pocahontas Part 2 + * 2-in-1: Aladdin, EarthWorm Jim 2 (Super 808) + * 2-in-1: The Lion King, Bomber Boy (GD-103) + * 2-in-1: Super Golden Card: EarthWorm Jim 2, Boogerman (king002) + * 2-in-1: Mortal Kombat 3 Extra 60, The Super Shinobi (king005) + * 3-in-1: Boogerman, Adventure Island 3, Double Dragon 3 (Super 308) + * 5-in-1: Golden Card: Aladdin, EarthWorm Jim 2, Garo Densetsu Special, Silkworm, Contra Force (SPC005) + * 6-in-1: Golden Card: EarthWorm Jim 2, Mortal Kombat 3, Double Dragon 3, Contra 3, The Jungle Book, Turtles Tournament Fighters (SPC009) + * + * Submapper 1, UNIF board name UNL-8237A: + * 9-in-1 High Standard Card: The Lion King, EarthWorm Jim 2, Aladdin, Boogerman, Somari, Turtles Tournament Fighters, Mortal Kombat 3, Captain Tsubasa 2, Taito Basketball (king001) + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; + +static const uint8 regperm[8][8] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + { 0, 2, 6, 1, 7, 3, 4, 5 }, + { 0, 5, 4, 1, 7, 2, 6, 3 }, /* unused */ + { 0, 6, 3, 7, 5, 2, 4, 1 }, + { 0, 2, 5, 3, 6, 1, 7, 4 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* empty */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* empty */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* empty */ +}; + +static const uint16 adrperm[8][8] = { + { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, + { 0xA001, 0xA000, 0x8000, 0xC000, 0x8001, 0xC001, 0xE000, 0xE001 }, + { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, /* unused */ + { 0xC001, 0x8000, 0x8001, 0xA000, 0xA001, 0xE001, 0xE000, 0xC000 }, + { 0xA001, 0x8001, 0x8000, 0xC000, 0xA000, 0xC001, 0xE000, 0xE001 }, + { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, /* empty */ + { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, /* empty */ + { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, /* empty */ +}; + +static const uint8 protarray[8][8] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 0 Super Hang-On */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00 }, /* 1 Monkey King */ + { 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00 }, /* 2 Super Hang-On/Monkey King */ + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x05, 0x00 }, /* 3 Super Hang-On/Monkey King */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 4 */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 5 */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 6 */ + { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0F, 0x00 } /* 7 (default) Blood of Jurassic */ +}; + +static void M215CW(uint16 A, uint16 V) { + uint16 mask = (reg[0] & 0x40) ? 0x7F : 0xFF; + uint16 base; + + if (iNESCart.submapper == 1) { + base = (reg[1] << 7) & 0x700; + } else { + base = (reg[1] << 6) & 0x300; + } + + base = (base & ~mask) | (((reg[1] << 2) & 0x80) & ~mask); + setchr1(A, base | (V & mask)); +} + +static void M215PW(uint16 A, uint16 V) { + uint16 mask = (reg[0] & 0x40) ? 0x0F : 0x1F; + uint16 base; + + if (iNESCart.submapper == 1) { + base = ((reg[1] << 5) & 0x60) | ((reg[1] << 4) & 0x80); + } else { + base = (reg[1] << 5) & 0x60; + } + + if (reg[0] & 0x80) { /* NROM */ + uint16 bank = (((reg[1] & 0x10) & ~mask) >> 1) | ((base & ~mask) >> 1) | (reg[0] & (mask >> 1)); + + if (reg[0] & 0x20) { /* NROM-256 */ + setprg32(0x8000, bank >> 1); + } else { /* NROM-128 */ + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { + setprg8(A, ((reg[1] & 0x10) & ~mask) | (base & ~mask) | (V & mask)); + } +} + +static DECLFR(M215ProtRead) { + return (CPU_OPENBUS & ~0x0F) | (protarray[reg[2]][A & 0x07] & 0x0F); +} + +static DECLFW(M215Write) { + A = adrperm[reg[3]][((A >> 12) & 0x06) | (A & 0x01)]; + switch (A & 0xE001) { + case 0x8000: + MMC3_Write(A, (V & 0xC0) | regperm[reg[3]][V & 0x07]); + break; + default: + MMC3_Write(A, V); + break; + } +} + +static DECLFW(M215Write5) { + switch (A & 0x07) { + case 0: + reg[0] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + break; + case 1: + reg[1] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + break; + case 2: + reg[2] = V & 0x07; + break; + case 7: + reg[3] = V & 0x07; + break; + } +} + +static void M215Power(void) { + reg[0] = 0x00; + reg[1] = 0x0F; + reg[3] = 0x04; + reg[2] = 0x07; + MMC3_Power(); + SetReadHandler(0x5000, 0x5FFF, M215ProtRead); + SetWriteHandler(0x5000, 0x5FFF, M215Write5); + SetWriteHandler(0x8000, 0xFFFF, M215Write); +} + +static void M215Reset(void) { + reg[0] = 0x00; + reg[1] = 0x0F; + reg[3] = 0x04; + reg[2] = 0x07; + MMC3_Reset(); +} + +void Mapper215_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M215CW; + MMC3_pwrap = M215PW; + + info->Power = M215Power; + info->Reset = M215Reset; + + AddExState(reg, 4, 0, "EXPR"); + + if ((!info->iNES2) && (PRG_ROM_SIZE_16K >= (2048 * 1024))) { /* UNL-8237A */ + info->submapper = 1; + } +} diff --git a/src/mappers/mapper216.c b/src/mappers/mapper216.c new file mode 100644 index 000000000..7e6be09e5 --- /dev/null +++ b/src/mappers/mapper216.c @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.addr & 0x01); + setchr8(latch.addr >> 1); +} + +void Mapper216_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper217.c b/src/mappers/mapper217.c new file mode 100644 index 000000000..f63858520 --- /dev/null +++ b/src/mappers/mapper217.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.addr >> 2); + setchr8(latch.addr); +} + +void Mapper217_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper218.c b/src/mappers/mapper218.c new file mode 100644 index 000000000..00af07206 --- /dev/null +++ b/src/mappers/mapper218.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mapinc.h" + +extern uint8 **VPageR; +static const uint8 mirrorings[] = { MI_V, MI_H, MI_0, MI_1 }; +static const uint8 mapping[4][8] = { + { 0, 1, 0, 1, 0, 1, 0, 1 }, /* MI_V */ + { 0, 0, 1, 1, 0, 0, 1, 1 }, /* MI_H */ + { 0, 0, 0, 0, 1, 1, 1, 1 }, /* MI_0 */ + { 0, 0, 0, 0, 0, 0, 0, 0 } /* MI_1 */ +}; + +static void M218Power(void) { + setchr8(0); + setprg32(0x8000, 0); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +void Mapper218_Init(CartInfo *info) { + int mirror2bits = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2); + + info->Power = M218Power; + + /* similar to mapper 30, this mapper interprets the two bits in headers mirroring in idiosyncratic ways */ + SetupCartMirroring(mirrorings[mirror2bits], 1, NULL); + + /* cryptic logic to effect the CHR RAM mappings by mapping 1k blocks to NTARAM according to how the pins are wired + this could be done by bit logic, but this is self-documenting */ + VPageR[0] = &NTARAM[mapping[mirror2bits][0]]; + VPageR[1] = &NTARAM[mapping[mirror2bits][1]]; + VPageR[2] = &NTARAM[mapping[mirror2bits][2]]; + VPageR[3] = &NTARAM[mapping[mirror2bits][3]]; + VPageR[4] = &NTARAM[mapping[mirror2bits][4]]; + VPageR[5] = &NTARAM[mapping[mirror2bits][5]]; + VPageR[6] = &NTARAM[mapping[mirror2bits][6]]; + VPageR[7] = &NTARAM[mapping[mirror2bits][7]]; + PPUCHRRAM = 0xFF; +} diff --git a/src/mappers/mapper219.c b/src/mappers/mapper219.c new file mode 100644 index 000000000..a85761d64 --- /dev/null +++ b/src/mappers/mapper219.c @@ -0,0 +1,113 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 extMode; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { &extMode, 1, "MODE" }, + { 0 } +}; + +static void M219PW(uint16 A, uint16 V) { + setprg8(A, (reg << 4) | (V & 0x0F)); +} + +static void M219CW(uint16 A, uint16 V) { + setchr1(A, (reg << 7) | (V & 0x7F)); +} + +static DECLFW(M219WriteOuter) { + switch (A & 0x01) { + case 0: + reg = (reg & ~0x01) | ((V >> 3) & 0x01); + break; + case 1: + reg = (reg & ~0x02) | ((V >> 4) & 0x02); + break; + } + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static DECLFW(M219WriteASIC) { + uint8 oldcmd = mmc3.cmd; + + if (!(A & 0x01)) { /* Register index */ + mmc3.cmd = V; + if ((oldcmd & 0x40) != ((V & 0x40))) { + MMC3_FixPRG(); + } + if ((oldcmd & 0x80) != ((V & 0x80))) { + MMC3_FixPRG(); + } + if (A & 0x02) { + extMode = (V & 0x20) != 0; + } + } else { + if (!extMode) { /* Scrambled mode inactive */ + MMC3_CMDWrite(A, V); + } else { /* Scrambled mode active */ + if ((mmc3.cmd >= 0x08) && (mmc3.cmd <= 0x1F)) { /* Scrambled CHR register */ + uint8 index = (mmc3.cmd - 8) >> 2; + if (mmc3.cmd & 0x01) { /* LSB nibble */ + mmc3.reg[index] &= ~0x0F; + mmc3.reg[index] |= ((V >> 1) & 0x0F); + } else { /* MSB nibble */ + mmc3.reg[index] &= ~0xF0; + mmc3.reg[index] |= ((V << 4) & 0xF0); + } + MMC3_FixCHR(); + } else if ((mmc3.cmd >= 0x25) && (mmc3.cmd <= 0x26)) { /* Scrambled PRG register */ + V = ((V << 1) & 0x08) | ((V >> 1) & 0x04) | ((V >> 3) & 0x02) | ((V >> 5) & 0x01); + mmc3.reg[6 | (mmc3.cmd & 0x01)] = V; + MMC3_FixPRG(); + } + } + } +} + +static void M219Power(void) { + extMode = FALSE; + reg = 3; + MMC3_Power(); + SetWriteHandler(0x5000, 0x5FFF, M219WriteOuter); + SetWriteHandler(0x8000, 0x9FFF, M219WriteASIC); +} + +static void M219Reset(void) { + extMode = FALSE; + reg = ~0; + MMC3_Reset(); +} + +void Mapper219_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M219PW; + MMC3_cwrap = M219CW; + info->Power = M219Power; + info->Reset = M219Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper221.c b/src/mappers/mapper221.c new file mode 100644 index 000000000..c2f4da0fe --- /dev/null +++ b/src/mappers/mapper221.c @@ -0,0 +1,92 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR reg[0] PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Mapper 221 - UNL-N625092 + * 700in1 and 400in1 carts + * 1000-in-1 + */ + +#include "mapinc.h" + +static uint16 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { 0 } +}; + +static uint16 GetPRGBank(void) { + return (((reg[0] >> 3) & 0x40) | ((reg[0] >> 2) & 0x38) | (reg[1] & 0x07)); +} + +static void Sync(void) { + uint16 prg = GetPRGBank(); + + if (!(reg[0] & 0x02)) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { + if (reg[0] & 0x100) { + setprg16(0x8000, prg); + setprg16(0xC000, prg | 0x07); + } else { + setprg16(0x8000, prg & ~1); + setprg16(0xC000, prg | 1); + } + } + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !(reg[1] & 0x08)); + setchr8(0); + setmirror((reg[0] & 0x01) ^ 0x01); +} + +static DECLFR(M221Read) { + if (GetPRGBank() >= PRG_BANK_COUNT(16)) { + return CPU_OPENBUS; + } + return CartBR(A); +} + +static DECLFW(M221Write) { + reg[(A >> 14) & 0x01] = A; + Sync(); +} + +static void M221Reset(void) { + reg[0] = reg[1] = 0; + Sync(); +} + +static void M221Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, M221Read); + SetWriteHandler(0x8000, 0xFFFF, M221Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper221_Init(CartInfo *info) { + info->Power = M221Power; + info->Reset = M221Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper222.c b/src/mappers/mapper222.c new file mode 100644 index 000000000..6f484fd15 --- /dev/null +++ b/src/mappers/mapper222.c @@ -0,0 +1,76 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * iNES Mapper 222 - (CTC-31?) + * (VRC2 mapper) + * + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 IRQCount; +static uint8 IRQa; + +static SFORMAT StateRegs[] = { + { &IRQCount, 1, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void M222IRQ(void) { + if (IRQa) { + IRQCount++; + if (IRQCount >= 238) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static DECLFW(M222WriteCHR) { + if (!(A & 0x01)) { + VRC24_Write(A, V); + VRC24_Write(A | 0x01, V >> 4); + } +} + +static DECLFW(M222WriteIRQ) { + /* TODO: Update this */ + IRQa = IRQCount = V; + if (scanline < 240) + IRQCount -= 8; + else + IRQCount += 4; + X6502_IRQEnd(FCEU_IQEXT); +} + +static void M222Power(void) { + VRC24_Power(); + SetWriteHandler(0xB000, 0xEFFF, M222WriteCHR); + SetWriteHandler(0xF000, 0xFFFF, M222WriteIRQ); +} + +void Mapper222_Init(CartInfo *info) { + VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); + info->Power = M222Power; + MapIRQHook = NULL; + GameHBIRQHook = M222IRQ; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper225.c b/src/mappers/mapper225.c new file mode 100644 index 000000000..5f03d8160 --- /dev/null +++ b/src/mappers/mapper225.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * PCB-018 board, discrete multigame cart 110-in-1 + * + * Mapper 225 + * Mapper 255 + * + */ + +/* 2020-2-20 - merge mapper 255, re-implement extra RAM */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 extraRAM[4]; + +static SFORMAT StateRegs[] = { + { extraRAM, 4, "PROT" }, + { 0 } +}; + +static void Sync(void) { + uint8 base = (latch.addr >> 8) & 0x40; + uint8 prg = (latch.addr >> 6) & 0x3F; + uint8 chr = latch.addr & 0x3F; + uint8 mirr = ((latch.addr >> 13) & 1) ^ 1; + + if (latch.addr & 0x1000) { + setprg16(0x8000, base | prg); + setprg16(0xC000, base | prg); + } else { + setprg32(0x8000, (base | prg) >> 1); + } + setchr8(base | chr); + setmirror(mirr); +} + +static DECLFW(M225LoWrite) { + /* e.g. 115-in-1 [p1][!] CRC32 0xb39d30b4 */ + if (A & 0x800) { + extraRAM[A & 3] = V & 0x0F; + } +} + +static DECLFR(M225LoRead) { + if (A & 0x800) { + return extraRAM[A & 3]; + } + return CPU_OPENBUS; +} + +static void M225Power(void) { + Latch_Power(); + SetReadHandler(0x5000, 0x5fff, M225LoRead); + SetWriteHandler(0x5000, 0x5fff, M225LoWrite); +} + +void Mapper225_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M225Power; + AddExState(StateRegs, ~0, 0, NULL); +} + +void Mapper255_Init(CartInfo *info) { + Mapper225_Init(info); +} diff --git a/src/mappers/mapper226.c b/src/mappers/mapper226.c new file mode 100644 index 000000000..714c2efaa --- /dev/null +++ b/src/mappers/mapper226.c @@ -0,0 +1,85 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2009 qeed + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Updated 2019-07-12 + * Mapper 226 - Updated and combine UNIF Ghostbusters63in1 board (1.5 MB carts), different bank order + * - some 1MB carts can switch game lists using Select + */ + +#include "mapinc.h" + +static uint8 reg[2], dipsw; +static SFORMAT StateRegs[] = { + { &dipsw, 1, "RST" }, + { reg, 2, "LATC" }, + { 0 } +}; + +static void Sync(void) { + uint8 base = (reg[0] >> 7) | ((reg[1] & 0x01) << 1); + uint8 prg = reg[0] & 0x1F; + + /* 1536KiB PRG roms have different bank order */ + if ((PRG_ROM_SIZE_16K == (1536 * 1024)) && (base > 0)) { + base = (base - 1); + } + + if (reg[0] & 0x20) { + setprg16(0x8000, (base << 5) | prg); + setprg16(0xC000, (base << 5) | prg); + } else { + setprg32(0x8000, ((base << 5) | prg) >> 1); + } + + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !(reg[1] & 0x02)); + setchr8(0); + setmirror((reg[0] >> 6) & 0x01); +} + +static DECLFW(M226Write) { + reg[A & 0x01] = V; + Sync(); +} + +static void M226Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M226Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M226Reset(void) { + reg[0] = reg[1] = 0; + Sync(); +} + +void Mapper226_Init(CartInfo *info) { + info->Power = M226Power; + info->Reset = M226Reset; + AddExState(StateRegs, ~0, 0, NULL); + GameStateRestore = StateRestore; +} diff --git a/src/mappers/mapper227.c b/src/mappers/mapper227.c new file mode 100644 index 000000000..66ac20593 --- /dev/null +++ b/src/mappers/mapper227.c @@ -0,0 +1,69 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static void Sync(void) { + uint32 prg = ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); + uint32 cpuA14 = latch.addr & 0x01; + uint32 nrom = (latch.addr >> 7) & 0x01; + uint32 unrom = (latch.addr >> 9) & 0x01; + + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, prg & ~cpuA14); + setprg16(0xC000, ((prg | cpuA14) & ~(0x07 * !nrom * !unrom)) | (0x07 * !nrom * unrom)); + + setchr8(0); + setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); + if (!iNESCart.battery && (latch.addr & 0x80) == 0x80) { + /* CHR-RAM write protect hack, needed for some multicarts */ + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); + } else { + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); + } +} + +static DECLFR(M227Read) { + if ((latch.addr & 0x400) && dipsw) { + A |= dipsw; + } + return CartBROB(A); +} + +static void M227Power(void) { + dipsw = 0; + Latch_Power(); +} + +static void M227Reset(void) { + dipsw = (dipsw + 1) & 0x1F; + Latch_RegReset(); +} + +void Mapper227_Init(CartInfo *info) { + Latch_Init(info, Sync, M227Read, TRUE, FALSE); + info->Power = M227Power; + info->Reset = M227Reset; + AddExState(&dipsw, 1, 0, "PADS"); +} diff --git a/src/mappers/mapper228.c b/src/mappers/mapper228.c new file mode 100644 index 000000000..cc350dd04 --- /dev/null +++ b/src/mappers/mapper228.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + Mapper 228: + Action 52 is highly uncommon in that its PRG ROM has a non-power-of-two ROM size: three 512 KiB PRG ROMs alongside one + 512 KiB CHR ROM. + + It is claimed that there are four 4-bit RAM locations at $4020-$4023, mirrored throughout $4020-$5FFF. This 16-bit RAM + is definitely not present on either cartridge, Nestopia does not implement it at all, and neither cartridge ever writes + to these addresses. + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x20) { + setprg16(0x8000, (latch.addr >> 6) & 0x7F); + setprg16(0xC000, (latch.addr >> 6) & 0x7F); + } else { + setprg32(0x8000, (latch.addr >> 7) & 0x3F); + } + setchr8(((latch.addr << 2) & 0x3C) | (latch.data & 0x3)); + setmirror(((latch.addr >> 13) & 0x01) ^ 0x01); +} + +void Mapper228_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + + if (PRG_ROM_SIZE_16K == 0x180000) { + int i; + size_t ssize = 0x200000; + uint8 *tmp = (uint8 *)FCEU_malloc(ssize); + + for (i = 0; i < (int)PRG_ROM_SIZE_16K; i++) { + tmp[i] = PRG_ROM_DATA[i]; + } + for (i = 0x000000; i < 0x080000; i++) { + tmp[0x180000 + i] = tmp[0x100000 + i]; + tmp[0x100000 + i] = (i >> 8) & 0xFF; + } + + PRG_ROM_SIZE_16K = ssize; + if (PRG_ROM_DATA) FCEU_free(PRG_ROM_DATA); + PRG_ROM_DATA = (uint8 *)FCEU_malloc(ssize); + for (i = 0; i < (int)PRG_ROM_SIZE_16K; i++) { + PRG_ROM_DATA[i] = tmp[i]; + } + FCEU_free(tmp); + + SetupCartPRGMapping(0, PRG_ROM_DATA, PRG_ROM_SIZE_16K, 0); + } +} diff --git a/src/mappers/mapper229.c b/src/mappers/mapper229.c new file mode 100644 index 000000000..2fc519e76 --- /dev/null +++ b/src/mappers/mapper229.c @@ -0,0 +1,38 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x1E) { + setprg16(0x8000, latch.addr & 0x1F); + setprg16(0xC000, latch.addr & 0x1F); + } else { + setprg32(0x8000, 0); + } + setchr8(latch.addr & 0x1F); + setmirror(((latch.addr >> 5) & 0x01) ^ 0x01); +} + +void Mapper229_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper230.c b/src/mappers/mapper230.c new file mode 100644 index 000000000..8c505b03f --- /dev/null +++ b/src/mappers/mapper230.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2009 qeed + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * 22 + Contra Reset based custom mapper... + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 mode; + +static SFORMAT StateRegs[] = { + { &mode, 1, "MODE" }, + { 0 } +}; + +static void Sync(void) { + if (mode) { /* Contra mode */ + setprg16(0x8000, latch.data & 0x07); + setprg16(0xC000, 0x07); + setmirror(MI_V); + } else { /* multicart mode */ + if (latch.data & 0x20) { + setprg16(0x8000, 8 + (latch.data & 0x1F)); + setprg16(0xC000, 8 + (latch.data & 0x1F)); + } else { + setprg32(0x8000, (8 + (latch.data & 0x1F)) >> 1); + } + setmirror((latch.data >> 6) & 0x01); + } + setchr8(0); +} + +static void M230Reset(void) { + mode ^= 1; + Latch_RegReset(); +} + +static void M230Power(void) { + mode = 0; + Latch_Power(); +} + +void Mapper230_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M230Power; + info->Reset = M230Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper231.c b/src/mappers/mapper231.c new file mode 100644 index 000000000..dca7c117c --- /dev/null +++ b/src/mappers/mapper231.c @@ -0,0 +1,43 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x20) { + setprg32(0x8000, (latch.addr >> 1) & 0x0F); + } else { + setprg16(0x8000, latch.addr & 0x1E); + setprg16(0xC000, latch.addr & 0x1E); + } + setchr8(0); + switch ((latch.addr >> 6) & 0x03) { + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_V); break; + case 2: setmirror(MI_H); break; + case 3: setmirrorw(0, 1, 1, 1); break; + } +} + +void Mapper231_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper232.c b/src/mappers/mapper232.c new file mode 100644 index 000000000..e004e819b --- /dev/null +++ b/src/mappers/mapper232.c @@ -0,0 +1,62 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 base = (reg[0] >> 1) & 0x0C; + + if (iNESCart.submapper == 1) { + base = ((base << 1) & 0x08) | ((base >> 1) & 0x04); + } + setprg16(0x8000, base | (reg[1] & 0x03)); + setprg16(0xC000, base | 0x03); + setchr8(0); +} + +static DECLFW(M232Write) { + reg[(A >> 14) & 0x01] = V; + Sync(); +} + +static void M232Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M232Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper232_Init(CartInfo *info) { + info->Power = M232Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper233.c b/src/mappers/mapper233.c new file mode 100644 index 000000000..5d271382b --- /dev/null +++ b/src/mappers/mapper233.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2009 qeed + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Updated 2019-07-12 + * Mapper 233 - UNIF 42in1ResetSwitch - reset-based switching + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reset; + +static SFORMAT StateRegs[] = { + { &reset, 1, "RST0" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank = (latch.data & 0x1F) | (reset << 5); + + if (latch.data & 0x20) { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } else { + setprg32(0x8000, bank >> 1); + } + setchr8(0); + switch ((latch.data >> 6) & 0x03) { + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_V); break; + case 2: setmirror(MI_H); break; + case 3: setmirror(MI_1); break; + } +} + +static void M233Power(void) { + reset = 0; + Latch_Power(); +} + +static void M233Reset(void) { + reset ^= 1; + Sync(); +} + +void Mapper233_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M233Power; + info->Reset = M233Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper234.c b/src/mappers/mapper234.c new file mode 100644 index 000000000..3cbf5e46c --- /dev/null +++ b/src/mappers/mapper234.c @@ -0,0 +1,95 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[3]; + +static SFORMAT StateRegs[] = { + { reg, 3, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (reg[0] & 0x40) { + setprg32(0x8000, (reg[0] & 0x0E) | (reg[1] & 0x01)); + setchr8(((reg[0] & 0x0E) << 2) | ((reg[1] >> 4) & 0x07)); + } else { + setprg32(0x8000, reg[0] & 0x0F); + setchr8(((reg[0] & 0x0F) << 2) | ((reg[1] >> 4) & 0x03)); + } + setmirror((reg[0] >> 7) ^ 0x01); +} + +static DECLFR(M234Read) { + uint8 ret = CartBR(A); + + switch (A & 0xFFF8) { + case 0xFF80: + case 0xFF88: + case 0xFF90: + case 0xFF98: + if (!reg[0]) { + reg[0] = ret; + Sync(); + } + break; + case 0xFFC0: + case 0xFFC8: + case 0xFFD0: + case 0xFFD8: + if (!reg[0]) { + reg[2] = ret; + Sync(); + } + break; + case 0xFFE8: + case 0xFFF0: + reg[1] = ret; + Sync(); + break; + } + + return ret; +} + +static void M234Reset(void) { + reg[0] = reg[1] = reg[2] = 0; + Sync(); +} + +static void M234Power(void) { + reg[0] = reg[1] = reg[2] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0xFF80, 0xFFFF, M234Read); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper234_Init(CartInfo *info) { + info->Power = M234Power; + info->Reset = M234Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper235.c b/src/mappers/mapper235.c new file mode 100644 index 000000000..6a0284701 --- /dev/null +++ b/src/mappers/mapper235.c @@ -0,0 +1,78 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 mode; + +static SFORMAT StateRegs[] = { + { &mode, 1, "UROM" }, + { 0 } +}; + +static void Sync(void) { + if (mode) { /* Contra mode */ + setprg16(0x8000, (PRG_BANK_COUNT(16) & 0xC0) | (latch.data & 0x07)); + setprg16(0xC000, (PRG_BANK_COUNT(16) & 0xC0) | 0x07); + setchr8(0); + setmirror(MI_V); + } else { + uint8 bank = ((latch.addr >> 3) & 0x60) | (latch.addr & 0x1F); + + if (latch.addr & 0x800) { + setprg16(0x8000, (bank << 1) | ((latch.addr >> 12) & 0x01)); + setprg16(0xC000, (bank << 1) | ((latch.addr >> 12) & 0x01)); + } else { + setprg32(0x8000, bank); + } + setchr8(0); + if (latch.addr & 0x400) { + setmirror(MI_0); + } else { + setmirror(((latch.addr >> 13) & 0x01) ^ 0x01); + } + } +} + +static DECLFR(M235Read) { + uint8 bank = ((latch.addr >> 3) & 0x60) | (latch.addr & 0x1F); + + if (!mode && (bank >= PRG_BANK_COUNT(32))) { + return CPU_OPENBUS; + } + return CartBR(A); +} + +static void M235Reset(void) { + if (PRG_ROM_SIZE_16K & 0x20000) { + mode = (mode + 1) & 1; + } + Latch_RegReset(); + FCEU_printf("mode : %d\n", mode); +} + +void Mapper235_Init(CartInfo *info) { + Latch_Init(info, Sync, M235Read, FALSE, FALSE); + info->Reset = M235Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper236.c b/src/mappers/mapper236.c new file mode 100644 index 000000000..456f00a66 --- /dev/null +++ b/src/mappers/mapper236.c @@ -0,0 +1,102 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &dipsw, 1, "DPSW " }, + { 0 } +}; + +static void Sync(void) { + uint8 prg; + uint8 chr; + + if (CHR_ROM_SIZE_8K) { + prg = reg[1] & 0x0F; + chr = reg[0] & 0x0F; + } else { + prg = (reg[1] & 0x07) | (reg[0] << 3); + chr = 0; + } + switch (reg[1] >> 4 & 3) { + case 0: + case 1: + setprg16(0x8000, prg); + setprg16(0xC000, prg | 0x07); + break; + case 2: + setprg32(0x8000, prg >> 1); + break; + case 3: + setprg16(0x8000, prg); + setprg16(0xC000, prg); + break; + } + setchr8(chr); + setmirror(((reg[0] >> 5) & 0x01) ^ 0x01); +} + +static DECLFR(M236Read) { + uint8 ret = CartBR(A); + + if (((reg[1] >> 4) & 0x03) == 1) { + return ((ret & ~0x0F) | (dipsw & 0x0F)); + } + return CartBR(A); +} + +static DECLFW(M236WriteReg) { + reg[(A >> 14) & 0x01] = A & 0xFF; + Sync(); +} + +static void M236Power(void) { + dipsw = 0; + reg[0] = 0; + reg[1] = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M236WriteReg); + SetReadHandler(0x8000, 0xFFFF, M236Read); +} + +static void M236Reset(void) { + ++dipsw; + /* Soft-reset returns to menu */ + reg[0] = 0; + reg[1] = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper236_Init(CartInfo *info) { + info->Power = M236Power; + info->Reset = M236Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper237.c b/src/mappers/mapper237.c new file mode 100644 index 000000000..259f0c33a --- /dev/null +++ b/src/mappers/mapper237.c @@ -0,0 +1,88 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 237 - "Teletubbies / Y2K" 420-in-1 pirate multicart. + * Dipswitch settings: + * 0: 42-in-1 + * 1: 5,000-in-1 + * 2: 420-in-1 + * 3: 10,000,000-in-1 (lol) + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank = (latch.data & 0x07); + uint8 base = ((latch.addr << 3) & 0x20) | (latch.data & 0x18); + uint8 A14 = (latch.data >> 6) & 0x01; + + setprg16(0x8000, base | (bank & ~A14)); + if (latch.data & 0x80) { + setprg16(0xC000, base | (bank | A14)); + } else { + setprg16(0xC000, base | 0x07); + } + setchr8(0); + setmirror(((latch.data & 0x20) >> 5) ^ 0x01); +} + +static DECLFW(M237Write) { + if (latch.addr & 0x02) { + latch.data = (latch.data & 0xF8) | (V & 0x07); + } else { + latch.addr = A; + latch.data = V; + } + Sync(); +} + +static DECLFR(M237Read) { + if (latch.addr & 0x01) { + return dipsw; + } + return CartBR(A); +} + +static void M237Reset(void) { + dipsw++; + dipsw &= 3; + Latch_RegReset(); +} + +static void M237Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M237Write); +} + +void Mapper237_Init(CartInfo *info) { + Latch_Init(info, Sync, M237Read, FALSE, FALSE); + info->Power = M237Power; + info->Reset = M237Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper238.c b/src/mappers/mapper238.c new file mode 100644 index 000000000..b8499a31d --- /dev/null +++ b/src/mappers/mapper238.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * iNES Mapper 238 + * SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1) + * the same as 603-5052 board (TODO: add reading registers, merge) + * + * Contra Fighter prot board + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static const uint8 lut[4] = { 0x00, 0x02, 0x02, 0x03 }; + +static DECLFW(M238ProtWrite) { + reg = lut[V & 0x03]; +} + +static DECLFR(M238ProtRead) { + return reg; +} + +static void M238Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x4020, 0x7FFF, M238ProtWrite); + SetReadHandler(0x4020, 0x7FFF, M238ProtRead); +} + +void Mapper238_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + info->Power = M238Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper240.c b/src/mappers/mapper240.c new file mode 100644 index 000000000..2cf33c15e --- /dev/null +++ b/src/mappers/mapper240.c @@ -0,0 +1,71 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg >> 4); + setchr8(reg & 0x0F); + setprg8r(0x10, 0x6000, 0); +} + +static DECLFW(M240Write) { + reg = V; + Sync(); +} + +static void M240Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0x4FFF, M240Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper240_Init(CartInfo *info) { + info->Power = M240Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + if (info->iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + } + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } +} diff --git a/src/mappers/mapper241.c b/src/mappers/mapper241.c new file mode 100644 index 000000000..7db733685 --- /dev/null +++ b/src/mappers/mapper241.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Map 241 */ +/* Mapper 7 mostly, but with SRAM or maybe prot circuit. */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, latch.data); + setchr8(0); +} + +void Mapper241_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper242.c b/src/mappers/mapper242.c new file mode 100644 index 000000000..4298516a9 --- /dev/null +++ b/src/mappers/mapper242.c @@ -0,0 +1,79 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static void Sync(void) { + uint32 prg = (latch.addr >> 2) & 0x1F; + uint32 cpuA14 = latch.addr & 0x01; + uint32 nrom = (latch.addr >> 7) & 0x01; + uint32 unrom = (latch.addr >> 9) & 0x01; + uint32 M242TwoChips = (PRG_ROM_SIZE_16K & 0x20000) && (PRG_ROM_SIZE_16K > 0x20000); + + if (M242TwoChips) { + if (latch.addr & 0x600) { /* First chip */ + prg &= ((PRG_BANK_COUNT(16) & ~0x08) - 1); + } else { /* Second chip */ + prg &= 0x07; + prg += (PRG_BANK_COUNT(16) & ~0x08); + } + } + + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, prg & ~cpuA14); + setprg16(0xC000, ((prg | cpuA14) & ~(0x07 * !nrom * !unrom)) | (0x07 * !nrom * unrom)); + + setchr8(0); + setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); + if (!iNESCart.battery && (latch.addr & 0x80) == 0x80 && (PRG_ROM_SIZE_16K > (256 * 1024))) { + /* CHR-RAM write protect hack, needed for some multicarts */ + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); + } else { + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); + } +} + +static DECLFR(M242Read) { + if (latch.addr & 0x100) { + A |= dipsw; + } + return CartBROB(A); +} + +static void M242Power(void) { + dipsw = 0; + Latch_Power(); +} + +static void M242Reset(void) { + dipsw = (dipsw + 1) & 0x1F; + Latch_RegReset(); +} + +void Mapper242_Init(CartInfo *info) { + Latch_Init(info, Sync, M242Read, TRUE, FALSE); + info->Power = M242Power; + info->Reset = M242Reset; + AddExState(&dipsw, 1, 0, "PADS"); +} diff --git a/src/mappers/mapper244.c b/src/mappers/mapper244.c new file mode 100644 index 000000000..059af9713 --- /dev/null +++ b/src/mappers/mapper244.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, reg[0]); + setchr8(reg[1]); +} + +static DECLFW(M244Write) { + if (V & 8) { + static const uint8 chr_perm[8][8] = { + { 0, 1, 2, 3, 4, 5, 6, 7, }, + { 0, 2, 1, 3, 4, 6, 5, 7, }, + { 0, 1, 4, 5, 2, 3, 6, 7, }, + { 0, 4, 1, 5, 2, 6, 3, 7, }, + { 0, 4, 2, 6, 1, 5, 3, 7, }, + { 0, 2, 4, 6, 1, 3, 5, 7, }, + { 7, 6, 5, 4, 3, 2, 1, 0, }, + { 7, 6, 5, 4, 3, 2, 1, 0, }, + }; + reg[1] = chr_perm[(V >> 4) & 0x07][V & 0x07]; + Sync(); + } else { + static const uint8 prg_perm[4][4] = { + { 0, 1, 2, 3, }, + { 3, 2, 1, 0, }, + { 0, 2, 1, 3, }, + { 3, 1, 2, 0, }, + }; + reg[0] = prg_perm[(V >> 4) & 0x03][V & 0x03]; + Sync(); + } +} + +static void M244Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M244Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper244_Init(CartInfo *info) { + info->Power = M244Power; + AddExState(StateRegs, ~0, 0, NULL); + GameStateRestore = StateRestore; +} diff --git a/src/mappers/mapper245.c b/src/mappers/mapper245.c new file mode 100644 index 000000000..419a81d52 --- /dev/null +++ b/src/mappers/mapper245.c @@ -0,0 +1,61 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M245PW(uint16 A, uint16 V) { + setprg8(A, ((mmc3.reg[0] & 0x02) << 5) | (V & 0x3F)); +} + +static void M245CW(uint16 A, uint16 V) { + setchr8(0); +} + +static DECLFW(M245Write) { + if (A & 0x01) { + mmc3.reg[mmc3.cmd & 0x07] = V; + } else { + mmc3.cmd = V; + } + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M245Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x8000, 0x9FFF, M245Write); +} + +void Mapper245_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + info->Power = M245Power; + MMC3_pwrap = M245PW; + MMC3_cwrap = M245CW; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper246.c b/src/mappers/mapper246.c new file mode 100644 index 000000000..ecc161fdc --- /dev/null +++ b/src/mappers/mapper246.c @@ -0,0 +1,99 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[4]; +static uint8 chr[4]; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 4, "CREG" }, + { 0 } +}; + +static void Sync(void) { + setprg2r(0x10, 0x6800, 0); + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, prg[3]); + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr2(0x1000, chr[2]); + setchr2(0x1800, chr[3]); +} + +static DECLFR(M246Read) { + if ((A & 0xFFE4) == 0xFFE4) { + size_t prgOffset = ((prg[3] | 0x10) << 13) | 0x1000 | (A & 0xFFF); + return PRGptr[0][prgOffset & 0x7FFFF]; + } + return CartBR(A); +} + +static DECLFW(M246Write) { + if (A & 0x04) { + chr[A & 0x03] = V; + Sync(); + } else { + prg[A & 0x03] = V; + Sync(); + } +} + +static void M246Power(void) { + prg[0] = 0; + prg[1] = 1; + prg[2] = ~1; + prg[3] = ~0; + Sync(); + + SetReadHandler(0x6800, 0x6FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, M246Read); + SetWriteHandler(0x6000, 0x67FF, M246Write); + SetWriteHandler(0x6800, 0x6FFF, CartBW); + + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M246Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper246_Init(CartInfo *info) { + info->Power = M246Power; + info->Close = M246Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 2048; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } +} diff --git a/src/mappers/mapper249.c b/src/mappers/mapper249.c new file mode 100644 index 000000000..dbdc25e37 --- /dev/null +++ b/src/mappers/mapper249.c @@ -0,0 +1,89 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static uint32 scrambleBankOrder(uint32 V, const uint8 *source, const uint8 *target, uint32 length) { + uint32 bank = 0; + uint32 bit = 0; + + for (bit = 0; bit < 8; bit++) { + if (V & (0x01 << bit)) { + uint32 index = 0; + + for (index = 0; index < length; index++) { + if (source[index] == bit) { + break; + } + } + bank |= (0x01 << (index == length ? bit : target[index])); + } + } + return bank; +} + +static void M249PW(uint16 A, uint16 V) { + static const uint8 prg_pattern[4][4] = { + { 3, 4, 2, 1 }, + { 4, 3, 1, 2 }, + { 1, 2, 3, 4 }, + { 2, 1, 4, 3 }, + }; + uint32 bank = scrambleBankOrder(V, prg_pattern[reg & 0x03], prg_pattern[(iNESCart.mapper == 249) ? 0 : 2], 4); + setprg8(A, bank); +} + +static void M249CW(uint16 A, uint16 V) { + static const uint8 chr_pattern[8][6] = { + { 5, 2, 6, 7, 4, 3 }, + { 4, 5, 3, 2, 7, 6 }, + { 2, 3, 4, 5, 6, 7 }, + { 6, 4, 2, 3, 7, 5 }, + { 5, 3, 7, 6, 2, 4 }, + { 4, 2, 5, 6, 7, 3 }, + { 3, 6, 4, 5, 2, 7 }, + { 2, 5, 6, 7, 3, 4 }, + }; + uint32 bank = scrambleBankOrder(V, chr_pattern[reg & 0x07], chr_pattern[(iNESCart.mapper == 249) ? 0 : 2], 6); + setchr1(A, bank); +} + +static DECLFW(M249Write) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M249Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x5000, 0x5FFF, M249Write); +} + +void Mapper249_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + MMC3_cwrap = M249CW; + MMC3_pwrap = M249PW; + info->Power = M249Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper250.c b/src/mappers/mapper250.c new file mode 100644 index 000000000..0d1afd1d1 --- /dev/null +++ b/src/mappers/mapper250.c @@ -0,0 +1,36 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static DECLFW(M250Write) { + MMC3_Write(((A & 0xE000) | ((A & 0x400) >> 10)), (A & 0xFF)); +} + +static void M250Power(void) { + MMC3_Power(); + SetWriteHandler(0x8000, 0xFFFF, M250Write); +} + +void Mapper250_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + info->Power = M250Power; +} diff --git a/src/mappers/mapper252.c b/src/mappers/mapper252.c new file mode 100644 index 000000000..cf4f5cbe1 --- /dev/null +++ b/src/mappers/mapper252.c @@ -0,0 +1,93 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 maskCHRCompare; +static uint8 maskCHRBank; + +static writefunc writePPU; +extern uint32 RefreshAddr; + +static void M252PW(uint16 A, uint16 V) { + setprg8(A, V & 0x1F); +} + +static void M252CW(uint16 A, uint16 V) { + if ((V & maskCHRBank) == maskCHRCompare) { + setchr1r(0x10, A, V & 0x01); + } else { + setchr1(A, V); + } +} + +static DECLFW(M252PPU_B2007) { + if (RefreshAddr < 0x2000) { + switch (vrc24.chr[RefreshAddr >> 10]) { + case 0x88: + maskCHRBank = 0xFC; + maskCHRCompare = 0x4C; + break; + case 0xC2: + maskCHRBank = 0xFE; + maskCHRCompare = 0x7C; + break; + case 0xC8: + maskCHRBank = 0xFE; + maskCHRCompare = 0x04; + break; + } + } + writePPU(A, V); +} + +static void M252Close(void) { + VRC24_Close(); +} + +static void M252Power(void) { + if (iNESCart.mapper == 252) { + maskCHRBank = 0xFE; + maskCHRCompare = 0x06; + } else { + maskCHRBank = 0xFE; + maskCHRCompare = 0x04; + } + VRC24_Power(); + + writePPU = GetWriteHandler(0x2007); + SetWriteHandler(0x2007, 0x2007, M252PPU_B2007); +} + +void Mapper252_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x04, 0x08, TRUE, TRUE); + VRC24_pwrap = M252PW; + VRC24_cwrap = M252CW; + + info->Power = M252Power; + info->Close = M252Close; + + CHRRAMSIZE = 2048; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); +} diff --git a/src/mappers/mapper254.c b/src/mappers/mapper254.c new file mode 100644 index 000000000..e39d633fe --- /dev/null +++ b/src/mappers/mapper254.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static DECLFR(M254ReadWRAM) { + if (reg == TRUE) { + return CPU_OPENBUS ^ (reg * 0x80); + } + return CartBR(A); +} + +static DECLFW(M254WriteWRAM) { + if (V & 0x01) { + reg = FALSE; + } + CartBW(A, V); +} + +static void M254Reset(void) { + reg = TRUE; + MMC3_FixCHR(); + MMC3_FixPRG(); +} + +static void M254Power(void) { + reg = 0x80; + MMC3_Power(); + SetReadHandler(0x6000, 0x7FFF, M254ReadWRAM); + SetWriteHandler(0x6000, 0x7FFF, M254WriteWRAM); +} + +void Mapper254_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + info->Power = M254Power; + info->Reset = M254Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper256.c b/src/mappers/mapper256.c new file mode 100644 index 000000000..8c13f068a --- /dev/null +++ b/src/mappers/mapper256.c @@ -0,0 +1,418 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007-2010 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VR02/VT03 Console and OneBus System + * + * Street Dance (Dance pad) (Unl) + * 101-in-1 Arcade Action II + * DreamGEAR 75-in-1, etc. + * + */ + +#include "mapinc.h" + +static uint8 submapper; + +/* General Purpose Registers */ +static uint8 cpu410x[16], ppu201x[16], apu40xx[64]; + +/* IRQ Registers */ +static uint8 IRQCount, IRQa, IRQReload; +#define IRQLatch cpu410x[0x1] /* accc cccc, a = 0, AD12 switching, a = 1, HSYNC switching */ + +/* MMC3 Registers */ +#define mmc3cmd cpu410x[0x5] /* pcv- ----, p - program swap, c - video swap, v - internal VRAM enable */ +#define mirror cpu410x[0x6] /* ---- ---m, m = 0 - H, m = 1 - V */ + +/* APU Registers */ +static uint8 pcm_enable = 0, pcm_irq = 0; +static int16 pcm_addr, pcm_size, pcm_latch, pcm_clock = 0xE1; + +static writefunc defapuwrite[64]; +static readfunc defapuread[64]; + +static SFORMAT StateRegs[] = +{ + { cpu410x, 16, "REGC" }, + { ppu201x, 16, "REGS" }, + { apu40xx, 64, "REGA" }, + { &IRQReload, 1, "IRQR" }, + { &IRQCount, 1, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { &pcm_enable, 1, "PCME" }, + { &pcm_irq, 1, "PCMI" }, + { &pcm_addr, 2, "PCMA" }, + { &pcm_size, 2, "PCMS" }, + { &pcm_latch, 2, "PCML" }, + { &pcm_clock, 2, "PCMC" }, + { 0 } +}; + +static void PSync(void) { + uint8 bankmode = cpu410x[0xb] & 7; + uint8 mask = (bankmode == 0x7) ? (0xff) : (0x3f >> bankmode); + uint32 block = ((cpu410x[0x0] & 0xf0) << 4) + (cpu410x[0xa] & (~mask)); + uint32 pswap = (mmc3cmd & 0x40) << 8; + +#if 0 + uint8 bank0 = (cpu410x[0xb] & 0x40)?(~1):(cpu410x[0x7]); + uint8 bank1 = cpu410x[0x8]; + uint8 bank2 = (cpu410x[0xb] & 0x40)?(cpu410x[0x9]):(~1); + uint8 bank3 = ~0; +#endif + uint8 bank0 = cpu410x[0x7]; + uint8 bank1 = cpu410x[0x8]; + uint8 bank2 = (cpu410x[0xb] & 0x40) ? (cpu410x[0x9]) : (~1); + uint8 bank3 = ~0; + +/* FCEU_printf(" PRG: %04x [%02x]",0x8000^pswap,block | (bank0 & mask)); */ + setprg8(0x8000 ^ pswap, block | (bank0 & mask)); +/* FCEU_printf(" %04x [%02x]",0xa000^pswap,block | (bank1 & mask)); */ + setprg8(0xa000, block | (bank1 & mask)); +/* FCEU_printf(" %04x [%02x]",0xc000^pswap,block | (bank2 & mask)); */ + setprg8(0xc000 ^ pswap, block | (bank2 & mask)); +/* FCEU_printf(" %04x [%02x]\n",0xe000^pswap,block | (bank3 & mask)); */ + setprg8(0xe000, block | (bank3 & mask)); +} + +static void CSync(void) { + static const uint8 midx[8] = { 0, 1, 2, 0, 3, 4, 5, 0 }; + uint8 mask = 0xff >> midx[ppu201x[0xa] & 7]; + uint32 block = ((cpu410x[0x0] & 0x0f) << 11) + ((ppu201x[0x8] & 0x70) << 4) + (ppu201x[0xa] & (~mask)); + uint32 cswap = (mmc3cmd & 0x80) << 5; + + uint8 bank0 = ppu201x[0x6] & (~1); + uint8 bank1 = ppu201x[0x6] | 1; + uint8 bank2 = ppu201x[0x7] & (~1); + uint8 bank3 = ppu201x[0x7] | 1; + uint8 bank4 = ppu201x[0x2]; + uint8 bank5 = ppu201x[0x3]; + uint8 bank6 = ppu201x[0x4]; + uint8 bank7 = ppu201x[0x5]; + + setchr1(0x0000 ^ cswap, block | (bank0 & mask)); + setchr1(0x0400 ^ cswap, block | (bank1 & mask)); + setchr1(0x0800 ^ cswap, block | (bank2 & mask)); + setchr1(0x0C00 ^ cswap, block | (bank3 & mask)); + setchr1(0x1000 ^ cswap, block | (bank4 & mask)); + setchr1(0x1400 ^ cswap, block | (bank5 & mask)); + setchr1(0x1800 ^ cswap, block | (bank6 & mask)); + setchr1(0x1C00 ^ cswap, block | (bank7 & mask)); + + setmirror((mirror ^ 1) & 1); +} + +static void Sync(void) { + PSync(); + CSync(); +} + +static const uint8 cpuMangle[16][4] = { + { 0, 1, 2, 3 }, /* Submapper 0: Normal */ + { 0, 1, 2, 3 }, /* Submapper 1: Waixing VT03 */ + { 1, 0, 2, 3 }, /* Submapper 2: Trump Grand */ + { 0, 1, 2, 3 }, /* Submapper 3: Zechess */ + { 0, 1, 2, 3 }, /* Submapper 4: Qishenglong */ + { 0, 1, 2, 3 }, /* Submapper 5: Waixing VT02 */ + { 0, 1, 2, 3 }, /* Submapper 6: unused so far */ + { 0, 1, 2, 3 }, /* Submapper 7: unused so far */ + { 0, 1, 2, 3 }, /* Submapper 8: unused so far */ + { 0, 1, 2, 3 }, /* Submapper 9: unused so far */ + { 0, 1, 2, 3 }, /* Submapper A: unused so far */ + { 0, 1, 2, 3 }, /* Submapper B: unused so far */ + { 0, 1, 2, 3 }, /* Submapper C: unused so far */ + { 0, 1, 2, 3 }, /* Submapper D: Cube Tech (CPU opcode encryption only) */ + { 0, 1, 2, 3 }, /* Submapper E: Karaoto (CPU opcode encryption only) */ + { 0, 1, 2, 3 } /* Submapper F: Jungletac (CPU opcode encryption only) */ +}; +static DECLFW(M256WriteCPU410X) { + /* FCEU_printf("CPU %04x:%04x\n",A,V); */ + A &= 0xF; + switch (A) { + case 0x1: + IRQLatch = V & 0xfe; + break; /* �� �� �������� */ + case 0x2: + IRQReload = 1; + break; + case 0x3: + X6502_IRQEnd(FCEU_IQEXT); + IRQa = 0; + break; + case 0x4: + IRQa = 1; + break; + default: + if (A >= 0x7 && A <= 0xA) + A = 0x7 + cpuMangle[submapper][A - 0x7]; + cpu410x[A] = V; + Sync(); + } +} + +static const uint8 ppuMangle[16][6] = { + { 0, 1, 2, 3, 4, 5 }, /* Submapper 0: Normal */ + { 1, 0, 5, 4, 3, 2 }, /* Submapper 1: Waixing VT03 */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper 2: Trump Grand */ + { 5, 4, 3, 2, 0, 1 }, /* Submapper 3: Zechess */ + { 2, 5, 0, 4, 3, 1 }, /* Submapper 4: Qishenglong */ + { 1, 0, 5, 4, 3, 2 }, /* Submapper 5: Waixing VT02 */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper 6: unused so far */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper 7: unused so far */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper 8: unused so far */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper 9: unused so far */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper A: unused so far */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper B: unused so far */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper C: unused so far */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper D: Cube Tech (CPU opcode encryption only) */ + { 0, 1, 2, 3, 4, 5 }, /* Submapper E: Karaoto (CPU opcode encryption only) */ + { 0, 1, 2, 3, 4, 5 } /* Submapper F: Jungletac (CPU opcode encryption only) */ +}; +static DECLFW(M256WritePPU201X) { + /* FCEU_printf("PPU %04x:%04x\n",A,V); */ + A &= 0x0F; + if (A >= 2 && A <= 7) + A = 2 + ppuMangle[submapper][A - 2]; + ppu201x[A] = V; + Sync(); +} + +static const uint8 mmc3Mangle[16][8] = { + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 0: Normal */ + { 5, 4, 3, 2, 1, 0, 6, 7 }, /* Submapper 1: Waixing VT03 */ + { 0, 1, 2, 3, 4, 5, 7, 6 }, /* Submapper 2: Trump Grand */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 3: Zechess */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 4: Qishenglong */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 5: Waixing VT02 */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 6: unused so far */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 7: unused so far */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 8: unused so far */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 9: unused so far */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper A: unused so far */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper B: unused so far */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper C: unused so far */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper D: Cube Tech (CPU opcode encryption only) */ + { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper E: Karaoto (CPU opcode encryption only) */ + { 0, 1, 2, 3, 4, 5, 6, 7 } /* Submapper F: Jungletac (CPU opcode encryption only) */ +}; +static DECLFW(M256WriteMMC3) { + /* FCEU_printf("MMC %04x:%04x\n",A,V); */ + switch (A & 0xe001) { + case 0x8000: + V = (V & 0xF8) | mmc3Mangle[submapper][V & 0x07]; + mmc3cmd = (mmc3cmd & 0x38) | (V & 0xc7); + Sync(); + break; + case 0x8001: { + switch (mmc3cmd & 7) { + case 0: + ppu201x[0x6] = V; + CSync(); + break; + case 1: + ppu201x[0x7] = V; + CSync(); + break; + case 2: + ppu201x[0x2] = V; + CSync(); + break; + case 3: + ppu201x[0x3] = V; + CSync(); + break; + case 4: + ppu201x[0x4] = V; + CSync(); + break; + case 5: + ppu201x[0x5] = V; + CSync(); + break; + case 6: + cpu410x[0x7] = V; + PSync(); + break; + case 7: + cpu410x[0x8] = V; + PSync(); + break; + } + break; + } + case 0xa000: + mirror = V; + CSync(); + break; + case 0xc000: + IRQLatch = V & 0xfe; + break; + case 0xc001: + IRQReload = 1; + break; + case 0xe000: + X6502_IRQEnd(FCEU_IQEXT); + IRQa = 0; + break; + case 0xe001: + IRQa = 1; + break; + } +} + +static void M256IRQHook(void) { + uint32 count = IRQCount; + if (!count || IRQReload) { + IRQCount = IRQLatch; + IRQReload = 0; + } else + IRQCount--; + if (count && !IRQCount) { + if (IRQa) + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static DECLFW(M256WriteAPU40XX) { +/* if(((A & 0x3f)!=0x16) && ((apu40xx[0x30] & 0x10) || ((A & 0x3f)>0x17)))FCEU_printf("APU %04x:%04x\n",A,V); */ + apu40xx[A & 0x3f] = V; + switch (A & 0x3f) { + case 0x12: + if (apu40xx[0x30] & 0x10) { + pcm_addr = V << 6; + } + break; + case 0x13: + if (apu40xx[0x30] & 0x10) { + pcm_size = (V << 4) + 1; + } + break; + case 0x15: + if (apu40xx[0x30] & 0x10) { + pcm_enable = V & 0x10; + if (pcm_irq) { + X6502_IRQEnd(FCEU_IQEXT); + pcm_irq = 0; + } + if (pcm_enable) + pcm_latch = pcm_clock; + V &= 0xef; + } + break; + } + defapuwrite[A & 0x3f](A, V); +} + +static DECLFR(M256ReadAPU40XX) { + uint8 result = defapuread[A & 0x3f](A); +/* FCEU_printf("read %04x, %02x\n",A,result); */ + switch (A & 0x3f) { + case 0x15: + if (apu40xx[0x30] & 0x10) { + result = (result & 0x7f) | pcm_irq; + } + break; + } + return result; +} + +static void M256CpuHook(int a) { + if (pcm_enable) { + pcm_latch -= a; + if (pcm_latch <= 0) { + pcm_latch += pcm_clock; + pcm_size--; + if (pcm_size < 0) { + pcm_irq = 0x80; + pcm_enable = 0; + X6502_IRQBegin(FCEU_IQEXT); + } else { + uint16 addr = pcm_addr | ((apu40xx[0x30] ^ 3) << 14); + uint8 raw_pcm = ARead[addr](addr) >> 1; + defapuwrite[0x11](0x4011, raw_pcm); + pcm_addr++; + pcm_addr &= 0x7FFF; + } + } + } +} + +static void M256Power(void) { + uint32 i; + IRQReload = IRQCount = IRQa = 0; + + memset(cpu410x, 0x00, sizeof(cpu410x)); + memset(ppu201x, 0x00, sizeof(ppu201x)); + memset(apu40xx, 0x00, sizeof(apu40xx)); + + SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0); + + for (i = 0; i < 64; i++) { + defapuread[i] = GetReadHandler(0x4000 | i); + defapuwrite[i] = GetWriteHandler(0x4000 | i); + } + SetReadHandler(0x4000, 0x403f, M256ReadAPU40XX); + SetWriteHandler(0x4000, 0x403f, M256WriteAPU40XX); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x2010, 0x201f, M256WritePPU201X); + SetWriteHandler(0x4100, 0x410f, M256WriteCPU410X); + SetWriteHandler(0x8000, 0xffff, M256WriteMMC3); + + FCEU_CheatAddRAM(8, 0x6000, WRAM); + setprg8r(0x10, 0x6000, 0); + Sync(); +} + +static void M256Reset(void) { + IRQReload = IRQCount = IRQa = 0; + + memset(cpu410x, 0x00, sizeof(cpu410x)); + memset(ppu201x, 0x00, sizeof(ppu201x)); + memset(apu40xx, 0x00, sizeof(apu40xx)); + + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M256Close(void) { +} + +void Mapper256_Init(CartInfo *info) { + info->Power = M256Power; + info->Reset = M256Reset; + info->Close = M256Close; + + if (info->iNES2) + submapper = info->submapper; + else + submapper = (((*(uint32 *)&(info->MD5)) == 0x305fcdc3) || ((*(uint32 *)&(info->MD5)) == 0x6abfce8e)) ? 2 : 0; /* PowerJoy Supermax Carts */ + + GameHBIRQHook = M256IRQHook; + MapIRQHook = M256CpuHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAM = (uint8 *)FCEU_gmalloc(8192); + SetupCartPRGMapping(0x10, WRAM, 8192, 1); +} diff --git a/src/mappers/mapper257.c b/src/mappers/mapper257.c new file mode 100644 index 000000000..5d19d90d8 --- /dev/null +++ b/src/mappers/mapper257.c @@ -0,0 +1,123 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[8]; +static uint32 lastnt = 0; + +static SFORMAT StateRegs[] = +{ + { reg, 2, "REG" }, + { &lastnt, 4, "LNT" }, + { 0 } +}; + +static uint8 bs_tbl[128] = { + 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, /* 00 */ + 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, /* 10 */ + 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, /* 20 */ + 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, /* 30 */ + 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, /* 40 */ + 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, /* 50 */ + 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x00, 0x10, 0x20, 0x30, /* 60 */ + 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, /* 70 */ +}; + +static uint8 br_tbl[16] = { + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, +}; + +static void Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + if(PRGsize[0] == 512 * 1024) { + if(reg[0] & 0x010) { + setprg32(0x8000, reg[0] & 7); + } else { + if(reg[0] & 0x40) + setprg8(0x8000, (reg[0] & 0x0F) | 0x20 | ((reg[0] & 0x20) >> 1)); + } + if((reg[0] & 0x18) == 0x18) + setmirror(MI_H); + else + setmirror(MI_V); + } else { + setprg16(0x8000, bs_tbl[reg[0] & 0x7f] >> 4); + setprg16(0xc000, bs_tbl[reg[0] & 0x7f] & 0xf); + setmirror(MI_V); + } +} + +static DECLFW(M257Write) { + reg[(A & 0x700) >> 8] = V; + PEC586Hack = (reg[0] & 0x80) ? TRUE : FALSE; +/* FCEU_printf("bs %04x %02x\n", A, V); */ + Sync(); +} + +static DECLFR(M257Read) { +/* FCEU_printf("read %04x\n", A); */ + return (CPU_OPENBUS & 0xD8) | br_tbl[reg[4] >> 4]; +} + +static DECLFR(M257ReadHi) { + if((reg[0] & 0x10) || ((reg[0] & 0x40) && (A < 0xA000))) + return CartBR(A); + else + return PRGptr[0][((0x0107 | ((A >> 7) & 0x0F8)) << 10) | (A & 0x3FF)]; +} + +static void M257Power(void) { + if(PRGsize[0] == 512 * 1024) + reg[0] = 0x00; + else + reg[0] = 0x0E; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + if(PRGsize[0] == 512 * 1024) + SetReadHandler(0x8000, 0xFFFF, M257ReadHi); + else + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5fff, M257Write); + SetReadHandler(0x5000, 0x5fff, M257Read); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M257Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper257_Init(CartInfo *info) { + info->Power = M257Power; + info->Close = M257Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper259.c b/src/mappers/mapper259.c new file mode 100644 index 000000000..d12bd4579 --- /dev/null +++ b/src/mappers/mapper259.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 259 - BMC-F-15 + * BMC F-15 PCB (256+266 MMC3 based, with 16/32Kb banking discrete logic) + * 150-in-1 Unchaied Melody FIGHT version with system test (START+SELECT) + * + * CHR - MMC3 stock regs + * PRG - MMC3 regs disabled, area 6000-7FFF used instead + * 011xxxxxxxxxxxxx addr mask, + * ----APPp reg bits mask + * A - higher 128K PRG bank select/32K bank mode override + * PP - bank number in 32K mode + * PPp - bank number in 16K mode + * initial state of extra regs is undefined, A001 enables/disables the 6000 area + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M259PW(uint16 A, uint16 V) { + uint8 mode = (reg & 0x08) >> 3; + + setprg16(0x8000, ((reg & 0x0F) & ~mode)); + setprg16(0xC000, ((reg & 0x0F) | mode)); +} + +static DECLFW(M259Write) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + } +} + +static void M259Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M259Write); +} + +void Mapper259_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M259PW; + info->Power = M259Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper260.c b/src/mappers/mapper260.c new file mode 100644 index 000000000..e0f221c1e --- /dev/null +++ b/src/mappers/mapper260.c @@ -0,0 +1,119 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2017 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +/* added on 2019-5-23 - NES 2.0 Mapper 260 + * HP10xx/HP20xx - a simplified version of FK23C mapper with pretty strict and better + * organized banking behaviour. It seems that some 176 mapper assigned game may be + * actually this kind of board instead but in common they aren't compatible at all, + * the games on the regular FK23C boards couldn't run on this mapper and vice versa... + */ + +static uint8 reg[4]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M260CW(uint16 A, uint16 V) { + uint16 base = reg[2] & 0x7F; + + switch (reg[0] & 0x07) { + case 0: setchr1(A, ((base << 3) & ~0xFF) | (V & 0xFF)); break; + case 1: setchr1(A, ((base << 3) & ~0x7F) | (V & 0x7F)); break; + case 2: setchr1(A, ((base << 3) & ~0xFF) | (V & 0xFF)); break; + case 3: setchr1(A, ((base << 3) & ~0x7F) | (V & 0x7F)); break; + case 4: setchr8(base); break; + case 5: setchr8(base); break; + case 6: setchr8((base & ~0x01) | (reg[3] & 0x01)); break; + case 7: setchr8((base & ~0x03) | (reg[3] & 0x03)); break; + } +} + +static void M260PW(uint16 A, uint16 V) { + uint8 base = reg[1] & 0x3F; + + switch (reg[0] & 0x07) { + case 0: setprg8(A, ((base << 1) & ~0x1F) | (V & 0x1F)); break; + case 1: setprg8(A, ((base << 1) & ~0x1F) | (V & 0x1F)); break; + case 2: setprg8(A, ((base << 1) & ~0x0F) | (V & 0x0F)); break; + case 3: setprg8(A, ((base << 1) & ~0x0F) | (V & 0x0F)); break; + case 4: + setprg16(0x8000, base); + setprg16(0xC000, base); + break; + case 5: setprg32(0x8000, base >> 1); break; + case 6: setprg32(0x8000, base >> 1); break; + case 7: setprg32(0x8000, base >> 1); break; + } +} + +static DECLFR(M260Read) { + return ((CPU_OPENBUS & ~0x03) | (dipsw & 0x03)); +} + +static DECLFW(M260WriteReg) { + if (!(reg[0] & 0x80)) { + reg[A & 0x03] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static DECLFW(M260WriteLatch) { + if((reg[0] & 0xE6) == 0x06 ) { + reg[3] = V; + MMC3_FixCHR(); + } else { + MMC3_Write(A, V); + } +} + +static void M260Reset(void) { + dipsw++; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Reset(); + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M260Power(void) { + dipsw = 0; + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Power(); + SetReadHandler(0x5000, 0x5FFF, M260Read); + SetWriteHandler(0x5000, 0x5FFF, M260WriteReg); + SetWriteHandler(0x8000, 0xFFFF, M260WriteLatch); +} + +void Mapper260_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M260CW; + MMC3_pwrap = M260PW; + info->Power = M260Power; + info->Reset = M260Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper261.c b/src/mappers/mapper261.c new file mode 100644 index 000000000..589741dc8 --- /dev/null +++ b/src/mappers/mapper261.c @@ -0,0 +1,40 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 261 - BMC810544-C-A1 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x40) + setprg32(0x8000, latch.addr >> 7); + else { + setprg16(0x8000, ((latch.addr >> 6) & 0x0E) | ((latch.addr >> 5) & 0x01)); + setprg16(0xC000, ((latch.addr >> 6) & 0x0E) | ((latch.addr >> 5) & 0x01)); + } + setchr8(latch.addr & 0x0F); + setmirror(((latch.addr >> 4) & 0x01) ^ 0x01); +} + +void Mapper261_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper262.c b/src/mappers/mapper262.c new file mode 100644 index 000000000..be94d5c34 --- /dev/null +++ b/src/mappers/mapper262.c @@ -0,0 +1,89 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 262 - UNL-SHERO */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M262CW(uint16 A, uint16 V) { + if (reg & 0x40) { + setchr8r(0x10, 0); + } else { + uint8 lsh[] = { 3, 2, 0, 1 }; + uint8 bank = (A >> 11) & 0x03; + + setchr1(A, (((reg >> lsh[bank]) << 8) & 0x100) | (V & 0xFF)); + } +} + +static DECLFW(M262Write) { + if (A & 0x100) { + reg = V; + MMC3_FixCHR(); + } +} + +static DECLFR(M262Read) { + if (A & 0x100) { + return(dipsw); + } + return CPU_OPENBUS; +} + +static void M262Reset(void) { + MMC3_Reset(); + dipsw ^= 0xFF; +} + +static void M262Power(void) { + dipsw = 0x00; + MMC3_Power(); + SetWriteHandler(0x4100, 0x4FFF, M262Write); + SetReadHandler(0x4100, 0x4FFF, M262Read); +} + +static void M262Close(void) { + MMC3_Close(); +} + +void Mapper262_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M262CW; + info->Power = M262Power; + info->Reset = M262Reset; + info->Close = M262Close; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper263.c b/src/mappers/mapper263.c new file mode 100644 index 000000000..053033b95 --- /dev/null +++ b/src/mappers/mapper263.c @@ -0,0 +1,47 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 263 - UNL-KOF97 */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint32 unscrambleAddr(uint32 A) { + return ((A & 0xE000) | ((A >> 12) & 0x01)); +} + +static uint8 unscrambleData(uint8 V) { + return ((V & 0xD8) | ((V & 0x20) >> 4) | ((V & 0x04) << 3) | ((V & 0x02) >> 1) | ((V & 0x01) << 2)); +} + +static DECLFW(M263Write) { + MMC3_Write(unscrambleAddr(A), unscrambleData(V)); +} + +static void M263Power(void) { + MMC3_Power(); + SetWriteHandler(0x8000, 0xFFFF, M263Write); +} + +void Mapper263_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + info->Power = M263Power; +} diff --git a/src/mappers/mapper265.c b/src/mappers/mapper265.c new file mode 100644 index 000000000..c8188af0c --- /dev/null +++ b/src/mappers/mapper265.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 265 - BMC-T-262 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 bank = ((latch.addr >> 3) & 0x60) | ((latch.addr >> 2) & 0x18) | (latch.data & 0x07); + + if (latch.addr & 0x80) { + if (!bank) { + /* NOTE: Unofficial support but Tetris II in 11-in-1 variant + works as if its NROM-256 */ + setprg32(0x8000, bank >> 1); + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank | 0x07); + } + setchr8(0); + setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); +} + +static DECLFW(M265Write) { + if (!(latch.addr & 0x2000)) { + latch.addr = A; + } + latch.data = V; + Sync(); +} + +static void M265Power(void) { + Latch_Power(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M265Write); +} + +void Mapper265_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M265Power; + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper266.c b/src/mappers/mapper266.c new file mode 100644 index 000000000..481b78392 --- /dev/null +++ b/src/mappers/mapper266.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * City Fighter IV sith Sound VRC4 hacked + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 reg; +static writefunc pcm; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M266PW(uint16 A, uint16 V) { + setprg32(0x8000, reg >> 2); +} + +static DECLFW(M266Write) { + /* FCEU_printf("%04x %02x",A,V); */ + A = (A & 0x9FFF) | ((A << 1) & 0x4000) | ((A >> 1) & 0x2000); + VRC24_Write(A, V); +} + +static void M266WriteMisc(uint16 A, uint8 V) { + if (A & 0x800) { + pcm(0x4011, (V & 0x0F) << 3); + } else { + reg = V & 0x0C; + VRC24_FixPRG(); + } +} + +static void M266Power(void) { + reg = 0; + VRC24_Power(); + pcm = GetWriteHandler(0x4011); + SetWriteHandler(0x8000, 0xFFFF, M266Write); +} + +void Mapper266_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x04, 0x08, FALSE, TRUE); + info->Power = M266Power; + VRC24_pwrap = M266PW; + VRC24_miscWrite = M266WriteMisc; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper267.c b/src/mappers/mapper267.c new file mode 100644 index 000000000..8facccc71 --- /dev/null +++ b/src/mappers/mapper267.c @@ -0,0 +1,69 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 267 - 8-in-1 JY-119 */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M267CW(uint16 A, uint16 V) { + uint16 base = ((reg & 0x20) >> 2) | (reg & 0x06); + + setchr1(A, (base << 6) | (V & 0x7F)); +} + +static void M267PW(uint16 A, uint16 V) { + uint16 base = ((reg & 0x20) >> 2) | (reg & 0x06); + + setprg8(A, (base << 4) | (V & 0x1F)); +} + +static DECLFW(M267Write) { + if (MMC3_WramIsWritable()) { + if (!(reg & 0x80)) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } + } +} + +static void M267Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M267Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x6FFF, M267Write); +} + +void Mapper267_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M267CW; + MMC3_pwrap = M267PW; + info->Reset = M267Reset; + info->Power = M267Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper268.c b/src/mappers/mapper268.c new file mode 100644 index 000000000..61b5db0c0 --- /dev/null +++ b/src/mappers/mapper268.c @@ -0,0 +1,210 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[8]; + +static void M268CW(uint16 A, uint16 V) { + uint16 base = ((reg[0] << 4) & 0x380) | ((reg[2] << 3) & 0x078); + uint16 mask = (reg[0] & 0x80) ? 0x7F : 0xFF; + uint8 vram = CHRRAM && (reg[4] & 0x01) && ((V & 0xFE) == (reg[4] & 0xFE)); + + /* CHR-RAM write protect on submapper 8/9) */ + if ((iNESCart.submapper & ~1) == 8) { + if (reg[0] & 0x10) { + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 1); + } else { + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 0); + } + } + + if (reg[3] & 0x10) { + /* GNROM */ + mask = 0x07; + V = A >> 10; + } + setchr1r(vram ? 0x10 : 0x00, A, (base & ~mask) | (V & mask)); +} + +static void M268PW(uint16 A, uint16 V) { + uint16 base; + uint16 mask = 0x0F /* PRG A13-A16 */ + | ((~reg[0] >> 2) & 0x10) /* PRG A17 */ + | ((~reg[1] >> 2) & 0x20) /* PRG A18 */ + | ((reg[1] >> 0) & 0x40) /* PRG A19 */ + | ((reg[1] << 2) & 0x80) /* PRG A20 */ + ; + + switch (iNESCart.submapper & ~1) { + default: /* Original implementation */ + base = (reg[3] & 0x0E) | ((reg[0] << 4) & 0x70) | ((reg[1] << 3) & 0x80) | + ((reg[1] << 6) & 0x300) | ((reg[0] << 6) & 0xC00); + break; + case 2: /* Later revision with different arrangement of register 1 */ + base = (reg[3] & 0x0E) | ((reg[0] << 4) & 0x70) | ((reg[1] << 4) & 0x80) | + ((reg[1] << 6) & 0x100) | ((reg[1] << 8) & 0x200) | ((reg[0] << 6) & 0xC00); + break; + case 4: /* LD622D: PRG A20-21 moved to register 0 */ + base = (reg[3] & 0x0E) | ((reg[0] << 4) & 0x70) | ((reg[0] << 3) & 0x180); + break; + case 6: /* J-852C: CHR A17 selects between two PRG chips */ + base = (reg[3] & 0x0E) | ((reg[0] << 4) & 0x70) | ((reg[1] << 3) & 0x80) | + ((reg[1] << 6) & 0x300) | ((reg[0] << 6) & 0xC00); + base &= PRG_BANK_COUNT(16) - 1; + if ((reg[0] & 0x80) ? !!(reg[0] & 0x08) : !!(mmc3.reg[0] & 0x80)) { + base |= PRG_BANK_COUNT(16); + } + break; + } + if (reg[3] & 0x10) { + /* GNROM */ + switch (iNESCart.submapper & ~1) { + default: mask = (reg[1] & 0x02) ? 0x03 : 0x01; break; + case 2: mask = (reg[1] & 0x10) ? 0x01 : 0x03; break; + } + V = A >> 13; + } + setprg8(A, (base & ~mask) | (V & mask)); + + if (mmc3.wram & 0x20) { + /* Hack for FS005 games on Mindkids board that only work with emulation. */ + mmc3.wram &= ~0x40; + } +} + +static void M268MIR(void) { + if (!(reg[0] & 0x20)) { + switch (iNESCart.submapper) { + case 10: + case 11: + setmirror(MI_0 + ((reg[0] >> 4) & 0x01)); + break; + default: + setmirror((mmc3.mirr & 0x01) ^ 0x01); + break; + } + } else { + setmirror((mmc3.mirr & 0x01) ^ 0x01); + } +} + +static DECLFR(M268WramRead) { + if (mmc3.wram & 0x80) { + return CartBR(A); + } + return CPU_OPENBUS; +} + +static DECLFW(M268WramWrite) { + if (MMC3_WramIsWritable()) { + CartBW(A, V); + } +} + +static DECLFW(M268Write) { + uint8 index = A & 0x07; + + if (!(iNESCart.submapper & 0x01) && (A >= 0x6000)) { + M268WramWrite(A, V); + } + + if (!(reg[3] & 0x80) || (index == 2)) { + if (index == 2) { + if (reg[2] & 0x80) { + V = (V & 0x0F) | (reg[2] & ~0x0F); + } + V &= 0xF1 | ((~reg[2] >> 3) & 0x0E); + } + reg[index] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } +} + +static void M268Reset(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0x00; + reg[4] = reg[5] = reg[6] = reg[7] = 0x00; + MMC3_Reset(); +} + +static void M268Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0x00; + reg[4] = reg[5] = reg[6] = reg[7] = 0x00; + MMC3_Power(); + SetReadHandler(0x6000, 0x7FFF, M268WramRead); + SetWriteHandler(0x6000, 0x7FFF, M268WramWrite); + if (iNESCart.mapper == 224 || (iNESCart.submapper & 0x01)) { + SetWriteHandler(0x5000, 0x5FFF, M268Write); + } else { + SetWriteHandler(0x6000, 0x7FFF, M268Write); + } +} + +static void M268Close(void) { + MMC3_Close(); +} + +static void Common_Init(CartInfo *info) { + int ws = info->PRGRamSize + info->PRGRamSaveSize; + + MMC3_Init(info, ws / 1024, info->battery); + MMC3_FixMIR = M268MIR; + MMC3_pwrap = M268PW; + MMC3_cwrap = M268CW; + + info->Power = M268Power; + info->Reset = M268Reset; + info->Close = M268Close; + + AddExState(reg, 8, 0, "EXPR"); + + if (CHR_ROM_SIZE_8K) { + CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; + if (CHRRAMSIZE) { + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0x00, "CRAM"); + } + } +} + +void Mapper268_Init(CartInfo *info) { + Common_Init(info); +} + +/* UNIF loader */ + +void COOLBOY_Init(CartInfo *info) { + info->mapper = 268; + info->submapper = 0; + info->PRGRamSize = 8192; + Common_Init(info); +} + +void MINDKIDS_Init(CartInfo *info) { /* M224 */ + info->mapper = 224; + info->submapper = 1; + info->PRGRamSize = 8192; + Common_Init(info); +} + diff --git a/src/mappers/mapper269.c b/src/mappers/mapper269.c new file mode 100644 index 000000000..291cb3a29 --- /dev/null +++ b/src/mappers/mapper269.c @@ -0,0 +1,95 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 269 + * Games Xplosion 121-in-1 + * 15000-in-1 + * 18000-in-1 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; +static uint8 cmd; + +static void M269CW(uint16 A, uint16 V) { + uint16 mask = 0xFF >> (~reg[2] & 0xF); + uint16 base = ((reg[3] << 6) & 0x1000) | ((reg[2] << 4) & 0xF00) | reg[0]; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M269PW(uint16 A, uint16 V) { + uint16 mask = ~reg[3] & 0x3F; + uint16 base = ((reg[3] << 2) & 0x100) | reg[1]; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M269Write5) { + if (!(reg[3] & 0x80)) { + reg[cmd] = V; + cmd = (cmd + 1) & 3; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M269Reset(void) { + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + MMC3_Reset(); +} + +static void M269Power(void) { + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + MMC3_Power(); + SetWriteHandler(0x5000, 0x5FFF, M269Write5); +} + +static uint8 unscrambleCHR(uint8 data) { + return ((data & 0x01) << 6) | ((data & 0x02) << 3) | ((data & 0x04) << 0) | ((data & 0x08) >> 3) | + ((data & 0x10) >> 3) | ((data & 0x20) >> 2) | ((data & 0x40) >> 1) | ((data & 0x80) << 0); +} + +void Mapper269_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_cwrap = M269CW; + MMC3_pwrap = M269PW; + info->Power = M269Power; + info->Reset = M269Reset; + AddExState(reg, 4, 0, "EXPR"); + AddExState(&cmd, 1, 0, "CMD0"); + + if (CHR_ROM_SIZE_8K == 0) { + size_t i; + if (CHR_ROM_DATA) { + FCEU_free(CHR_ROM_DATA); + } + CHR_ROM_DATA = (uint8*)FCEU_malloc(PRGsize[0]); + /* unscramble CHR data from PRG */ + for (i = 0; i < PRGsize[0]; i++) { + CHR_ROM_DATA[i] = unscrambleCHR(PRG_ROM_DATA[i]); + } + SetupCartCHRMapping(0, CHR_ROM_DATA, PRGsize[0], 0); + } +} diff --git a/src/mappers/mapper271.c b/src/mappers/mapper271.c new file mode 100644 index 000000000..2b3448409 --- /dev/null +++ b/src/mappers/mapper271.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.data >> 4); + setchr8(latch.data & 0x0F); + setmirror((latch.data >> 5) & 0x01); +} + +void Mapper271_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper272.c b/src/mappers/mapper272.c new file mode 100644 index 000000000..ec35536a6 --- /dev/null +++ b/src/mappers/mapper272.c @@ -0,0 +1,162 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 272 is used for a bootleg implementation of + * 悪魔城 Special: ぼくDracula君 (Akumajō Special: Boku Dracula-kun). + * + * as implemented from + * https://forums.nesdev.org/viewtopic.php?f=9&t=15302&start=60#p205862 + * + */ + +#include "mapinc.h" + +static uint8 prg[2]; +static uint8 chr[8]; +static uint8 mirr; +static uint8 pal_mirr; +static uint8 IRQCount; +static uint8 IRQa; + +static uint16 lastAddr; + +static SFORMAT StateRegs[] = { + { prg, 2, "PREG" }, + { chr, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { &pal_mirr, 1, "PALM" }, + { &IRQCount, 1, "CNTR" }, + { &IRQa, 1, "CCLK" }, + { &lastAddr, 2, "LADR" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg16(0xC000, ~0); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + if (pal_mirr & 0x02) { + setmirror(MI_0 + (pal_mirr & 0x01)); + } else { + setmirror((mirr & 0x01) ^ 0x01); + } +} + +static DECLFW(M272Write) { + /* writes to VRC chip */ + switch (A & 0xF000) { + case 0x8000: + prg[0] = V; + break; + case 0x9000: + mirr = V; + break; + case 0xA000: + prg[1] = V; + break; + case 0xB000: + case 0xC000: + case 0xD000: + case 0xE000: { + int bank = (((A - 0xB000) >> 11) & 0x06) | ((A >> 1) & 0x01); + if (A & 0x01) { + chr[bank] = (chr[bank] & ~0xF0) | (V << 4); + } else { + chr[bank] = (chr[bank] & ~0x0F) | (V & 0x0F); + } + break; + } + } + + /* writes to PAL chip */ + switch (A & 0xC00C) { + case 0x8004: + pal_mirr = V; + break; + case 0x800c: + X6502_IRQBegin(FCEU_IQEXT); + break; + case 0xc004: + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xc008: + IRQa = 1; + break; + case 0xc00c: + IRQa = 0; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + } + + Sync(); +} + +static void M272Reset(void) { + prg[0] = prg[1] = 0; + chr[0] = chr[1] = chr[2] = chr[3] = 0; + chr[4] = chr[5] = chr[6] = chr[7] = 0; + mirr = pal_mirr = 0; + lastAddr = 0; + IRQCount = 0; + IRQa = 0; + Sync(); +} + +static void M272Power(void) { + M272Reset(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M272Write); +} + +static void M272Hook(uint32 A) { + if ((lastAddr & 0x2000) && !(A & 0x2000)) { + if (IRQa) { + IRQCount++; + if (IRQCount == 84) { + IRQCount = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } + lastAddr = A; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper272_Init(CartInfo *info) { + info->Power = M272Power; + info->Reset = M272Reset; + PPU_hook = M272Hook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper274.c b/src/mappers/mapper274.c new file mode 100644 index 000000000..3370825d7 --- /dev/null +++ b/src/mappers/mapper274.c @@ -0,0 +1,84 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 274 is used for the 90-in-1 Hwang Shinwei multicart. + * Its UNIF board name is BMC-80013-B. + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_274 */ + + /* 2020-03-22 - Update support for Cave Story II, FIXME: Arabian does not work for some reasons... */ + +#include "mapinc.h" + +static uint8 reg[2], extraChip; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &extraChip, 1, "CHIP" }, + { 0 } +}; + +static void Sync(void) { + if (extraChip) { + setprg16(0x8000, 0x80 | (reg[0] & ((PRG_BANK_COUNT(16) - 1) & 0x0F))); + } else { + setprg16(0x8000, (reg[1] & 0x70) | (reg[0] & 0x0F)); + } + setprg16(0xC000, reg[1] & 0x7F); + setchr8(0); + setmirror(((reg[0] >> 4) & 0x01) ^ 0x01); +} + +static DECLFW(M274Write8) { + reg[0] = V; + Sync(); +} + +static DECLFW(M274WriteA) { + reg[1] = V; + extraChip = (A & 0x4000) == 0; + Sync(); +} + +static void M274Power(void) { + reg[0] = reg[1] = 0; + extraChip = 1; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x9FFF, M274Write8); + SetWriteHandler(0xA000, 0xFFFF, M274WriteA); +} + +static void M274Reset(void) { + reg[0] = reg[1] = 0; + extraChip = 1; + Sync(); +} + +static void M274Restore(int version) { + Sync(); +} + +void Mapper274_Init(CartInfo *info) { + info->Power = M274Power; + info->Reset = M274Reset; + GameStateRestore = M274Restore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper277.c b/src/mappers/mapper277.c new file mode 100644 index 000000000..a76640c9a --- /dev/null +++ b/src/mappers/mapper277.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = latch.data & 0x0F; + + if (latch.data & 0x08) { + if (latch.data & 0x01) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { + setprg32(0x8000, prg >> 1); + } + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg | 0x07); + } + setchr8(0); + setmirror(((latch.data >> 4) & 0x01) ^ 0x01); +} + +static DECLFW(M277Write) { + if (!(latch.data & 0x20)) { + Latch_Write(A, V); + } +} + +static void M277Power(void) { + latch.addr = 0; + latch.data = 8; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBROB); + SetWriteHandler(0x8000, 0xFFFF, M277Write); +} + +static void M277Reset(void) { + latch.addr = 0; + latch.data = 8; + Sync(); +} + +void Mapper277_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M277Power; + info->Reset = M277Reset; +} diff --git a/src/mappers/mapper281.c b/src/mappers/mapper281.c new file mode 100644 index 000000000..ac59ebda1 --- /dev/null +++ b/src/mappers/mapper281.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +static uint32 GetPRGBank(uint32 V) { + return ((jyasic.mode[3] << 5) | (V & 0x1F)); +} + +static uint32 GetCHRBank(uint32 V) { + return ((jyasic.mode[3] << 8) | (V & 0xFF)); +} + +void Mapper281_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} diff --git a/src/mappers/mapper282.c b/src/mappers/mapper282.c new file mode 100644 index 000000000..11e02019e --- /dev/null +++ b/src/mappers/mapper282.c @@ -0,0 +1,41 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +static uint32 GetPRGBank(uint32 V) { + return (((jyasic.mode[3] << 4) & ~0x1F) | (V & 0x1F)); +} + +static uint32 GetCHRBank(uint32 V) { + if (jyasic.mode[3] & 0x20) { + return (((jyasic.mode[3] << 6) & 0x600) | (V & 0x1FF)); + } else { + return (((jyasic.mode[3] << 6) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0xFF)); + } +} + +void Mapper282_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} diff --git a/src/mappers/mapper283.c b/src/mappers/mapper283.c new file mode 100644 index 000000000..9dee48607 --- /dev/null +++ b/src/mappers/mapper283.c @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg8(0x6000, (PRG_ROM_SIZE_16K & 0x6000) ? 32 : 31); + setprg32(0x8000, latch.data); + setchr8(0); +} + +void Mapper283_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, FALSE); +} diff --git a/src/mappers/mapper284.c b/src/mappers/mapper284.c new file mode 100644 index 000000000..df78ad89e --- /dev/null +++ b/src/mappers/mapper284.c @@ -0,0 +1,228 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* FIXME: + * The extender nametable mirroring only works in NEWPPU. +*/ + +#include "mapinc.h" +#include "dripsound.h" + +static uint8 extattrib[2][1024]; +static uint8 jumper; +static uint8 control; +static uint8 prg; +static uint8 chr[4]; +static uint8 IRQa; +static uint8 IRQLatch; +static int16 IRQCount; +static uint16 lastAddr; + +static uint8 DRIPHack = FALSE; + +static SFORMAT StateRegs[] = { + { &jumper, 1, "JUMP" }, + { &control, 1, "CTRL" }, + { &prg, 1, "PREG" }, + { chr, 4, "CREG" }, + { &IRQa, 1, "IRQA" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQCount, 2, "IRQC" }, + { &lastAddr, 2, "LADD" }, + { 0 } +}; + +static uint8 Sync(void) { + if (control & 0x08) { + setprg8r(0x10, 0x6000, 0); + } + + setprg16(0x8000, prg); + setprg16(0xC000, 0x0F); + + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr2(0x1000, chr[2]); + setchr2(0x1800, chr[3]); + + switch (control & 0x03) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +static DECLFW(M284Write) { + switch (A & 0xE000) { + case 0x8000: + case 0xA000: + switch (A & 0x0F) { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + DRIPSound_Write(A, V); + break; + case 0x8: + IRQLatch = V; + break; + case 0x9: + IRQCount = ((V & 0x7F) << 8) | IRQLatch; + IRQa = V & 0x80; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xA: + control = V & 0x0F; + Sync(); + break; + case 0xB: + prg = V & 0x0F; + Sync(); + break; + case 0xC: + case 0xD: + case 0xE: + case 0xF: + chr[A & 0x03] = V & 0x0F; + Sync(); + break; + } + break; + case 0xC000: + case 0xE000: + extattrib[(A & 0x400) >> 10][A & 0x3FF] = V & 0x03; + break; + } +} + +static DECLFR(M284Read) { + switch (A & 0xF800) { + case 0x4800: + return (jumper | 'd'); + case 0x5000: + case 0x5800: + return DRIPSound_Read(A); + } + return CartBR(A); +} + +#ifdef NEWPPU +uint8 M284PPURead(uint32 A) { + if ((A > 0x2000) && (A < 0x3F00)) { + if (control & 0x04) { + if ((A & 0x3FF) < 0x3C0) { + lastAddr = A & 0x3FF; + } else { + const uint8 ext_attrib[4] = { 0x00, 0x55, 0xAA, 0xFF }; + uint8 bank = 0; + + A &= 0x0FFF; + + switch (iNESCart.mirror) { + default: + case MI_0: bank = 0; break; + case MI_1: bank = 1; break; + case MI_V: bank = (A & 0x800) ? 1 : 0; break; + case MI_H: bank = (A & 0x400) ? 1 : 0; break; + } + return (ext_attrib[(extattrib[bank][lastAddr & 0x3FF]) & 0x03]); + } + } + } + return FFCEUX_PPURead_Default(A); +} +#endif + +static void M284Reset(void) { + control = 0; + prg = 0; + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + memset(&extattrib[0][0], 0x00, sizeof(extattrib)); + jumper = !jumper ? 0x80 : 0; + + Sync(); +} + +static void M284Power(void) { + control = 0; + prg = 0; + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + memset(&extattrib[0][0], 0x00, sizeof(extattrib)); + + jumper = 0; + + Sync(); + + SetReadHandler(0x4800, 0x5FFF, M284Read); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M284Write); + +#ifdef NEWPPU + FFCEUX_PPURead = M284PPURead; +#endif +} + +static void M284CPUIRQHook(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) { + IRQa = FALSE; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper284_Init(CartInfo *info) { + info->Power = M284Power; + MapIRQHook = M284CPUIRQHook; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + AddExState(extattrib[0], 1024, 0, "ATT0"); + AddExState(extattrib[1], 1024, 0, "ATT1"); + + WRAMSIZE = 8192; + WRAM = FCEU_malloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + DRIPSound_ESI(); + DRIPSound_AddStateInfo(); + + DRIPHack = TRUE; + + FCEU_printf(" DRIPGAME Mapper warning: Set video to use NEWPPU for game to work properly.\n"); +} diff --git a/src/mappers/mapper285.c b/src/mappers/mapper285.c new file mode 100644 index 000000000..8cb88fe63 --- /dev/null +++ b/src/mappers/mapper285.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Mapper 285 - A65AS */ +/* actually, there is two cart in one... First have extra mirroring + * mode (one screen) and 32K bankswitching, second one have only + * 16 bankswitching mode and normal mirroring... But there is no any + * correlations between modes and they can be used in one mapper code. + * + * Submapper 0 - 3-in-1 (N068) + * Submapper 0 - 3-in-1 (N080) + * Submapper 1 - 4-in-1 (JY-066) + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.data & 0x40) { + setprg32(0x8000, (latch.data >> 1) & 0x0F); + } else { + if (iNESCart.submapper == 1) { + setprg16(0x8000, ((latch.data & 0x30) >> 1) | (latch.data & 0x07)); + setprg16(0xC000, ((latch.data & 0x30) >> 1) | 0x07); + } else { + setprg16(0x8000, latch.data & 0x0F); + setprg16(0xC000, (latch.data & 0x0F) | 0x07); + } + } + setchr8(0); + if (latch.data & 0x80) { + setmirror(MI_0 + (((latch.data >> 5) & 0x01))); + } else { + setmirror(((latch.data >> 3) & 0x01) ^ 0x01); + } +} + +void Mapper285_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper286.c b/src/mappers/mapper286.c new file mode 100644 index 000000000..e5bd861d2 --- /dev/null +++ b/src/mappers/mapper286.c @@ -0,0 +1,98 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[4]; +static uint8 chr[4]; +static uint8 mirr; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 4, "CREG" }, + { &mirr, 1, "MIRR" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0]); + setprg8(0xa000, prg[1]); + setprg8(0xc000, prg[2]); + setprg8(0xe000, prg[3]); + + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr2(0x1000, chr[2]); + setchr2(0x1800, chr[3]); + + setmirror((mirr & 0x01) ^ 0x01); +} + +static DECLFW(M286Write) { + switch (A & 0xF000) { + case 0x8000: + case 0x9000: + chr[(A & 0xC00) >> 10] = A & 0x1F; + Sync(); + break; + case 0xA000: + case 0xB000: + if (A & (1 << (dipsw + 4))) { + prg[(A & 0xC00) >> 10] = A & 0x0F; + Sync(); + } + break; + case 0xC000: + mirr = V; + Sync(); + break; + } +} + +static void M286Reset(void) { + dipsw++; + dipsw &= 3; + prg[0] = prg[1] = prg[2] = prg[3] = ~0; + mirr = 0; + Sync(); +} + +static void M286Power(void) { + dipsw = 0; + prg[0] = prg[1] = prg[2] = prg[3] = ~0; + mirr = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M286Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper286_Init(CartInfo *info) { + info->Power = M286Power; + info->Reset = M286Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper287.c b/src/mappers/mapper287.c new file mode 100644 index 000000000..d074b9cff --- /dev/null +++ b/src/mappers/mapper287.c @@ -0,0 +1,98 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2008 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 287 + * BMC-411120-C, actually cart ID is 811120-C, sorry ;) K-3094 - another ID + * - 4-in-1 (411120-C) + * - 4-in-1 (811120-C,411120-C) [p4][U] + * + * BMC-K-3088, similar to BMC-411120-C but without jumper or dipswitch + * - 19-in-1(K-3088)(810849-C)(Unl) + */ + +/* 2023-03-02 + - use PRG size to determine variant + - remove forced mask for outer-bank (rely on internal mask set during PRG/CHR mapping) + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M287CW(uint16 A, uint16 V) { + uint16 base = reg & 0x07; + + setchr1(A, (base << 7) | (V & 0x7F)); +} + +static void M287PW(uint16 A, uint16 V) { + uint16 mode = reg & ((dipsw && (PRG_ROM_SIZE_16K <= (512 * 1024))) ? 0x0C : 0x08); + uint16 base = reg & 0x07; + + if (mode) { + /* 32K Mode */ + setprg32(0x8000, (base << 2) | ((reg >> 4) & 0x03)); + /* FCEU_printf("32K mode: bank:%02x\n", ((reg >> 4) & 3) | ((reg & 7) << 2)); */ + } else { + /* MMC3 Mode */ + setprg8(A, (base << 4) | (V & 0x0F)); + /* FCEU_printf("MMC3: %04x:%02x\n", A, (V & 0x0F) | ((reg & 7) << 4)); */ + } +} + +static DECLFW(M287WriteReg) { + /* printf("Wr: A:%04x V:%02x\n", A, V); */ + if (MMC3_WramIsWritable()) { + reg = A; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M287Reset(void) { + reg = 0; + dipsw ^= 4; + MMC3_Reset(); +} + +static void M287Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M287WriteReg); +} + +void Mapper287_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M287PW; + MMC3_cwrap = M287CW; + info->Power = M287Power; + info->Reset = M287Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper288.c b/src/mappers/mapper288.c new file mode 100644 index 000000000..b32ab63f0 --- /dev/null +++ b/src/mappers/mapper288.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 288 is used for two GKCX1 21-in-1 multicarts + * - 21-in-1 (GA-003) + * - 64-in-1 (CF-015) + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static void Sync(void) { + setprg32(0x8000, latch.addr >> 3); + setchr8(latch.addr); + setmirror(((latch.addr >> 5) & 0x01) ^ 0x01); +} + +static DECLFR(M288Read) { + uint8 ret = CartBR(A); + if (latch.addr & 0x20) { + return CartBR(A | (dipsw & 0x0F)); + } + return ret; +} + +static void M288Reset(void) { + dipsw++; + Sync(); +} + +void Mapper288_Init(CartInfo *info) { + Latch_Init(info, Sync, M288Read, FALSE, FALSE); + info->Reset = M288Reset; + AddExState(&dipsw, 1, 0, "DIPSW"); +} diff --git a/src/mappers/mapper289.c b/src/mappers/mapper289.c new file mode 100644 index 000000000..48d2cac83 --- /dev/null +++ b/src/mappers/mapper289.c @@ -0,0 +1,81 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2019-5-23 + * UNIF: BMC-60311C: + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_289 + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[2]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint32 bank = reg[1] & 0x7F; + + if (reg[0] & 0x02) { + setprg16(0x8000, (bank & ~0x07) | ((reg[0] & 0x01) ? 0x07 : (latch.data & 0x07))); + setprg16(0xC000, bank | 0x07); + } else { + setprg16(0x8000, bank & ~(reg[0] & 0x01)); + setprg16(0xC000, bank | (reg[0] & 0x01)); + } + /* CHR-RAM write-protect */ + SetupCartCHRMapping(0, CHRptr[0], 0x2000, ((reg[0] >> 2) & 0x01) ^ 0x01); + setchr8(0); + setmirror(((reg[0] >> 3) & 0x01) ^ 0x01); +} + +static DECLFR(M289Read) { + return (CPU_OPENBUS & ~0x03) | (dipsw & 0x03); +} + +static DECLFW(M289Write) { + reg[A & 0x01] = V; + Sync(); +} + +static void M289Power(void) { + dipsw = 0; + reg[0] = reg[1] = 0; + Latch_Power(); + SetReadHandler(0x6000, 0x7FFF, M289Read); + SetWriteHandler(0x6000, 0x7FFF, M289Write); +} + +static void M289Reset(void) { + dipsw++; + reg[0] = reg[1] = 0; + Latch_RegReset(); +} + +void Mapper289_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M289Power; + info->Reset = M289Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper290.c b/src/mappers/mapper290.c new file mode 100644 index 000000000..b51d63ba8 --- /dev/null +++ b/src/mappers/mapper290.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 290 - BMC-NTD-03 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint32 prg = ((latch.addr >> 10) & 0x1E) | ((latch.addr >> 6) & 0x01); + uint32 chr = ((latch.addr >> 5) & 0x18) | (latch.addr & 0x07); + + if (latch.addr & 0x80) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { + setprg32(0x8000, prg >> 1); + } + setchr8(chr); + setmirror(((latch.addr >> 10) & 0x01) ^ 0x01); +} + +void Mapper290_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper291.c b/src/mappers/mapper291.c new file mode 100644 index 000000000..4a4aeb45c --- /dev/null +++ b/src/mappers/mapper291.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M291CW(uint16 A, uint16 V) { + setchr1(A, ((reg << 2) & 0x100) | (V & 0xFF)); +} + +static void M291PW(uint16 A, uint16 V) { + if (reg & 0x20) { + setprg32(0x8000, ((reg >> 4) & 0x04) | ((reg >> 1) & 0x03)); + } else { + setprg8(A, ((reg >> 2) & 0x10) | (V & 0x0F)); + } +} + +static DECLFW(M291Write) { + /* The Outer Bank Register responds even when the MMC3 clone's WRAM bit is clear. */ + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M291Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M291Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M291Write); +} + +void Mapper291_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M291CW; + MMC3_pwrap = M291PW; + info->Power = M291Power; + info->Reset = M291Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper292.c b/src/mappers/mapper292.c new file mode 100644 index 000000000..5b30dd803 --- /dev/null +++ b/src/mappers/mapper292.c @@ -0,0 +1,80 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 292 - PCB BMW8544 + * UNIF UNL-DRAGONFIGHTER + * "Dragon Fighter" protected MMC3 based custom mapper board + * mostly hacky implementation, I can't verify if this mapper can read a RAM of the + * console or watches the bus writes somehow. + * + * TODO: needs updating + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[3]; + +static SFORMAT StateRegs[] = { + { reg, 3, "REGS" }, + { 0 } +}; + +static void M292PW(uint16 A, uint16 V) { + setprg8(A, V); + setprg8(0x8000, reg[0] & 0x1F); +} + +static void M292CW(uint16 A, uint16 V) { + setchr2(0x0000, (mmc3.reg[0] >> 1) ^ reg[1]); + setchr2(0x0800, (mmc3.reg[1] >> 1) ^ ((reg[2] & 0x40) << 1)); + setchr4(0x1000, reg[2] & 0x3F); +} + +static DECLFW(M292ProtWrite) { + reg[0] = V; + MMC3_FixPRG(); +} + +static DECLFR(M292ProtRead) { + if ((reg[0] & 0xE0) == 0xC0) { + reg[1] = ARead[0x6A](0x6A); + } else { + reg[2] = ARead[0xFF](0xFF); + } + MMC3_FixCHR(); + return CPU_OPENBUS; +} + +static void M292Power(void) { + reg[0] = reg[1] = reg[2] = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M292ProtWrite); + SetReadHandler(0x6000, 0x7FFF, M292ProtRead); +} + +void Mapper292_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M292PW; + MMC3_cwrap = M292CW; + info->Power = M292Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper293.c b/src/mappers/mapper293.c new file mode 100644 index 000000000..1e5244fbb --- /dev/null +++ b/src/mappers/mapper293.c @@ -0,0 +1,87 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NewStar 12-in-1 and 76-in-1 + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 mode = ((reg[0] >> 2) & 0x02) | ((reg[1] >> 6) & 0x01); + uint8 base = ((reg[1] << 5) & 0x20) | ((reg[1] >> 1) & 0x18); + uint8 bank = (reg[0] & 0x07); + + switch (mode) { + case 0: /* UNROM */ + setprg16(0x8000, base | bank); + setprg16(0xC000, base | 0x07); + break; + case 1: + setprg16(0x8000, base | (bank & 0xFE)); + setprg16(0xC000, base | 0x07); + break; + case 2: /* NROM-128 */ + setprg16(0x8000, base | bank); + setprg16(0xC000, base | bank); + break; + case 3: /* NROM-256 */ + setprg16(0x8000, (base | bank) & 0xFE); + setprg16(0xC000, (base | bank) | 1); + break; + } + setchr8(0); + setmirror(((reg[1] >> 7) & 0x01) ^ 0x01); +} + +static DECLFW(M293Write) { + if (!(A & 0x2000)) { + /* First Banking Register ($8000-$9FFF, $C000-$DFFF) */ + reg[0] = V; + } + if (!(A & 0x4000)) { + /* Second Banking Register ($8000-$BFFF) */ + reg[1] = V; + } +} + +static void M293Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xDFFF, M293Write); +} + +static void StateRestore(int version) { + Sync(); +} + +/* BMC 12-in-1/76-in-1 (NewStar) (Unl) */ +void Mapper293_Init(CartInfo *info) { + info->Power = M293Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper294.c b/src/mappers/mapper294.c new file mode 100644 index 000000000..16478c291 --- /dev/null +++ b/src/mappers/mapper294.c @@ -0,0 +1,63 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 NewRisingSun + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, (reg << 3) | (latch.data & 0x07)); + setprg16(0xC000, (reg << 3) | 0x07); + setchr8(0); + setmirror(((reg >> 4) & 0x01) ^ 0x01); +} + +static DECLFW(M294Write) { + if (A & 0x100) { + reg = V; + Sync(); + } +} + +static void M294Reset(void) { + reg = 0; + Latch_RegReset(); +} + +static void M294Power(void) { + reg = 0; + Latch_Power(); + SetWriteHandler(0x4100, 0x5FFF, M294Write); +} + +void Mapper294_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M294Power; + info->Reset = M294Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper295.c b/src/mappers/mapper295.c new file mode 100644 index 000000000..0b4881de9 --- /dev/null +++ b/src/mappers/mapper295.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" +#include "fdssound.h" + +static uint32 GetPRGBank(uint32 V) { + return ((jyasic.mode[3] << 4) | (V & 0x0F)); +} + +static uint32 GetCHRBank(uint32 V) { + return ((jyasic.mode[3] << 7) | (V & 0x7F)); +} + +static void M295Power(void) { + JYASIC_Power(); + FDSSound_Power(); +} + +void Mapper295_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; + info->Power = M295Power; +} diff --git a/src/mappers/mapper297.c b/src/mappers/mapper297.c new file mode 100644 index 000000000..fa0ff36fb --- /dev/null +++ b/src/mappers/mapper297.c @@ -0,0 +1,94 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 297 - 2-in-1 Uzi Lightgun (MGC-002) */ + +#include "mapinc.h" +#include "mmc1.h" + +static uint8 mode; +static uint8 latch; + +static SFORMAT StateRegs[] = { + { &mode, 1, "MODE" }, + { &latch, 1, "LATC" }, + { 0 } +}; + +static void M297PRG(uint16 A, uint16 V) { + setprg16(A, 0x08 | (V & 0x07)); +} + +static void M297CHR(uint16 A, uint16 V) { + setchr4(A, 0x20 | (V & 0x1F)); +} + +static void Sync(void) { + if (mode & 0x01) { + /* MMC1 */ + MMC1_FixPRG(); + MMC1_FixCHR(); + MMC1_FixMIR(); + } else { + /* Mapper 70 */ + setprg16(0x8000, ((mode & 0x02) << 1) | ((latch >> 4) & 0x03)); + setprg16(0xC000, ((mode & 0x02) << 1) | 0x03); + setchr8(latch & 0x0F); + setmirror(MI_V); + } +} + +static DECLFW(M297Mode) { + if (A & 0x100) { + mode = V; + Sync(); + } +} + +static DECLFW(M297Latch) { + if (mode & 0x01) { + MMC1_Write(A, V); + } else { + latch = V; + Sync(); + } +} + +static void M297Power(void) { + latch = 0; + mode = 0; + Sync(); + MMC1_Power(); + SetWriteHandler(0x4100, 0x5FFF, M297Mode); + SetWriteHandler(0x8000, 0xFFFF, M297Latch); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper297_Init(CartInfo *info) { + MMC1_Init(info, 0, 0); + info->Power = M297Power; + MMC1_cwrap = M297CHR; + MMC1_pwrap = M297PRG; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper298.c b/src/mappers/mapper298.c new file mode 100644 index 000000000..3f563748e --- /dev/null +++ b/src/mappers/mapper298.c @@ -0,0 +1,30 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * iNES Mapper 298 - UNL-TF1201 + * Lethal Weapon (VRC4 mapper) + */ + +#include "mapinc.h" +#include "vrc24.h" + +void Mapper298_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x02, 0x01, FALSE, FALSE); +} diff --git a/src/mappers/mapper299.c b/src/mappers/mapper299.c new file mode 100644 index 000000000..6c0853f96 --- /dev/null +++ b/src/mappers/mapper299.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* BMC-11160 (m299) */ +/* Simple BMC discrete mapper by TXC */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, (latch.data >> 4) & 0x07); + setchr8(((latch.data >> 2) & 0x1C) | (latch.data & 0x03)); + setmirror((latch.data >> 7) & 0x01); +} + +void Mapper299_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper300.c b/src/mappers/mapper300.c new file mode 100644 index 000000000..02d3cb584 --- /dev/null +++ b/src/mappers/mapper300.c @@ -0,0 +1,36 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 300 - BMC-190in1 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.addr >> 2); + setprg16(0xC000, latch.addr >> 2); + setchr8(latch.addr >> 2); + setmirror((latch.addr & 0x01) ^ 0x01); +} + +void Mapper300_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper301.c b/src/mappers/mapper301.c new file mode 100644 index 000000000..f16f57edf --- /dev/null +++ b/src/mappers/mapper301.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * GG1 boards, similar to T-262, with no Data latch + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint8 prg = (latch.addr >> 2) & 0x1F; + uint8 nrom = (latch.addr & 0x80) != 0; + uint8 unrom = (latch.addr & 0x200) != 0; + + setprg16(0x8000, prg); + setprg16(0xC000, (prg & ~(0x07 * nrom)) | (0x07 * unrom)); + setchr8(0); + setmirror(((latch.addr & 2) >> 1) ^ 1); +} + +static DECLFR(M301Read) { + if ((latch.addr & 0x100) && (PRGsize[0] <= (512 * 1024))) { + A = (A & 0xFFFE) + (dipsw & 0x01); + } + return CartBR(A); +} + +static void M301Power(void) { + dipsw = 0; + Latch_Power(); +} + +static void M301Reset(void) { + dipsw++; + Latch_RegReset(); +} + +void Mapper301_Init(CartInfo *info) { + Latch_Init(info, Sync, M301Read, FALSE, FALSE); + info->Power = M301Power; + info->Reset = M301Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper302.c b/src/mappers/mapper302.c new file mode 100644 index 000000000..3b7148d06 --- /dev/null +++ b/src/mappers/mapper302.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 302 - UNL-KS7057 + * FDS Conversion + */ + +#include "mapinc.h" +#include "vrc24.h" + +static void M302PW(uint16 A, uint16 V) { + setprg8( 0x8000, 0x00); + setprg8( 0xA000, 0x0D); + setprg16(0xC000, 0x07); +} + +static void M302CW(uint16 A, uint16 V) { + setchr8(0); +} + +static DECLFR(M302Read) { + uint8 bank = (((A - 0x6000) >> 11) & 0x06) | ((A >> 11) & 0x01); + + return PRGptr[0][(vrc24.chr[bank ^ 4] << 11) | (A & 0x07FF)]; +} + +static void M302Power(void) { + VRC24_Power(); + SetReadHandler(0x6000, 0x9FFF, M302Read); +} + +void Mapper302_Init(CartInfo *info) { + VRC24_Init(info, VRC2, 0x01, 0x02, FALSE, TRUE); + info->Power = M302Power; + VRC24_pwrap = M302PW; + VRC24_cwrap = M302CW;; +} diff --git a/src/mappers/mapper303.c b/src/mappers/mapper303.c new file mode 100644 index 000000000..e6c140d87 --- /dev/null +++ b/src/mappers/mapper303.c @@ -0,0 +1,144 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 303 - Kaiser 7017 + * UNIF UNL-KS7017 + * FDS Conversion - Almana No Kiseki + * + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 latch; +static uint8 prg, mirr; +static int32 IRQa, IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = { + { &mirr, 1, "MIRR" }, + { &prg, 1, "REGS" }, + { &latch, 1, "LATC" }, + { &IRQa, 4, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { &IRQLatch, 4, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, prg); + setprg16(0xC000, 2); + setchr8(0); + setprg8r(0x10, 0x6000, 0); + setmirror(mirr); +} + +static DECLFW(M303Write) { + /* FCEU_printf("bs %04x %02x\n",A,V); */ + if ((A & 0xFF00) == 0x4A00) { + latch = ((A >> 2) & 0x03) | ((A >> 4) & 0x04); + } else if ((A & 0xFF00) == 0x5100) { + prg = latch; + Sync(); + } else { + if (A == 0x4020) { + X6502_IRQEnd(FCEU_IQEXT); + IRQCount &= 0xFF00; + IRQCount |= V; + } else if (A == 0x4021) { + X6502_IRQEnd(FCEU_IQEXT); + IRQCount &= 0x00FF; + IRQCount |= V << 8; + IRQa = 1; + } else if (A == 0x4025) { + mirr = ((V & 8) >> 3) ^ 0x01; + } + } + if (A >= 0x4040 && A <= 0x407F) { + FDSWaveWrite(A, V); + } + switch (A) { + case 0x4080: FDSSReg0Write(A, V); break; + case 0x4082: FDSSReg1Write(A, V); break; + case 0x4083: FDSSReg2Write(A, V); break; + case 0x4084: FDSSReg3Write(A, V); break; + case 0x4085: FDSSReg4Write(A, V); break; + case 0x4086: FDSSReg5Write(A, V); break; + case 0x4087: FDSSReg6Write(A, V); break; + case 0x4088: FDSSReg7Write(A, V); break; + case 0x4089: FDSSReg8Write(A, V); break; + case 0x408A: FDSSReg9Write(A, V); break; + } +} + +static DECLFR(FDSRead4030) { + uint8 ret = (X.IRQlow & FCEU_IQEXT) ? 1 : 0; + + X6502_IRQEnd(FCEU_IQEXT); + return ret; +} + +static void UNL7017IRQ(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) { + IRQa = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M303Power(void) { + latch = prg = mirr = IRQa = IRQCount = IRQLatch = 0; + FDSSound_Power(); + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4030, 0x4030, FDSRead4030); + SetWriteHandler(0x4020, 0x5FFF, M303Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M303Reset(void) { + Sync(); + FDSSoundRegReset(); + FDSSound_SC(); +} + +static void M303Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper303_Init(CartInfo *info) { + info->Power = M303Power; + info->Close = M303Close; + info->Reset = M303Reset; + MapIRQHook = UNL7017IRQ; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper304.c b/src/mappers/mapper304.c new file mode 100644 index 000000000..1c2147ccc --- /dev/null +++ b/src/mappers/mapper304.c @@ -0,0 +1,99 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversions + * + * Super Mario Bros 2j (Alt Full) is a BAD incomplete dump, should be mapper 43 + * + * Both Voleyball and Zanac by Whirlind Manu shares the same PCB, but with + * some differences: Voleyball has 8K CHR ROM and 8K ROM at 6000K, Zanac + * have 8K CHR RAM and banked 16K ROM mapper at 6000 as two 8K banks. + * + * NES 2.0 Mapper 304 - UNL-SMB2J + * Super Mario Bros 2j (Alt Small) uses additionally IRQ timer to drive framerate + * + * PCB for this mapper is "09-034A" + */ + +#include "mapinc.h" + +static uint8 prg; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = +{ + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { &prg, 1, "PRG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, 4 | prg); + setprg32(0x8000, 0); + setchr8(0); +} + +static DECLFW(M304Write1) { + prg = V & 0x01; + Sync(); +} + +static DECLFW(M304Write2) { + IRQa = V & 0x01; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); +} + +static DECLFR(M304Read) { + return 0xFF; +} + +static void M304Power(void) { + prg = 0; + IRQCount = IRQa = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetReadHandler(0x4020, 0x4FFF, M304Read); + SetWriteHandler(0x4068, 0x4068, M304Write2); + SetWriteHandler(0x4027, 0x4027, M304Write1); +} + +static void M304IRQHook(int a) { + if (IRQa) { + if (IRQCount < 5750) { + IRQCount += a; + } else { + IRQa = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper304_Init(CartInfo *info) { + info->Power = M304Power; + MapIRQHook = M304IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper305.c b/src/mappers/mapper305.c new file mode 100644 index 000000000..e25040386 --- /dev/null +++ b/src/mappers/mapper305.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 305 + * UNIF UNL-KS7031 + * FDS Conversion - dracula ii - noroi no fuuin [u][!] + * + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg[4]; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg2(0x6000, reg[0]); + setprg2(0x6800, reg[1]); + setprg2(0x7000, reg[2]); + setprg2(0x7800, reg[3]); + + setprg2(0x8000, 15); + setprg2(0x8800, 14); + setprg2(0x9000, 13); + setprg2(0x9800, 12); + setprg2(0xa000, 11); + setprg2(0xa800, 10); + setprg2(0xb000, 9); + setprg2(0xb800, 8); + + setprg2(0xc000, 7); + setprg2(0xc800, 6); + setprg2(0xd000, 5); + setprg2(0xd800, 4); + setprg2(0xe000, 3); + setprg2(0xe800, 2); + setprg2(0xf000, 1); + setprg2(0xf800, 0); + + setchr8(0); +} + +static DECLFW(M305Write) { + reg[(A >> 11) & 0x03] = V; + Sync(); +} + +static void M305Power(void) { + memset(reg, 0, sizeof(reg)); + FDSSound_Power(); + Sync(); + setmirror(MI_V); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M305Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper305_Init(CartInfo *info) { + info->Power = M305Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper306.c b/src/mappers/mapper306.c new file mode 100644 index 000000000..b140bb633 --- /dev/null +++ b/src/mappers/mapper306.c @@ -0,0 +1,75 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2016 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 306 - Kaiser 7016 + * UNIF UNL-KS7016 + * FDS Conversion (Exciting Basket), weird banking addressing, seems because + * of used addressing scheme, made to disable the lower system banks from 6000 + * but the kaiser mapper chip and PCB are the same as usual + * probably need a hard eprom dump to verify actual banks layout + * + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8( 0x6000, reg); + setprg32(0x8000, 3); + setchr8(0); +} + +static DECLFW(M306Write) { + if ((A & 0xD903) == 0xD903) { + if (A & 0x40) { + reg = (A >> 2) & 0x0F; + } else { + reg = 0x08 | ((A >> 2) & 0x03); + } + Sync(); + } +} + +static void M306Power(void) { + FDSSound_Power(); + + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0xD000, 0xDFFF, M306Write); + SetWriteHandler(0xF000, 0xFFFF, M306Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper306_Init(CartInfo *info) { + info->Power = M306Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper307.c b/src/mappers/mapper307.c new file mode 100644 index 000000000..3b82baa53 --- /dev/null +++ b/src/mappers/mapper307.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion - Metroid - Jin Ji Zhi Ling (Kaiser)(KS7037)[U][!] + * NES 2.0 Mapper 307 - UNL-KS7037 + * + */ + +#include "mapinc.h" +#include "n118.h" +#include "fdssound.h" + +static void M307FixPRG(void) { + setprg4r(0x10, 0x6000, 0); + setprg4(0x7000, 15); + setprg8(0x8000, n118.reg[6]); + setprg4(0xA000, ~3); + setprg4r(0x10, 0xB000, 0x01); + setprg8(0xC000, n118.reg[7]); + setprg8(0xE000, ~0); +} + +static void M307FixCHR(void) { + setchr8(0); + setmirrorw(n118.reg[2] & 0x01, n118.reg[4] & 0x01, n118.reg[3] & 0x01, n118.reg[5] & 0x01); +} + +static void M307Power(void) { + FDSSound_Power(); + N118_Power(); + SetWriteHandler(0xB000, 0xBFFF, CartBW); +} + +void Mapper307_Init(CartInfo *info) { + N118_Init(info, 8, info->battery); + info->Power = M307Power; + N118_FixPRG = M307FixPRG; + N118_FixCHR = M307FixCHR; +} diff --git a/src/mappers/mapper308.c b/src/mappers/mapper308.c new file mode 100644 index 000000000..a921a34a3 --- /dev/null +++ b/src/mappers/mapper308.c @@ -0,0 +1,76 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 308 - UNL-TH2131-1 */ +/* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_308 + * NES 2.0 Mapper 308 is used for a bootleg version of the Sunsoft game Batman + * similar to Mapper 23 Submapper 3) with custom IRQ functionality. + * UNIF board name is UNL-TH2131-1. + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 IRQLatch, IRQa; +static uint16 IRQCount; + +static SFORMAT IRQStateRegs[] = { + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQa, 1, "IRQA" }, + + { 0 } +}; + +static DECLFW(M308Write) { + switch (A & 0xF003) { + case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; IRQCount = 0; break; + case 0xF001: IRQa = 1; break; + case 0xF003: IRQLatch = (V & 0xF0) >> 4; break; + } +} + +static void M308IRQHook(int a) { + if (IRQa) { + while (a--) { + IRQCount++; + if ((IRQCount & 0x0FFF) == 2048) { + IRQLatch--; + } + if (!IRQLatch && (IRQCount & 0x0FFF) < 2048) { + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void M308Power(void) { + IRQa = IRQCount = IRQLatch = 0; + VRC24_Power(); + SetWriteHandler(0xF000, 0xFFFF, M308Write); +} + +void Mapper308_Init(CartInfo *info) { + VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); + info->Power = M308Power; + MapIRQHook = M308IRQHook; + AddExState(IRQStateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper309.c b/src/mappers/mapper309.c new file mode 100644 index 000000000..8c1b3cb0a --- /dev/null +++ b/src/mappers/mapper309.c @@ -0,0 +1,83 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* FDS Conversion + * NES 2.0 Mapper 309 is used for Whirlwind Manu's ROM cartridge conversion + * of game 愛戦士ニコル (Ai Senshi Nicol, cartridge code M309). + * Its UNIF board name is UNL-LH51. + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_309 + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg, mirr; + +static SFORMAT StateRegs[] = { + { ®, 1, "REG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, reg); + setprg8(0xA000, ~2); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + setchr8(0); + setmirror(((mirr >> 3) & 0x01) ^ 0x01); +} + +static DECLFW(M309Write) { + switch (A & 0xF000) { + case 0x8000: reg = V; Sync(); break; + case 0xF000: mirr = V; Sync(); break; + } +} + +static void M309Power(void) { + FDSSound_Power(); + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M309Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M309Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper309_Init(CartInfo *info) { + info->Power = M309Power; + info->Close = M309Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper310.c b/src/mappers/mapper310.c new file mode 100644 index 000000000..7ddb5ae2f --- /dev/null +++ b/src/mappers/mapper310.c @@ -0,0 +1,93 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" + +static uint8 regData[2]; +static uint8 regAddr; + +static SFORMAT K1053_state[] = +{ + { regData, 2, "REGD" }, + { ®Addr, 1, "REGA" }, + { 0 } +}; + +static void K1053_sync(void) { + int prg = (regData[0] & 0x3F) | ((regAddr << 4) & ~0x3F); + int chrWritable; + switch (regAddr & 3) { + case 0: + setprg32(0x8000, prg >> 1); + chrWritable = 0; + break; + case 1: + setprg16(0x8000, prg); + setprg16(0xC000, prg | 7); + chrWritable = 1; + break; + case 2: + prg = prg << 1 | regData[0] >> 7; + setprg8(0x8000, prg); + setprg8(0xA000, prg); + setprg8(0xC000, prg); + setprg8(0xE000, prg); + chrWritable = 1; + break; + case 3: + setprg16(0x8000, prg); + setprg16(0xC000, prg); + chrWritable = 0; + break; + } + SetupCartCHRMapping(0, CHRptr[0], 0x8000, chrWritable); + setchr8(regData[1]); + setmirror((regData[0] & 0x40) ? MI_H : MI_V); +} + +static void K1053_restore(int version) { + K1053_sync(); +} + +static DECLFW(K1053_write) { + regData[(A >> 14) & 1] = V; + if (A & 0x4000) + regAddr = A & 0xFF; + K1053_sync(); +} + +static void K1053_reset(void) { + regData[0] = regData[1] = regAddr = 0; + K1053_sync(); +} + +static void K1053_power(void) { + K1053_reset(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, K1053_write); +} + +void Mapper310_Init(CartInfo *info) { + info->Power = K1053_power; + info->Reset = K1053_reset; + GameStateRestore = K1053_restore; + AddExState(&K1053_state, ~0, 0, 0); +} diff --git a/src/mappers/mapper312.c b/src/mappers/mapper312.c new file mode 100644 index 000000000..5fb9e16bd --- /dev/null +++ b/src/mappers/mapper312.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 312 - Kaiser 7013B + * UNIF UNL-KS7013B + * Just another pirate cart with pirate mapper, instead of original MMC1 + * Kaiser Highway Star + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, reg); + setprg16(0xc000, ~0); + setmirror((latch.data & 0x01) ^ 0x01); + setchr8(0); +} + +static DECLFW(M312LoWrite) { + reg = V; + Sync(); +} + +static void M312Power(void) { + reg = 0; + Latch_Power(); + SetWriteHandler(0x6000, 0x7FFF, M312LoWrite); +} + +void Mapper312_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M312Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper313.c b/src/mappers/mapper313.c new file mode 100644 index 000000000..56b3e5d78 --- /dev/null +++ b/src/mappers/mapper313.c @@ -0,0 +1,78 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 313 is used for MMC3-based multicarts that switch + * between 128 KiB PRG-ROM/128 KiB CHR-ROM-sized games on each reset and + * thus require no additional registers. + * Its UNIF board name is BMC-RESET-TXROM. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M313CW(uint16 A, uint16 V) { + switch (iNESCart.submapper) { + default: setchr1(A, (reg << 7) | (V & 0x7F)); break; + case 1: setchr1(A, (reg << 7) | (V & 0x7F)); break; + case 2: setchr1(A, (reg << 8) | (V & 0xFF)); break; + case 3: setchr1(A, (reg << 8) | (V & 0xFF)); break; + case 4: setchr1(A, (reg << 7) | (V & 0x7F)); break; + } +} + +static void M313PW(uint16 A, uint16 V) { + switch (iNESCart.submapper) { + default: setprg8(A, (reg << 4) | (V & 0x0F)); break; + case 1: setprg8(A, (reg << 5) | (V & 0x1F)); break; + case 2: setprg8(A, (reg << 4) | (V & 0x0F)); break; + case 3: setprg8(A, (reg << 5) | (V & 0x1F)); break; + case 4: + if (reg == 0) { + setprg8(A, (reg << 5) | (V & 0x1F)); + } else { + setprg8(A, (reg << 4) | (V & 0x0F)); + } + break; + } +} + +static void M313Reset(void) { + reg++; + reg &= 0x03; + MMC3_Reset(); +} + +static void M313Power(void) { + reg = 0; + MMC3_Power(); +} + +/* NES 2.0 313, UNIF BMC-RESET-TXROM */ +void Mapper313_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_cwrap = M313CW; + MMC3_pwrap = M313PW; + info->Power = M313Power; + info->Reset = M313Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper314.c b/src/mappers/mapper314.c new file mode 100644 index 000000000..ce2dd47b7 --- /dev/null +++ b/src/mappers/mapper314.c @@ -0,0 +1,81 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * BMC 42-in-1 "reset switch" type + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 regs[4]; + +static SFORMAT StateRegs[] = { + { regs, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 prg = regs[1] & 0x3F; + + if (regs[0] & 0x80) { /* NROM mode */ + if (regs[1] & 0x80) { + setprg32(0x8000, prg); + } else { + setprg16(0x8000, (prg << 1) | ((regs[1] >> 6) & 0x01)); + setprg16(0xC000, (prg << 1) | ((regs[1] >> 6) & 0x01)); + } + } else { /* UNROM mode */ + setprg16(0x8000, (prg << 1) | (latch.data & 0x07)); + setprg16(0xC000, (prg << 1) | 0x07); + } + setchr8((regs[2] << 2) | ((regs[0] >> 1) & 0x03)); + setmirror(((regs[0] >> 5) & 0x01) ^ 0x01); + +} + +static DECLFW(M314Write) { + A &= 0x03; + if (A == 0x03) A = 0x01; /* K-42001's "Aladdin III" */ + regs[A] = V; + Sync(); +} + +static void M314Reset(void) { + /* Reset returns to menu */ + regs[0] = 0x80; + regs[1] = 0x43; + regs[2] = regs[3] = 0; + Sync(); +} + +static void M314Power(void) { + regs[0] = 0x80; + regs[1] = 0x43; + regs[2] = regs[3] = 0; + Latch_Power(); + SetWriteHandler(0x5000, 0x5FFF, M314Write); +} + +void Mapper314_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Power = M314Power; + info->Reset = M314Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper315.c b/src/mappers/mapper315.c new file mode 100644 index 000000000..38f866d38 --- /dev/null +++ b/src/mappers/mapper315.c @@ -0,0 +1,81 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 315 + * BMC-830134C + * Used for multicarts using 820732C- and 830134C-numbered PCBs such as 4-in-1 Street Blaster 5 + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_315 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M315CCW(uint16 A, uint16 V) { + uint16 mask = 0xFF; + uint16 base = reg << 8; + + V = ((reg << 6) & 0x80) | ((reg << 3) & 0x40) | (V & 0xFF); + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M315CPW(uint16 A, uint16 V) { + uint16 mask = 0x0F; + uint16 base = reg << 3; + + if ((reg & 0x06) == 0x06) { /* GNROM-like */ + setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & ~0x02) & mask)); + setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & ~0x02) & mask)); + setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] | 0x02) & mask)); + setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] | 0x02) & mask)); + } else { + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static DECLFW(M315CWrite) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M315CReset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M315CPower(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M315CWrite); +} + +void Mapper315_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M315CPW; + MMC3_cwrap = M315CCW; + info->Power = M315CPower; + info->Reset = M315CReset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper319.c b/src/mappers/mapper319.c new file mode 100644 index 000000000..2b44cb632 --- /dev/null +++ b/src/mappers/mapper319.c @@ -0,0 +1,92 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[2]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = +{ + { reg, 2, "REG" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M319Sync(void) { + uint16 bank, mask; + + if (iNESCart.CRC32 == 0xE5B9AB1F || iNESCart.PRGCRC32 == 0xC25FD362) { + /* The publicly-available UNIF (UNL-HP898F) ROM file of Prima Soft 9999999-in-1 has + * the order of the 16 KiB PRG-ROM banks slightly mixed up, so that the + * PRG A14 mode bit operates on A16 instead of A14. To obtain the + * correct bank order, use UNIF 16 KiB PRG banks 0, 4, 1, 5, 2, 6, 3, 7. + */ + bank = (reg[1] >> 3) & 7; + mask = (reg[1] >> 4) & 4; + + setprg16(0x8000, bank & ~mask); + setprg16(0xC000, bank | mask); + } else { + bank = ((reg[1] >> 2) & 0x06) | ((reg[1] >> 5) & 0x01); + mask = (reg[1] >> 6) & 0x01; + + setprg16(0x8000, (bank & ~mask)); + setprg16(0xC000, (bank | mask)); + } + + bank = reg[0] >> 4; + mask = (reg[0] << 2) & 0x04; + + setchr8((bank & ~mask) | ((latch.data << 2) & mask)); + setmirror(reg[1] >> 7); +} + +static DECLFR(M319ReadDIP) { + return dipsw; +} + +static DECLFW(M319Write) { + reg[(A >> 2) & 0x01] = V; + M319Sync(); +} + +static void M319Reset(void) { + reg[0] = reg[1] = 0; + dipsw ^= 0x40; + M319Sync(); +} + +static void M319Power(void) { + reg[0] = reg[1] = dipsw = 0; + Latch_Power(); + SetReadHandler(0x5000, 0x5FFF, M319ReadDIP); + SetWriteHandler(0x6000, 0x7FFF, M319Write); +} + +void Mapper319_Init(CartInfo *info) { + Latch_Init(info, M319Sync, NULL, 0, 0); + info->Power = M319Power; + info->Reset = M319Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper320.c b/src/mappers/mapper320.c new file mode 100644 index 000000000..0fe0bb324 --- /dev/null +++ b/src/mappers/mapper320.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 320 is used for the Super HiK 6-in-1 A-030 multicart. + * Basically UxROM with an address-latch-based outer bank register. + * UNIF board name is BMC-830425C-4391T. Mirroring is hard-wired. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_320 + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint16 mask = (latch.addr & 0x10) ? 0x07 : 0x0F; + uint16 base = latch.addr << 3; + + setprg16(0x8000, base | (latch.data & mask)); + setprg16(0xC000, base | (latch.data & mask) | ((~latch.addr >> 1) & 0x08) | 0x07); + setchr8(0); + setmirror(MI_V); +} + +static DECLFW(M320Write) { + if ((A & 0xFFE0) == 0xF0E0) { + latch.addr = A; + } + latch.data = V; + Sync(); +} + +static void M320Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M320Write); +} + +void Mapper320_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M320Power; + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper322.c b/src/mappers/mapper322.c new file mode 100644 index 000000000..7e003cb45 --- /dev/null +++ b/src/mappers/mapper322.c @@ -0,0 +1,97 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 322 + * BMC-K-3033 + * 35-in-1 (K-3033) + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_322 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M322CW(uint16 A, uint16 V) { + if (reg & 0x20) { + uint16 base = ((reg >> 4) & 0x04) | ((reg >> 3) & 0x03); + + if (reg & 0x80) { + setchr1(A, (base << 8) | (V & 0xFF)); + } else { + setchr1(A, (base << 7) | (V & 0x7F)); + } + } else { + setchr1(A, (V & 0x7F)); + } +} + +static void M322PW(uint16 A, uint16 V) { + uint16 base = ((reg >> 4) & 0x04) | ((reg >> 3) & 0x03); + + if (reg & 0x20) { + if (reg & 0x80) { + setprg8(A, (base << 5) | (V & 0x1F)); + } else { + setprg8(A, (base << 4) | (V & 0x0F)); + } + } else { + if (reg & 0x03) { + setprg32(0x8000, (base << 3) | ((reg >> 1) & 0x03)); + } else { + setprg16(0x8000, (base << 3) | (reg & 0x07)); + setprg16(0xC000, (base << 3) | (reg & 0x07)); + } + } +} + +static DECLFW(M322Write) { + if (MMC3_WramIsWritable()) { + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M322Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M322Write); +} + +static void M322Reset(void) { + reg = 0; + MMC3_Reset(); +} + +void Mapper322_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M322PW; + MMC3_cwrap = M322CW; + info->Power = M322Power; + info->Reset = M322Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper323.c b/src/mappers/mapper323.c new file mode 100644 index 000000000..cb179cebf --- /dev/null +++ b/src/mappers/mapper323.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 323 - UNIF FARID_SLROM_8-IN-1 */ + +#include "mapinc.h" +#include "mmc1.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M323PW(uint16 A, uint16 V) { + uint8 mask = 0x07; + uint8 base = reg >> 1; + + setprg16(A, (base & ~mask) | (V & mask)); +} + +static void M323CW(uint16 A, uint16 V) { + uint16 mask = 0x1F; + uint16 base = reg << 1; + + setchr4(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M323Write) { + if (!(mmc1.reg[3] & 0x10) && !(reg & 0x08)) { + reg = V; + MMC1_FixCHR(); + MMC1_FixPRG(); + MMC1_FixMIR(); + } +} + +static void M323Power(void) { + reg = 0; + MMC1_Power(); + SetWriteHandler(0x6000, 0x7FFF, M323Write); +} + +static void M323Reset(void) { + reg = 0; + MMC1_Reset(); +} + +void Mapper323_Init(CartInfo *info) { + MMC1_Init(info, 0, 0); + MMC1_cwrap = M323CW; + MMC1_pwrap = M323PW; + info->Power = M323Power; + info->Reset = M323Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper324.c b/src/mappers/mapper324.c new file mode 100644 index 000000000..9b694a509 --- /dev/null +++ b/src/mappers/mapper324.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 324 + * FARID_UNROM_8-IN-1 + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_324 + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setchr8(0); + setprg16(0x8000, ((latch.data & 0x70) >> 1) | (latch.data & 0x07)); + setprg16(0xC000, ((latch.data & 0x70) >> 1) | 0x07 ); +} + +static DECLFW(M324Write) { + if ((V & 0x80) && !(latch.data & 0x80) && !(latch.data & 0x08)) { + Latch_Write(A, V); + } else { + latch.data = (latch.data & ~0x07) | (V & 0x07); + Sync(); + } +} + +static void M324Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M324Write); +} + +void Mapper324_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Power = M324Power; + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper325.c b/src/mappers/mapper325.c new file mode 100644 index 000000000..c53d8f4a1 --- /dev/null +++ b/src/mappers/mapper325.c @@ -0,0 +1,51 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 325 + * UNIF UNL-MALISB + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M325PW(uint16 A, uint16 V) { + setprg8(A, ((V << 1) & 0x08) | ((V >> 1) & 0x04) | (V & 0x03)); +} + +static void M325CW(uint16 A, uint16 V) { + setchr1(A, (V & 0xDD) | ((V << 4) & 0x20) | ((V >> 4) & 0x02)); +} + +static DECLFW(M325Write) { + A = (A & 0xFFFE) | ((A >> 3) & 1); + MMC3_Write(A, V); +} + +static void M325Power(void) { + MMC3_Power(); + SetWriteHandler(0x8000, 0xFFFF, M325Write); +} + +void Mapper325_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M325PW; + MMC3_cwrap = M325CW; + info->Power = M325Power; +} diff --git a/src/mappers/mapper326.c b/src/mappers/mapper326.c new file mode 100644 index 000000000..eec1b010d --- /dev/null +++ b/src/mappers/mapper326.c @@ -0,0 +1,89 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 326 is used for a bootleg version of Contra/Gryzor. + * as implemented from + * http://forums.nesdev.org/viewtopic.php?f=9&t=17352&p=218722#p218722 + */ + +#include "mapinc.h" + +static uint8 prg[4], chr[8], nt[4]; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { nt, 4, "NTAR" }, + { 0 } +}; + +static void Sync(void) { + int i; + + for (i = 0; i < 4; i++) setprg8(0x8000 + (i << 13), prg[i]); + for (i = 0; i < 8; i++) setchr1(i << 10, chr[i]); + for (i = 0; i < 3; i++) setntamem(NTARAM + 0x400 * (nt[i] & 0x01), 1, i); +} + +static DECLFW(M326Write) { + switch (A & 0xE010) { + case 0x8000: prg[0] = V; break; + case 0xA000: prg[1] = V; break; + case 0xC000: prg[2] = V; break; + default: break; + } + + switch (A & 0x1F) { + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + chr[A & 0x07] = V; + break; + case 0x18: case 0x19: case 0x1A: case 0x1B: + nt[A & 0x03] = V; + break; + default: + break; + } + + Sync(); +} + +static void M326Power(void) { + int i; + + for (i = 0; i < 4; i++) prg[i] = 0xFC | i; + for (i = 0; i < 8; i++) chr[i] = i; + for (i = 0; i < 4; i++) nt[i] = (i >> 1) & 0x01; + + Sync(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M326Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper326_Init(CartInfo *info) { + info->Power = M326Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper327.c b/src/mappers/mapper327.c new file mode 100644 index 000000000..195065af9 --- /dev/null +++ b/src/mappers/mapper327.c @@ -0,0 +1,108 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 Cluster + * http://clusterrr.com + * clusterrr@clusterrr.com + * + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + NES 2.0 mapper 327 is used for a 6-in-1 multicart. Its UNIF board name is BMC-10-24-C-A1. + + MMC3-based multicart mapper with CHR RAM, CHR ROM and PRG RAM + + $6000-7FFF: A~[011xxxxx xxMRSBBB] Multicart reg + This register can only be written to if PRG-RAM is enabled and writable (see $A001) + and BBB = 000 (power on state) + + BBB = CHR+PRG block select bits (A19, A18, A17 for both PRG and CHR) + S = PRG block size (0=256k 1=128k) + R = CHR mode (0=CHR ROM 1=CHR RAM) + M = CHR block size (0=256k 1=128k) + ignored when S is 0 for some reason + + Example Game: + -------------------------- + 6 in 1 multicart (SMB3, TMNT2, Contra, Ninja Cat, Ninja Crusaders, Rainbow Islands 2) +*/ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M327PW(uint16 A, uint16 V) { + uint8 base = (reg << 4) & 0x70; + uint8 mask = (reg & 0x08) ? 0x1F : 0x0F; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M327CW(uint16 A, uint16 V) { + if (reg & 0x10) { + setchr8r(0x10, 0); + } else { + uint16 base = (reg << 7) & 0x380; + uint16 mask = (reg & 0x20) ? 0xFF : 0x7F; + + setchr1(A, base | (V & mask)); + } +} + +static DECLFW(M327Write) { + if (MMC3_WramIsWritable()) { + CartBW(A, V); + if ((reg & 7) == 0) { + reg = A & 0x3F; + MMC3_FixPRG(); + MMC3_FixCHR(); + } + } +} + +static void M327Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M327Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M327Write); +} + +static void M327Close(void) { + MMC3_Close(); +} + +void Mapper327_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = M327PW; + MMC3_cwrap = M327CW; + + info->Power = M327Power; + info->Reset = M327Reset; + info->Close = M327Close; + AddExState(®, 1, 0, "EXPR"); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper328.c b/src/mappers/mapper328.c new file mode 100644 index 000000000..286ef204b --- /dev/null +++ b/src/mappers/mapper328.c @@ -0,0 +1,51 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2016 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Test Ver. 1.01 Dlya Proverki TV Pristavok (RT-01, by SS aka Snake) + * A simple board with 16K PRG ROM + 2K CHR ROM with no mapper, hardwired mirroring + * PRG EPROM has copy protected areas with "weak bits", which is tested at some + * points of the program. Trying to simalate "weak bits" behaviour + * + */ + +/* NES 2.0 Mapper 328 - UNL-RT-01 */ + +#include +#include "mapinc.h" + +static DECLFR(M328Read) { + if (((A >= 0xCE80) && (A < 0xCF00)) || ((A >= 0xFE80) && (A < 0xFF00))) { + return 0xF2 | (rand() & 0x0D); + } + return CartBR(A); +} + +static void M328Power(void) { + setprg16(0x8000, 0); + setprg16(0xC000, 0); + setchr2(0x0000,0); + setchr2(0x0800,0); + setchr2(0x1000,0); + setchr2(0x1800,0); + SetReadHandler(0x8000, 0xFFFF, M328Read); +} + +void Mapper328_Init(CartInfo *info) { + info->Power = M328Power; +} diff --git a/src/mappers/mapper329.c b/src/mappers/mapper329.c new file mode 100644 index 000000000..fda93319a --- /dev/null +++ b/src/mappers/mapper329.c @@ -0,0 +1,37 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2006 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 329 - UNL-EDU2000 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg8r(0x10, 0x6000, latch.data >> 6); + setprg32(0x8000, latch.data & 0x1F); + setchr8(0); + setmirror(((latch.data >> 5) & 0x01) ^ 0x01); +} + +void Mapper329_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper330.c b/src/mappers/mapper330.c new file mode 100644 index 000000000..bf44bcd33 --- /dev/null +++ b/src/mappers/mapper330.c @@ -0,0 +1,135 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 330 is used for a bootleg version of Contra/Gryzor. + * as implemented from + * http://forums.nesdev.org/viewtopic.php?f=9&t=17352&p=218722#p218722 + */ + +#include "mapinc.h" +#include "n163sound.h" + +static uint8 IRQa; +static uint16 IRQCount; + +static uint8 prg[4], chr[8], nt[4]; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { nt, 4, "NTAR" }, + { 0 } +}; + +static void Sync(void) { + int i; + + setprg8r(0x10, 0x6000, 0); + setprg8(0xE000, ~0); + + for (i = 0; i < 3; i++) setprg8(0x8000 + (i << 13), prg[i]); + for (i = 0; i < 8; i++) setchr1(i << 10, chr[i]); + for (i = 0; i < 3; i++) setntamem(NTARAM + 0x400 * (nt[i] & 0x01), 1, i); +} + +static DECLFW(M330WriteCHR) { + if ((A & 0x400) && !(A & 0x4000)) { + if (A & 0x2000) { + IRQCount &= 0x00FF; + IRQCount |= (V & 0x7F) << 8; + IRQa = V & 0x80; + X6502_IRQEnd(FCEU_IQEXT); + } else { + IRQCount &= 0xFF00; + IRQCount |= V; + } + } else { + int index = (A >> 11) & 0x07; + chr[index] = V; + Sync(); + } +} + +static DECLFW(M330WriteNT) { + if (!(A & 0x400)) { + int index = (A >> 11) & 0x03; + nt[index] = V; + Sync(); + } +} + +static DECLFW(M330WritePRG) { + if ((A >= 0xF000) && (A & 0x800)) { + N163Sound_Write(A, V); + } else if (!(A & 0x400)) { + int index = (A >> 11) & 0x03; + prg[index] = V; + Sync(); + } +} + +static void M330Power(void) { + int i; + + for (i = 0; i < 4; i++) prg[i] = i; + for (i = 0; i < 8; i++) chr[i] = i; + for (i = 0; i < 4; i++) nt[i] = (i >> 1) & 0x01; + + IRQa = IRQCount = 0; + + Sync(); + + SetReadHandler(0x4800, 0x4FFF, N163Sound_Read); + SetWriteHandler(0x4800, 0x4FFF, N163Sound_Write); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + + SetWriteHandler(0x8000, 0xBFFF, M330WriteCHR); + SetWriteHandler(0xC000, 0xDFFF, M330WriteNT); + SetWriteHandler(0xE000, 0xFFFF, M330WritePRG); +} + +static void M330IRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount > 0x7FFF) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + IRQCount = 0; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper330_Init(CartInfo *info) { + info->Power = M330Power; + MapIRQHook = M330IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAM = (uint8 *)FCEU_gmalloc(8192); + SetupCartPRGMapping(0x10, WRAM, 8192, 1); + AddExState(WRAM, 8192, 0, "WRAM"); + + N163Sound_ESI(); +} diff --git a/src/mappers/mapper331.c b/src/mappers/mapper331.c new file mode 100644 index 000000000..a8deb637f --- /dev/null +++ b/src/mappers/mapper331.c @@ -0,0 +1,84 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * 7-in-1 Darkwing Duck, Snake, MagicBlock (PCB marked as "12 in 1") + * 12-in-1 1991 New Star Co. Ltd. + * + */ + +#include "mapinc.h" + +static uint8 reg[3]; +static uint8 PPUCHRBus; + +static SFORMAT StateRegs[] = { + { reg, 3, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 base = (reg[2] & 0x03) << 3; + + if (reg[2] & 8) { + setprg16(0x8000, base | ((reg[PPUCHRBus] & 0x06) & ~0x01)); /* actually, both 0 and 1 registers used, but they will switch each PA12 transition */ + setprg16(0xc000, base | ((reg[PPUCHRBus] & 0x06) | 0x01)); /* if bits are different for both registers, so they must be programmed strongly the same! */ + } else { + setprg16(0x8000, base | (reg[PPUCHRBus] & 0x07)); + setprg16(0xc000, base | 0x07); + } + setchr4(0x0000, (base << 2) | (reg[0] >> 3)); + setchr4(0x1000, (base << 2) | (reg[1] >> 3)); + setmirror(((reg[2] & 4) >> 2) ^ 1); +} + +static DECLFW(M331Write) { + switch (A & 0xE000) { + case 0xA000: reg[0] = V; Sync(); break; + case 0xC000: reg[1] = V; Sync(); break; + case 0xE000: reg[2] = V; Sync(); break; + } +} + +static void M331Power(void) { + reg[0] = reg[1] = reg[2] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M331Write); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M331PPUHook(uint32 A) { + uint8 bank = (A & 0x1000) >> 12; + + if ((PPUCHRBus != bank) && ((A & 0x3000) != 0x2000)) { + PPUCHRBus = bank; + Sync(); + } +} + +void Mapper331_Init(CartInfo *info) { + info->Power = M331Power; + PPU_hook = M331PPUHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper332.c b/src/mappers/mapper332.c new file mode 100644 index 000000000..1dc852b89 --- /dev/null +++ b/src/mappers/mapper332.c @@ -0,0 +1,89 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* added 2019-5-23 + * NES 2.0 Mapper 332 + * BMC-WS Used for Super 40-in-1 multicart + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_332 */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[2], dipsw; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint32 prg = ((reg[0] >> 3) & 0x08) | (reg[0] & 0x07); + uint32 chr = ((reg[0] >> 3) & 0x08) | (reg[1] & 0x07); + uint32 mask = (reg[1] & 0x10) ? 0 : (reg[1] & 0x20) ? 1 : 3; + + if (reg[0] & 0x08) { + setprg16(0x8000, prg); + setprg16(0xc000, prg); + } else { + setprg32(0x8000, prg >> 1); + } + setchr8((chr & ~mask) | (latch.data & mask)); + setmirror(((reg[0] >> 4) & 0x01) ^ 0x01); +} + +static DECLFR(M332Read) { + if ((reg[1] >> 6) & (dipsw & 0x03)) { + return CPU_OPENBUS; + } + return CartBR(A); +} + +static DECLFW(M332Write) { + if (!(reg[0] & 0x20)) { + reg[A & 0x01] = V; + Sync(); + } +} + +static void M332Reset(void) { + dipsw++; /* Soft-resetting cycles through solder pad or DIP switch settings */ + if (dipsw == 3) { + dipsw = 0; /* Only 00b, 01b and 10b settings are valid */ + } + /* Always reset to menu */ + reg[0] = reg[1] = 0; + Latch_RegReset(); +} + +static void M332Power(void) { + dipsw = 0; + reg[0] = reg[1] = 0; + Latch_Power(); + SetReadHandler(0x8000, 0xFFFF, M332Read); + SetWriteHandler(0x6000, 0x7FFF, M332Write); +} + +void Mapper332_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = M332Reset; + info->Power = M332Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper333.c b/src/mappers/mapper333.c new file mode 100644 index 000000000..6018f105f --- /dev/null +++ b/src/mappers/mapper333.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2016 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * 8-in-1 Rockin' Kats, Snake, (PCB marked as "8 in 1"), similar to 12IN1, + * but with MMC3 on board, all games are hacked the same, Snake is buggy too! + * + * no reset-citcuit, so selected game can be reset, but to change it you must use power + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M333CW(uint16 A, uint16 V) { + setchr1(A, ((reg & 0x0C) << 5) | (V & 0x7F)); +} + +static void M333PW(uint16 A, uint16 V) { + if (reg & 0x10) { /* MMC3 mode */ + setprg8(A, ((reg & 0x0C) << 2) | (V & 0x0F)); + } else { + setprg32(0x8000, reg & 0x0F); + } +} + +static DECLFW(M333Write) { + if (A & 0x1000) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } else { + MMC3_Write(A, V); + } +} + +static void M333Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x8000, 0xFFFF, M333Write); +} + +void Mapper333_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M333CW; + MMC3_pwrap = M333PW; + info->Power = M333Power; + AddExState(&StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper334.c b/src/mappers/mapper334.c new file mode 100644 index 000000000..b2c94bc21 --- /dev/null +++ b/src/mappers/mapper334.c @@ -0,0 +1,73 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M334PW(uint16 A, uint16 V) { + setprg32(0x8000, reg >> 1); +} + +static DECLFW(M334Write) { + if (!(A & 0x01) && MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + } +} + +static DECLFR(M334Read) { + if (A & 0x02) { + return ((CPU_OPENBUS & 0xFE) | (dipsw & 0x01)); + } + return CPU_OPENBUS; +} + +static void M334Reset(void) { + dipsw++; + reg = 0; + MMC3_Reset(); +} + +static void M334Power(void) { + dipsw = 0; + reg = 0; + MMC3_Power(); + SetReadHandler(0x6000, 0x7FFF, M334Read); + SetWriteHandler(0x6000, 0x7FFF, M334Write); +} + +void Mapper334_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M334PW; + info->Power = M334Power; + info->Reset = M334Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper335.c b/src/mappers/mapper335.c new file mode 100644 index 000000000..57a615976 --- /dev/null +++ b/src/mappers/mapper335.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 mapper 335 is used for a 10-in-1 multicart. + * Its UNIF board name is BMC-CTC-09. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_335 */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (reg[1] & 0x10) { + setprg16(0x8000, ((reg[1] & 0x07) << 1) | ((reg[1] >> 3) & 0x01)); + setprg16(0xC000, ((reg[1] & 0x07) << 1) | ((reg[1] >> 3) & 0x01)); + } else { + setprg32(0x8000, reg[1] & 0x07); + } + setchr8(reg[0] & 0x0F); + setmirror(((reg[1] >> 5) & 0x01) ^ 0x01); +} + +static DECLFW(M335Write) { + switch (A & 0xE000) { + case 0x8000: + case 0xA000: + reg[0] = V; + Sync(); + break; + case 0xC000: + case 0xE000: + reg[1] = V; + Sync(); + break; + } +} + +static void M335Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M335Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper335_Init(CartInfo *info) { + info->Power = M335Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper336.c b/src/mappers/mapper336.c new file mode 100644 index 000000000..b3681b731 --- /dev/null +++ b/src/mappers/mapper336.c @@ -0,0 +1,50 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* BMC-K-3046 */ +/* NES 2.0 mapper 336 is used for an 11-in-1 multicart + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_336 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.data); + setprg16(0xC000, latch.data | 0x07); + setchr8(0); +} + +static DECLFW(M336Write) { + latch.addr = A; + latch.data = V | CartBR(A); + Sync(); +} + +static void M336Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M336Write); +} + +void Mapper336_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M336Power; + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper337.c b/src/mappers/mapper337.c new file mode 100644 index 000000000..83ae9f1bd --- /dev/null +++ b/src/mappers/mapper337.c @@ -0,0 +1,79 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 337 - BMC-CTC-12IN1 + * 12-in-1 Game Card multicart + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_337 + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank = reg & 0x1F; + + setprg8(0x6000, 1); + if (reg & 0x80) { /* UNROM */ + setprg16(0x8000, bank); + setprg16(0xC000, bank | 0x07); + } else { + if (reg & 0x40) { /* NROM-256 */ + setprg32(0x8000, bank >> 1); + } else { /* NROM-128 */ + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } + setchr8(0); + setmirror(((reg >> 5) & 0x01) ^ 0x01); +} + +static DECLFW(M337Write) { + if (A < 0xC000) { + reg = (reg & 0x07) | (V & ~0x07); + } else { + reg = (reg & ~0x07) | (V & 0x07); + } + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M337Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M337Write); +} + +void Mapper337_Init(CartInfo *info) { + info->Power = M337Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper338.c b/src/mappers/mapper338.c new file mode 100644 index 000000000..69c0c3f56 --- /dev/null +++ b/src/mappers/mapper338.c @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* BMC-SA005-A */ +/* NES 2.0 mapper 338 is used for a 16-in-1 and a 200/300/600/1000-in-1 multicart. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_338 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.addr); + setprg16(0xC000, latch.addr); + setchr8(latch.addr); + setmirror((latch.addr >> 3) & 0x01); +} + +void Mapper338_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper339.c b/src/mappers/mapper339.c new file mode 100644 index 000000000..72f7ce483 --- /dev/null +++ b/src/mappers/mapper339.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 mapper 339 is used for a 21-in-1 multicart. + * Its UNIF board name is BMC-K-3006. + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_339 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M339CW(uint16 A, uint16 V) { + setchr1(A, ((reg << 4) & ~0x7F) | (V & 0x7F)); +} + +static void M339PW(uint16 A, uint16 V) { + uint16 base = reg & 0x1F; + + if (reg & 0x20) { /* MMC3 mode */ + setprg8(A, ((base << 1) & ~0x0F) | (V & 0x0F)); + } else { + if ((reg & 0x07) == 0x06) { /* NROM-256 */ + setprg32(0x8000, base >> 1); + } else { /* NROM-128 */ + setprg16(0x8000, base); + setprg16(0xC000, base); + } + } +} + +static DECLFW(M339Write) { + if (MMC3_WramIsWritable()) { + reg = A & 0x3F; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M339Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M339Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M339Write); +} + +void Mapper339_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = M339PW; + MMC3_cwrap = M339CW; + info->Power = M339Power; + info->Reset = M339Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper340.c b/src/mappers/mapper340.c new file mode 100644 index 000000000..5b0c026ab --- /dev/null +++ b/src/mappers/mapper340.c @@ -0,0 +1,50 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 340 + * UNIF BMC-K-3036 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint16 prg = ((latch.addr >> 2) & 0x20) | (latch.addr & 0x1F); + + if (latch.addr & 0x20) { /* NROM-128 */ + if (latch.addr & 0x01) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { /* NROM-256 */ + setprg32(0x8000, prg >> 1); + } + } else { /* UNROM */ + setprg16(0x8000, prg); + setprg16(0xC000, prg | 0x07); + } + SetupCartCHRMapping(0, CHRptr[0], 0x2000, (~latch.addr & 0x20)); + setchr8(0); + setmirror(((latch.addr & 0x40) || ((latch.addr & 0x20) && (latch.addr & 0x04))) ? MI_H : MI_V); +} + +void Mapper340_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper341.c b/src/mappers/mapper341.c new file mode 100644 index 000000000..4596abb58 --- /dev/null +++ b/src/mappers/mapper341.c @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* BMC-TJ-03 */ +/* NES 2.0 mapper 341 is used for a simple 4-in-1 multicart */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 mirr = (latch.addr & ((PRGsize[0] & 0x40000) ? 0x800 : 0x200)) ? MI_H : MI_V; + + setprg32(0x8000, latch.addr >> 8); + setchr8(latch.addr >> 8); + setmirror(mirr); +} + +void Mapper341_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper342.c b/src/mappers/mapper342.c new file mode 100644 index 000000000..48162fa02 --- /dev/null +++ b/src/mappers/mapper342.c @@ -0,0 +1,2304 @@ +/* FCEUmm - NES/Famicom Emulator +* +* Copyright notice for this file: +* Copyright (C) 2022 Cluster +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Very complicated homebrew multicart mapper with. +* The code is so obscured and weird because it's ported from Verilog CPLD source code: +* https://github.com/ClusterM/coolgirl-famicom-multicart/blob/master/CoolGirl_mappers.vh +* +* Range: $5000-$5FFF +* +* Mask: $5007 +* +* All registers are $00 on power-on and reset. +* +* $5xx0 +* 7 bit 0 +* ---- ---- +* PPPP PPPP +* |||| |||| +* ++++-++++-- PRG base offset (A29-A22) +* +* $5xx1 +* 7 bit 0 +* ---- ---- +* PPPP PPPP +* |||| |||| +* ++++-++++-- PRG base offset (A21-A14) +* +* $5xx2 +* 7 bit 0 +* ---- ---- +* AMMM MMMM +* |||| |||| +* |+++-++++-- PRG mask (A20-A14, inverted+anded with PRG address) +* +---------- CHR mask (A18, inverted+anded with CHR address) +* +* $5xx3 +* 7 bit 0 +* ---- ---- +* BBBC CCCC +* |||| |||| +* |||+-++++-- CHR bank A (bits 7-3) +* +++-------- PRG banking mode (see below) +* +* $5xx4 +* 7 bit 0 +* ---- ---- +* DDDE EEEE +* |||| |||| +* |||+-++++-- CHR mask (A17-A13, inverted+anded with CHR address) +* +++-------- CHR banking mode (see below) +* +* $5xx5 +* 7 bit 0 +* ---- ---- +* CDDE EEWW +* |||| |||| +* |||| ||++-- 8KiB WRAM page at $6000-$7FFF +* |+++-++---- PRG bank A (bits 5-1) +* +---------- CHR bank A (bit 8) +* +* $5xx6 +* 7 bit 0 +* ---- ---- +* FFFM MMMM +* |||| |||| +* |||+ ++++-- Mapper code (bits 4-0, see below) +* +++-------- Flags 2-0, functionality depends on selected mapper +* +* $5xx7 +* 7 bit 0 +* ---- ---- +* LMTR RSNO +* |||| |||+-- Enable WRAM (read and write) at $6000-$7FFF +* |||| ||+--- Allow writes to CHR RAM +* |||| |+---- Allow writes to flash chip +* |||+-+----- Mirroring (00=vertical, 01=horizontal, 10=1Sa, 11=1Sb) +* ||+-------- Enable four-screen mode +* |+-- ------ Mapper code (bit 5, see below) +* +---------- Lockout bit (prevent further writes to all registers) +* +*/ + +#include "mapinc.h" + +#define SAVE_FLASH_SIZE (1024 * 1024 * 8) +#define FLASH_SECTOR_SIZE (128 * 1024) +#define ROM_CHIP 0x00 +#define WRAM_CHIP 0x10 +#define FLASH_CHIP 0x11 +#define CFI_CHIP 0x13 + +static uint32 CHR_SIZE = 0; +static uint8 *SAVE_FLASH = NULL; +static uint8 *CFI = NULL; + +static uint8 sram_enabled = 0; +static uint8 sram_page = 0; /* [1:0] */ +static uint8 can_write_chr = 0; +static uint8 map_rom_on_6000 = 0; +static uint8 flags = 0; /* [2:0] */ +static uint8 mapper = 0; /* [5:0] */ +static uint8 can_write_flash = 0; +static uint8 mirroring = 0; /* [1:0] */ +static uint8 four_screen = 0; +static uint8 lockout = 0; + +static uint32 prg_base = 0; /* [26:14] */ +static uint32 prg_mask = 0xF8; /* 11111000, 128KB */ /* [20:14] */ +static uint8 prg_mode = 0; /* [2:0] */ +static uint8 prg_bank_6000 = 0; /* [7:0] */ +static uint8 prg_bank_a = 0; /* [7:0] */ +static uint8 prg_bank_b = 1; /* [7:0] */ +static uint8 prg_bank_c = ~1; /* [7:0] */ +static uint8 prg_bank_d = ~0; /* [7:0] */ + +static uint32 chr_mask = 0; /* [18:13] */ +static uint8 chr_mode = 0; /* [2:0] */ +static uint16 chr_bank_a = 0; /* [8:0] */ +static uint16 chr_bank_b = 1; /* [8:0] */ +static uint16 chr_bank_c = 2; /* [8:0] */ +static uint16 chr_bank_d = 3; /* [8:0] */ +static uint16 chr_bank_e = 4; /* [8:0] */ +static uint16 chr_bank_f = 5; /* [8:0] */ +static uint16 chr_bank_g = 6; /* [8:0] */ +static uint16 chr_bank_h = 7; /* [8:0] */ + +static uint8 TKSMIR[8]; + +static uint32 prg_bank_6000_mapped = 0; +static uint32 prg_bank_a_mapped = 0; +static uint32 prg_bank_b_mapped = 0; +static uint32 prg_bank_c_mapped = 0; +static uint32 prg_bank_d_mapped = 0; + +/* for MMC2/MMC4 */ +static uint8 ppu_latch0 = 0; +static uint8 ppu_latch1 = 0; +/* for MMC1 */ +static uint64 lreset = 0; +static uint8 mmc1_load_register = 0; /* [5:0] */ +/* for MMC3 */ +static uint8 mmc3_internal = 0; /* [2:0] */ +/* for mapper #69 */ +static uint8 mapper69_internal = 0; /* [3:0] */ +/* for mapper #112 */ +static uint8 mapper112_internal = 0; /* [2:0] */ +/* for mapper #163 */ +static uint8 mapper163_latch = 0; +static uint8 mapper163_r0 = 0; /* [7:0] */ +static uint8 mapper163_r1 = 0; /* [7:0] */ +static uint8 mapper163_r2 = 0; /* [7:0] */ +static uint8 mapper163_r3 = 0; /* [7:0] */ +static uint8 mapper163_r4 = 0; /* [7:0] */ +static uint8 mapper163_r5 = 0; /* [7:0] */ + +/* For mapper #90 */ +static uint8 mul1 = 0; +static uint8 mul2 = 0; + +/* for MMC3 scanline-based interrupts, counts A12 rises after long A12 falls */ +static uint8 mmc3_irq_enabled = 0; /* register to enable/disable counter */ +static uint8 mmc3_irq_latch = 0; /* [7:0], stores counter reload latch value */ +static uint8 mmc3_irq_counter = 0; /* [7:0], counter itself (downcounting) */ +static uint8 mmc3_irq_reload = 0; /* flag to reload counter from latch */ +/* for MMC5 scanline-based interrupts, counts dummy PPU reads */ +static uint8 mmc5_irq_enabled = 0; /* register to enable/disable counter */ +static uint8 mmc5_irq_line = 0; /* [7:0], scanline on which IRQ will be triggered */ +static uint8 mmc5_irq_out = 0; /* stores 1 when IRQ is triggered */ +/* for mapper #18 */ +static uint16 mapper18_irq_value = 0; /* [15:0], counter itself (downcounting) */ +static uint8 mapper18_irq_control = 0; /* [3:0], IRQ settings */ +static uint16 mapper18_irq_latch = 0; /* [15:0], stores counter reload latch value */ +/* for mapper #65 */ +static uint8 mapper65_irq_enabled = 0; /* register to enable/disable IRQ */ +static uint16 mapper65_irq_value = 0; /* [15:0], counter itself (downcounting) */ +static uint16 mapper65_irq_latch = 0; /* [15:0], stores counter reload latch value */ +/* reg mapper65_irq_out = 0; */ +/* for Sunsoft FME-7 */ +static uint8 mapper69_irq_enabled = 0; /* register to enable/disable IRQ */ +static uint8 mapper69_counter_enabled = 0; /* register to enable/disable counter */ +static uint16 mapper69_irq_value = 0; /* counter itself (downcounting) */ +/* for VRC4 CPU-based interrupts */ +static uint8 vrc4_irq_value = 0; /* [7:0], counter itself (upcounting) */ +static uint8 vrc4_irq_control = 0; /* [2:0]� IRQ settings */ +static uint8 vrc4_irq_latch = 0; /* [7:0], stores counter reload latch value */ +static uint8 vrc4_irq_prescaler = 0; /* [6:0], prescaler counter for VRC4 */ +static uint8 vrc4_irq_prescaler_counter = 0; /* prescaler cicles counter for VRC4 */ +/* for VRC3 CPU-based interrupts */ +static uint16 vrc3_irq_value = 0; /* [15:0], counter itself (upcounting) */ +static uint8 vrc3_irq_control = 0; /* [3:0], IRQ settings */ +static uint16 vrc3_irq_latch = 0; /* [15:0], stores counter reload latch value */ +/* for mapper #42 (only Baby Mario) */ +static uint8 mapper42_irq_enabled = 0; /* register to enable/disable counter */ +static uint16 mapper42_irq_value = 0; /* [14:0], counter itself (upcounting) */ +/* for mapper #83 */ +static uint8 mapper83_irq_enabled_latch = 0; +static uint8 mapper83_irq_enabled = 0; +static uint16 mapper83_irq_counter = 0; +/* for mapper #90 */ +static uint8 mapper90_xor = 0; +/* for mapper #67 */ +static uint8 mapper67_irq_enabled = 0; +static uint8 mapper67_irq_latch = 0; +static uint16 mapper67_irq_counter = 0; + +static uint8 flash_state = 0; +static uint16 flash_buffer_a[10]; +static uint8 flash_buffer_v[10]; +static uint8 cfi_mode = 0; + +static uint8 show_error_log = 0; +static uint8 vrc24_compatibility = 0; + +static uint8 ntaramExtra[0x800]; /* for 4-screen mirroring */ + +/* Micron 4-gbit memory CFI data */ +static const uint8 cfi_data[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x52, 0x59, 0x02, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x27, 0x36, 0x00, 0x00, 0x06, + 0x06, 0x09, 0x13, 0x03, 0x05, 0x03, 0x02, 0x1E, + 0x02, 0x00, 0x06, 0x00, 0x01, 0xFF, 0x03, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + 0x50, 0x52, 0x49, 0x31, 0x33, 0x14, 0x02, 0x01, + 0x00, 0x08, 0x00, 0x00, 0x02, 0xB5, 0xC5, 0x05, + 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static void SyncPRG(void) { + uint8 REG_A_CHIP, REG_B_CHIP, REG_C_CHIP, REG_D_CHIP; + + prg_bank_6000_mapped = (prg_base << 1) | (prg_bank_6000 & ((~(prg_mask << 1) & 0xFE) | 1)); + prg_bank_a_mapped = (prg_base << 1) | (prg_bank_a & ((~(prg_mask << 1) & 0xFE) | 1)); + prg_bank_b_mapped = (prg_base << 1) | (prg_bank_b & ((~(prg_mask << 1) & 0xFE) | 1)); + prg_bank_c_mapped = (prg_base << 1) | (prg_bank_c & ((~(prg_mask << 1) & 0xFE) | 1)); + prg_bank_d_mapped = (prg_base << 1) | (prg_bank_d & ((~(prg_mask << 1) & 0xFE) | 1)); + REG_A_CHIP = (SAVE_FLASH != NULL && prg_bank_a_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP; + REG_B_CHIP = (SAVE_FLASH != NULL && prg_bank_b_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP; + REG_C_CHIP = (SAVE_FLASH != NULL && prg_bank_c_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP; + REG_D_CHIP = (SAVE_FLASH != NULL && prg_bank_d_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP; + + if (!cfi_mode || !SAVE_FLASH) { + switch (prg_mode & 0x07) { + default: + case 0: + setprg16r(REG_A_CHIP, 0x8000, prg_bank_a_mapped >> 1); + setprg16r(REG_C_CHIP, 0xC000, prg_bank_c_mapped >> 1); + break; + case 1: + setprg16r(REG_C_CHIP, 0x8000, prg_bank_c_mapped >> 1); + setprg16r(REG_A_CHIP, 0xC000, prg_bank_a_mapped >> 1); + break; + case 4: + setprg8r(REG_A_CHIP, 0x8000, prg_bank_a_mapped); + setprg8r(REG_B_CHIP, 0xA000, prg_bank_b_mapped); + setprg8r(REG_C_CHIP, 0xC000, prg_bank_c_mapped); + setprg8r(REG_D_CHIP, 0xE000, prg_bank_d_mapped); + break; + case 5: + setprg8r(REG_C_CHIP, 0x8000, prg_bank_c_mapped); + setprg8r(REG_B_CHIP, 0xA000, prg_bank_b_mapped); + setprg8r(REG_A_CHIP, 0xC000, prg_bank_a_mapped); + setprg8r(REG_D_CHIP, 0xE000, prg_bank_d_mapped); + break; + case 6: + setprg32r(REG_B_CHIP, 0x8000, prg_bank_b_mapped >> 2); + break; + case 7: + setprg32r(REG_A_CHIP, 0x8000, prg_bank_a_mapped >> 2); + break; + } + } else { + setprg32r(CFI_CHIP, 0x8000, 0); + } + + if (!map_rom_on_6000 && WRAM) { + setprg8r(WRAM_CHIP, 0x6000, sram_page); /* Select SRAM page */ + } else if (map_rom_on_6000) { + setprg8(0x6000, prg_bank_6000_mapped); /* Map ROM on $6000-$7FFF */ + } +} + +static void SyncCHR(void) { + /* calculate CHR shift */ + /* wire shift_chr_right = ENABLE_MAPPER_021_022_023_025 && ENABLE_MAPPER_022 && (mapper == 6'b011000) && flags[1]; */ + int chr_shift = ((mapper == 24) && (flags & 2)) ? 1 : 0; + + /* enable or disable writes to CHR RAM, setup CHR mask */ + SetupCartCHRMapping(0, CHR_ROM_DATA, ((((~chr_mask & 0x3F) + 1) * 0x2000 - 1) & (CHR_SIZE - 1)) + 1, can_write_chr); + + switch (chr_mode & 0x07) { + default: + case 0: + setchr8(chr_bank_a >> 3 >> chr_shift); + break; + case 1: + setchr4(0x0000, mapper163_latch >> chr_shift); + setchr4(0x1000, mapper163_latch >> chr_shift); + break; + case 2: + setchr2(0x0000, chr_bank_a >> 1 >> chr_shift); + TKSMIR[0] = TKSMIR[1] = chr_bank_a; + setchr2(0x0800, chr_bank_c >> 1 >> chr_shift); + TKSMIR[2] = TKSMIR[3] = chr_bank_c; + setchr1(0x1000, chr_bank_e >> chr_shift); + TKSMIR[4] = chr_bank_e; + setchr1(0x1400, chr_bank_f >> chr_shift); + TKSMIR[5] = chr_bank_f; + setchr1(0x1800, chr_bank_g >> chr_shift); + TKSMIR[6] = chr_bank_g; + setchr1(0x1C00, chr_bank_h >> chr_shift); + TKSMIR[7] = chr_bank_h; + break; + case 3: + setchr1(0x0000, chr_bank_e >> chr_shift); + TKSMIR[0] = chr_bank_e; + setchr1(0x0400, chr_bank_f >> chr_shift); + TKSMIR[1] = chr_bank_f; + setchr1(0x0800, chr_bank_g >> chr_shift); + TKSMIR[2] = chr_bank_g; + setchr1(0x0C00, chr_bank_h >> chr_shift); + TKSMIR[3] = chr_bank_h; + setchr2(0x1000, chr_bank_a >> 1 >> chr_shift); + TKSMIR[4] = TKSMIR[5] = chr_bank_a; + setchr2(0x1800, chr_bank_c >> 1 >> chr_shift); + TKSMIR[6] = TKSMIR[7] = chr_bank_c; + break; + case 4: + setchr4(0x0000, chr_bank_a >> 2 >> chr_shift); + setchr4(0x1000, chr_bank_e >> 2 >> chr_shift); + break; + case 5: + if (!ppu_latch0) { + setchr4(0x0000, chr_bank_a >> 2 >> chr_shift); + } else { + setchr4(0x0000, chr_bank_b >> 2 >> chr_shift); + } + if (!ppu_latch1) { + setchr4(0x1000, chr_bank_e >> 2 >> chr_shift); + } else { + setchr4(0x1000, chr_bank_f >> 2 >> chr_shift); + } + break; + case 6: + setchr2(0x0000, chr_bank_a >> 1 >> chr_shift); + setchr2(0x0800, chr_bank_c >> 1 >> chr_shift); + setchr2(0x1000, chr_bank_e >> 1 >> chr_shift); + setchr2(0x1800, chr_bank_g >> 1 >> chr_shift); + break; + case 7: + setchr1(0x0000, chr_bank_a >> chr_shift); + setchr1(0x0400, chr_bank_b >> chr_shift); + setchr1(0x0800, chr_bank_c >> chr_shift); + setchr1(0x0C00, chr_bank_d >> chr_shift); + setchr1(0x1000, chr_bank_e >> chr_shift); + setchr1(0x1400, chr_bank_f >> chr_shift); + setchr1(0x1800, chr_bank_g >> chr_shift); + setchr1(0x1C00, chr_bank_h >> chr_shift); + break; + } +} + +static void SyncMIR(void) { + if (four_screen) { + /* setmirror(MI_4); */ + SetupCartMirroring(4, 0, ntaramExtra); + } else { + if (!((mapper == 20) && (flags & 1))) { /* Mapper #189? */ + switch (mirroring) { + case 0: + setmirror(MI_V); + break; + case 1: + setmirror(MI_H); + break; + case 2: + setmirror(MI_0); + break; + case 3: + setmirror(MI_1); + break; + } + } + } +} + +static void Sync(void) { + SyncPRG(); + SyncCHR(); + SyncMIR(); +} + +static DECLFW(COOLGIRL_Flash_Write) { + if (flash_state < sizeof(flash_buffer_a) / sizeof(flash_buffer_a[0])) { + flash_buffer_a[flash_state] = A & 0xFFF; + flash_buffer_v[flash_state] = V; + flash_state++; + + /* enter CFI mode */ + if ((flash_state == 1) && + (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0x98)) { + cfi_mode = 1; + flash_state = 0; + } + + /* sector erase */ + if ((flash_state == 6) && + (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) && + (flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) && + (flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0x80) && + (flash_buffer_a[3] == 0x0AAA) && (flash_buffer_v[3] == 0xAA) && + (flash_buffer_a[4] == 0x0555) && (flash_buffer_v[4] == 0x55) && + (flash_buffer_v[5] == 0x30)) { + int sector = prg_bank_a_mapped * 0x2000 / FLASH_SECTOR_SIZE; + uint32 sector_address = sector * FLASH_SECTOR_SIZE; + uint32 i; + for (i = sector_address; i < sector_address + FLASH_SECTOR_SIZE; i++) + SAVE_FLASH[i % SAVE_FLASH_SIZE] = 0xFF; + FCEU_printf("Flash sector #%d is erased: 0x%08x - 0x%08x.\n", sector, sector_address, sector_address + FLASH_SECTOR_SIZE - 1); + flash_state = 0; + } + + /* write byte */ + if ((flash_state == 4) && + (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) && + (flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) && + (flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0xA0)) { + /*int sector = prg_bank_a_mapped * 0x2000 / FLASH_SECTOR_SIZE; */ + uint32 flash_addr = prg_bank_a_mapped * 0x2000 + (A % 0x8000); + if (SAVE_FLASH[flash_addr % SAVE_FLASH_SIZE] != 0xFF) { + if (!(show_error_log & 2)) { + FCEU_PrintError("Error: can't write to 0x%08x, flash sector is not erased.\n", flash_addr); + show_error_log |= 2; /* show error log only on reset or power-on */ + } + } else { + SAVE_FLASH[flash_addr % SAVE_FLASH_SIZE] = V; + } + flash_state = 0; + } + } + + /* not a command */ + if (((A & 0xFFF) != 0x0AAA) && ((A & 0xFFF) != 0x0555)) { + flash_state = 0; + } + + /* reset */ + if (V == 0xF0) { + flash_state = 0; + cfi_mode = 0; + } + + SyncPRG(); +} + +static DECLFW(M342Write) { + if (sram_enabled && A >= 0x6000 && A < 0x8000 && !map_rom_on_6000) { + CartBW(A, V); /* SRAM is enabled and writable */ + } + + if (SAVE_FLASH && can_write_flash && A >= 0x8000) { + /* writing flash */ + COOLGIRL_Flash_Write(A, V); + } + + /* block two writes in a row */ + if ((timestampbase + timestamp) < (lreset + 2)) { + return; + } + lreset = timestampbase + timestamp; + + if (A >= 0x5000 && A < 0x6000 && !lockout) { + switch (A & 0x07) { + case 0: + /* use bits 29-27 to simulate flash memory */ + prg_base = (prg_base & 0xFF) | (V << 8); + break; + case 1: + prg_base = (prg_base & 0xFF00) | V; + break; + case 2: + chr_mask = (chr_mask & 0x1F) | ((V & 0x80) >> 2); + prg_mask = V & 0x7F; + break; + case 3: + prg_mode = V >> 5; + chr_bank_a = (chr_bank_a & 0x07) | (V << 3); + break; + case 4: + chr_mode = V >> 5; + chr_mask = (chr_mask & 0x20) | (V & 0x1F); + break; + case 5: + chr_bank_a = (chr_bank_a & 0xFF) | ((V & 0x80) << 1); + prg_bank_a = (prg_bank_a & 0xC1) | ((V & 0x7C) >> 1); + sram_page = V & 0x03; + break; + case 6: + flags = V >> 5; + mapper = (mapper & 0x20) | (V & 0x1F); + break; + case 7: + lockout = V >> 7; + mapper = (mapper & 0x1F) | ((V & 0x40) >> 1); + four_screen = (V & 0x20) >> 5; + mirroring = (V & 0x18) >> 3; + can_write_flash = (V & 4) >> 2; + can_write_chr = (V & 2) >> 1; + sram_enabled = V & 1; + switch (mapper) { + case 14: + /* Mapper #65 - Irem's H3001 */ + prg_bank_b = 1; + break; + case 17: + /* MMC2 */ + prg_bank_b = ~2; + break; + case 23: + /* Mapper #42 */ + map_rom_on_6000 = 1; + break; + } + break; + } + if (lockout) { + FCEU_printf("mapper code = %d flags: %02x four-screen = %d\n", mapper, flags, four_screen); + } + } + + /* $0000-$7FFF */ + if (A < 0x8000) { + /* Mapper #163 */ + if (mapper == 6) { + if (A == 0x5101) { + if (mapper163_r4 && !V) { + mapper163_r5 ^= 1; + } + mapper163_r4 = V; + } else if (A == 0x5100 && V == 6) { + prg_mode = prg_mode & 0xFE; + prg_bank_b = 12; + } else { + if ((A & 0x7000) == 0x5000) { + switch ((A & 0x300) >> 8) { + case 2: + prg_mode |= 1; + prg_bank_a = (prg_bank_a & 0x3F) | ((V & 0x03) << 6); + mapper163_r0 = V; + break; + case 0: + prg_mode |= 1; + prg_bank_a = (prg_bank_a & 0xC3) | ((V & 0x0F) << 2); + chr_mode = (chr_mode & 0xFE) | (V >> 7); + mapper163_r1 = V; + break; + case 3: + mapper163_r2 = V; + break; + case 1: + mapper163_r3 = V; + break; + } + } + } + } + + /* Mapper #87 */ + if (mapper == 12) { + /* $6000-$7FFF */ + if ((A & 0x6000) == 0x6000) { + chr_bank_a = (chr_bank_a & 0xE7) | ((V & 0x01) << 4) | ((V & 0x02) << 2); + } + } + + /* Mapper #90 - JY */ + /* + if (mapper == 13) + { + switch (A) + { + case 0x5800: mul1 = V; break; + case 0x5801: mul2 = V; break; + } + } + */ + + /* MMC5 (not really) */ + if (mapper == 15) { + switch (A) { + case 0x5105: + if (V == 0xFF) { + four_screen = 1; + } else { + four_screen = 0; + switch (((V >> 2) & 0x01) | ((V >> 3) & 0x02)) { + case 0: + mirroring = 2; + break; + case 1: + mirroring = 0; + break; + case 2: + mirroring = 1; + break; + case 3: + mirroring = 3; + break; + } + } + break; + case 0x5115: + prg_bank_a = V & 0x1E; + prg_bank_b = (V & 0x1E) | 1; + break; + case 0x5116: + prg_bank_c = V & 0x1F; + break; + case 0x5117: + prg_bank_d = V & 0x1F; + break; + case 0x5120: + chr_bank_a = V; + break; + case 0x5121: + chr_bank_b = V; + break; + case 0x5122: + chr_bank_c = V; + break; + case 0x5123: + chr_bank_d = V; + break; + case 0x5128: + chr_bank_e = V; + break; + case 0x5129: + chr_bank_f = V; + break; + case 0x512A: + chr_bank_g = V; + break; + case 0x512B: + chr_bank_h = V; + break; + case 0x5203: + X6502_IRQEnd(FCEU_IQEXT); + mmc5_irq_out = 0; + mmc5_irq_line = V; + break; + case 0x5204: + X6502_IRQEnd(FCEU_IQEXT); + mmc5_irq_out = 0; + mmc5_irq_enabled = (V & 0x80) >> 7; + break; + } + } + + /* Mapper #189 */ + if (mapper == 20) { + /* $4120-$7FFF */ + if ((flags & 0x02) && (A >= 0x4120)) { + prg_bank_a = (prg_bank_a & 0xC3) | ((V & 0x0F) << 2) | ((V & 0xF0) >> 2); + } + } + + /* Mappers #79 and #146 - NINA-03/06 and Sachen 3015: (flag0 = 1) */ + if (mapper == 27) { + if ((A & 0x6100) == 0x4100) { + chr_bank_a = (chr_bank_a & 0xC7) | ((V & 0x07) << 3); + prg_bank_a = (chr_bank_a & 0xF8) | ((V & 0x08) >> 1); + } + } + + /* Mapper #133 */ + if (mapper == 28) { + if ((A & 0x6100) == 0x4100) { + chr_bank_a = (chr_bank_a & 0xE7) | ((V & 0x03) << 3); + prg_bank_a = (chr_bank_a & 0xF8) | (V & 0x04); + } + } + + /* Mapper #184 */ + if (mapper == 31) { + if ((A & 0x6000) == 0x6000) { + chr_bank_a = (chr_bank_a & 0xE3) | ((V & 0x07) << 2); + chr_bank_e = (chr_bank_e & 0xE3) | ((V & 0x30) >> 2) | 0x10; + } + } + + /* Mapper #38 */ + if (mapper == 32) { + if ((A & 0x7000) == 0x7000) { + prg_bank_a = (prg_bank_a & 0xF7) | ((V & 0x03) << 2); + chr_bank_a = (chr_bank_a & 0xE7) | ((V & 0x0C) << 1); + } + } + } else { /* $8000-$FFFF */ + /* Mapper #2 - UxROM */ + /* flag0 - mapper #71 - for Fire Hawk only. */ + /* other mapper-#71 games are UxROM */ + if (mapper == 1) { + if (!(flags & 0x01) || ((A & 0x7000) != 0x1000)) { + /* UxROM_BITSIZE = 4 */ + prg_bank_a = (prg_bank_a & 0xC1) | ((V & 0x1F) << 1); + if (flags & 0x02) { + /* One screen mirroring select, CHR RAM bank, PRG ROM bank */ + mirroring = 0x02 | (V >> 7); + chr_bank_a = (chr_bank_a & 0xFC) | ((V & 0x60) >> 5); + } + } else { + /* CodeMasters, blah. Mirroring control used only by Fire Hawk */ + mirroring = 0x02 | ((V >> 4) & 0x01); + } + } + + /* Mapper #3 - CNROM */ + if (mapper == 2) { + chr_bank_a = (chr_bank_a & 0x07) | ((V & 0x1F) << 3); + } + + /* Mapper #78 - Holy Diver */ + if (mapper == 3) { + prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x07) << 1); + chr_bank_a = (chr_bank_a & 0x87) | ((V & 0xF0) >> 1); + mirroring = ((V >> 3) & 1) ^ 1; + } + + /* Mapper #97 - Irem's TAM-S1 */ + if (mapper == 4) { + prg_bank_a = (prg_bank_a & 0xC1) | ((V & 0x1F) << 1); + mirroring = (V >> 7) ^ 1; + } + + /* Mapper #93 - Sunsoft-2 */ + if (mapper == 5) { + prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x70) >> 3); + can_write_chr = V & 0x01; + } + + /* Mapper #18 */ + if (mapper == 7) { + switch (((A & 0x7000) >> 10) | (A & 0x03)) { + case 0: /* $8000 */ + prg_bank_a = (prg_bank_a & 0xF0) | (V & 0x0F); + break; + case 1: /* $8001 */ + prg_bank_a = (prg_bank_a & 0x0F) | ((V & 0x0F) << 4); + break; + case 2: /* $8002 */ + prg_bank_b = (prg_bank_b & 0xF0) | (V & 0x0F); + break; + case 3: /* $8003 */ + prg_bank_b = (prg_bank_b & 0x0F) | ((V & 0x0F) << 4); + break; + case 4: /* $9000 */ + prg_bank_c = (prg_bank_c & 0xF0) | (V & 0x0F); + break; + case 5: /* $9001 */ + prg_bank_c = (prg_bank_c & 0x0F) | ((V & 0x0F) << 4); + break; + case 6: + break; + case 7: + break; + case 8: /* $A000 */ + chr_bank_a = (chr_bank_a & 0xF0) | (V & 0x0F); + break; + case 9: /* $A001 */ + chr_bank_a = (chr_bank_a & 0x0F) | ((V & 0x0F) << 4); + break; + case 10: /* $A002 */ + chr_bank_b = (chr_bank_b & 0xF0) | (V & 0x0F); + break; + case 11: /* $A003 */ + chr_bank_b = (chr_bank_b & 0x0F) | ((V & 0x0F) << 4); + break; + case 12: /* $B000 */ + chr_bank_c = (chr_bank_c & 0xF0) | (V & 0x0F); + break; + case 13: /* $B001 */ + chr_bank_c = (chr_bank_c & 0x0F) | ((V & 0x0F) << 4); + break; + case 14: /* $B002 */ + chr_bank_d = (chr_bank_d & 0xF0) | (V & 0x0F); + break; + case 15: /* $B003 */ + chr_bank_d = (chr_bank_d & 0x0F) | ((V & 0x0F) << 4); + break; + case 16: /* $C000 */ + chr_bank_e = (chr_bank_e & 0xF0) | (V & 0x0F); + break; + case 17: /* $C001 */ + chr_bank_e = (chr_bank_e & 0x0F) | ((V & 0x0F) << 4); + break; + case 18: /* $C002 */ + chr_bank_f = (chr_bank_f & 0xF0) | (V & 0x0F); + break; + case 19: /* $C003 */ + chr_bank_f = (chr_bank_f & 0x0F) | ((V & 0x0F) << 4); + break; + case 20: /* $D000 */ + chr_bank_g = (chr_bank_g & 0xF0) | (V & 0x0F); + break; + case 21: /* $D001 */ + chr_bank_g = (chr_bank_g & 0x0F) | ((V & 0x0F) << 4); + break; + case 22: /* $D002 */ + chr_bank_h = (chr_bank_h & 0xF0) | (V & 0x0F); + break; + case 23: /* $D003 */ + chr_bank_h = (chr_bank_h & 0x0F) | ((V & 0x0F) << 4); + break; + case 24: /* $E000 */ + mapper18_irq_latch = (mapper18_irq_latch & 0xFFF0) | (V & 0x0F); + break; + case 25: /* $E001 */ + mapper18_irq_latch = (mapper18_irq_latch & 0xFF0F) | ((V & 0x0F) << 4); + break; + case 26: /* $E002 */ + mapper18_irq_latch = (mapper18_irq_latch & 0xF0FF) | ((V & 0x0F) << 8); + break; + case 27: /* $E003 */ + mapper18_irq_latch = (mapper18_irq_latch & 0x0FFF) | ((V & 0x0F) << 12); + break; + case 28: /* $F000 */ + X6502_IRQEnd(FCEU_IQEXT); + mapper18_irq_value = mapper18_irq_latch; + break; + case 29: /* $F001 */ + X6502_IRQEnd(FCEU_IQEXT); + mapper18_irq_control = V & 0x0F; + break; + case 30: + switch (A & 3) { + case 0: + mirroring = 1; + break; /* Horz */ + case 1: + mirroring = 0; + break; /* Vert */ + case 2: + mirroring = 2; + break; /* 1SsA */ + case 3: + mirroring = 3; + break; /* 1SsB */ + } + break; + case 31: + break; /* sound */ + } + } + + /* Mapper #7 - AxROM, mapper #241 - BNROM */ + if (mapper == 8) { + prg_bank_a = (prg_bank_a & 0xC3) | ((V & 0x0F) << 2); + if (!(flags & 0x01)) { + mirroring = 0x02 | ((V >> 4) & 0x01); + } + } + + /* Mapper #228 - Cheetahmen II */ + if (mapper == 9) { + prg_bank_a = (prg_bank_a & 0xC3) | ((A & 0x0780) >> 5); + chr_bank_a = (chr_bank_a & 0x07) | ((A & 0x0007) << 5) | ((V & 0x03) << 3); + mirroring = (A >> 13) & 0x01; + } + + /* Mapper #11 - ColorDreams */ + if (mapper == 10) { + prg_bank_a = (prg_bank_a & 0xF3) | ((V & 0x03) << 2); + chr_bank_a = (chr_bank_a & 0x87) | ((V & 0xF0) >> 1); + } + + /* Mapper #66 - GxROM */ + if (mapper == 11) { + prg_bank_a = (prg_bank_a & 0xF3) | ((V & 0x30) >> 2); + chr_bank_a = (chr_bank_a & 0xE7) | ((V & 0x03) << 3); + } + + /* Mapper #90 - JY */ + if (mapper == 13) { + switch (A & 0xF000) { + case 0x8000: + switch (A & 0x03) { + case 0: + prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); + break; + case 1: + prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); + break; + case 2: + prg_bank_c = (prg_bank_c & 0xC0) | (V & 0x3F); + break; + case 3: + prg_bank_d = (prg_bank_d & 0xC0) | (V & 0x3F); + break; + } + break; + case 0x9000: + switch (A & 0x07) { + case 0: + chr_bank_a = V; + break; /* $9000 */ + case 1: + chr_bank_b = V; + break; /* $9001 */ + case 2: + chr_bank_c = V; + break; /* $9002 */ + case 3: + chr_bank_d = V; + break; /* $9003 */ + case 4: + chr_bank_e = V; + break; /* $9004 */ + case 5: + chr_bank_f = V; + break; /* $9005 */ + case 6: + chr_bank_g = V; + break; /* $9006 */ + case 7: + chr_bank_h = V; + break; /* $9007 */ + } + break; + case 0xC000: + /* use MMC3's IRQs */ + switch (A & 0x07) { + case 0: + if (V & 0x01) { + mmc3_irq_enabled = 1; + } else { + X6502_IRQEnd(FCEU_IQEXT); + mmc3_irq_enabled = 0; + } + break; + case 1: + break; /* who cares about this shit? */ + case 2: + mmc3_irq_enabled = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 3: + mmc3_irq_enabled = 1; + break; + case 4: + break; /* prescaler? who cares? */ + case 5: + mmc3_irq_latch = V ^ mapper90_xor; + mmc3_irq_reload = 1; + break; + case 6: + mapper90_xor = V; + break; + case 7: + break; /* meh */ + } + break; + case 0xD000: + if ((A & 0x03) == 1) { + mirroring = V & 0x03; + } + break; + } + } + + /* Mapper #65 - Irem's H3001 */ + if (mapper == 14) { + switch (((A & 0x7000) >> 9) | (A & 0x07)) { + case 0: /* $8000 */ + prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); + break; + case 9: /* $9001, mirroring */ + mirroring = (V >> 7) & 0x01; + break; + case 11: /* $9003, enable IRQ */ + X6502_IRQEnd(FCEU_IQEXT); + mapper65_irq_enabled = V >> 7; + break; + case 12: /* $9004 */ + X6502_IRQEnd(FCEU_IQEXT); /* mapper65_irq_out = 0; */ /* ack */ + mapper65_irq_value = mapper65_irq_latch; /* $9004, IRQ reload */ + break; + case 13: /* $9005, IRQ high V */ + mapper65_irq_latch = (mapper65_irq_latch & 0x00FF) | (V << 8); + break; + case 14: /* $9006, IRQ low V */ + mapper65_irq_latch = (mapper65_irq_latch & 0xFF00) | V; + break; + case 16: /* $A000 */ + prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); + break; + case 24: /* $B000 */ + chr_bank_a = V; + break; + case 25: /* $B001 */ + chr_bank_b = V; + break; + case 26: /* $B002 */ + chr_bank_c = V; + break; + case 27: /* $B003 */ + chr_bank_d = V; + break; + case 28: /* $B004 */ + chr_bank_e = V; + break; + case 29: /* $B005 */ + chr_bank_f = V; + break; + case 30:/* $B006 */ + chr_bank_g = V; + break; + case 31: /* $B007 */ + chr_bank_h = V; + break; + case 32: /* $C000 */ + prg_bank_c = (prg_bank_c & 0xC0) | (V & 0x3F); + break; + } + } + + /* Mapper #1 - MMC1 */ + /* + r0 - load register + flag0 - 16KB of SRAM (SOROM) + */ + if (mapper == 16) { + if (V & 0x80) { + /* reset */ + mmc1_load_register = (mmc1_load_register & 0xC0) | 0x20; + prg_mode = 0; + prg_bank_c = (prg_bank_c & 0xE0) | 0x1E; + } else { + mmc1_load_register = (mmc1_load_register & 0xC0) | ((V & 0x01) << 5) | + ((mmc1_load_register & 0x3E) >> 1); + if (mmc1_load_register & 0x01) { + switch (A & 0xE000) { + case 0x8000: + if ((mmc1_load_register & 0x18) == 0x18) { + prg_mode = 0; + prg_bank_c = (prg_bank_c & 0xE1) | 0x1E; + } else if ((mmc1_load_register & 0x18) == 0x10) { + prg_mode = 1; + prg_bank_c = (prg_bank_c & 0xE1); + } else { + prg_mode = 7; + } + if (mmc1_load_register & 0x20) { + chr_mode = 4; + } else { + chr_mode = 0; + } + mirroring = ((mmc1_load_register >> 1) & 0x03) ^ 2; + break; + case 0xA000: + chr_bank_a = (chr_bank_a & 0x83) | ((mmc1_load_register & 0x3E) << 1); + if (flags & 0x01) { + /* (flags[0]) - 16KB of SRAM */ + /* PRG RAM page #2 is battery backed */ + sram_page = 0x02 | (((mmc1_load_register >> 4) & 0x01) ^ 0x01); + } + prg_bank_a = (prg_bank_a & 0xDF) | (mmc1_load_register & 0x20); /* for SUROM, 512k PRG support */ + prg_bank_c = (prg_bank_c & 0xDF) | (mmc1_load_register & 0x20); /* for SUROM, 512k PRG support */ + break; + case 0xC000: + chr_bank_e = (chr_bank_e & 0x83) | ((mmc1_load_register & 0x3E) << 1); + break; + case 0xE000: + prg_bank_a = (prg_bank_a & 0xE1) | (mmc1_load_register & 0x1E); + sram_enabled = ((mmc1_load_register >> 5) & 0x01) ^ 0x01; + break; + } + mmc1_load_register = 0x20; + } + } + } + + /* Mapper #9 and #10 - MMC2 and MMC4 */ + /* flag0 - 0=MMC2, 1=MMC4 */ + if (mapper == 17) { + switch ((A >> 12) & 0x07) { + case 2: /* $A000-$AFFF */ + if (!(flags & 0x01)) { + /* MMC2 */ + prg_bank_a = (prg_bank_a & 0xF0) | (V & 0x0F); + } else { + /* MMC4 */ + prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0x0F) << 1); + } + break; + case 3: /* $B000-$BFFF */ + chr_bank_a = (chr_bank_a & 0x83) | ((V & 0x1F) << 2); + break; + case 4: /* $C000-$CFFF */ + chr_bank_b = (chr_bank_b & 0x83) | ((V & 0x1F) << 2); + break; + case 5: /* $D000-$DFFF */ + chr_bank_e = (chr_bank_e & 0x83) | ((V & 0x1F) << 2); + break; + case 6: /* $E000-$EFFF */ + chr_bank_f = (chr_bank_f & 0x83) | ((V & 0x1F) << 2); + break; + case 7: /* $F000-$FFFF */ + mirroring = V & 0x01; + break; + } + } + + /* Mapper #152 */ + if (mapper == 18) { + chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x0F) << 3); + prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x70) >> 3); + mirroring = 0x02 | (V >> 7); + } + + /* Mapper #73 - VRC3 */ + if (mapper == 19) { + switch (A & 0xF000) { + case 0x8000: + vrc3_irq_latch = (vrc3_irq_latch & 0xFFF0) | (V & 0x0F); + break; + case 0x9000: + vrc3_irq_latch = (vrc3_irq_latch & 0xFF0F) | ((V & 0x0F) << 4); + break; + case 0xA000: + vrc3_irq_latch = (vrc3_irq_latch & 0xF0FF) | ((V & 0x0F) << 8); + break; + case 0xB000: + vrc3_irq_latch = (vrc3_irq_latch & 0x0FFF) | ((V & 0x0F) << 12); + break; + case 0xC000: + X6502_IRQEnd(FCEU_IQEXT); /* ack */ + vrc3_irq_control = (vrc3_irq_control & 0xF8) | (V & 0x07); + if (vrc3_irq_control & 0x02) { + vrc3_irq_value = vrc3_irq_latch; + } + break; + case 0xD000: + X6502_IRQEnd(FCEU_IQEXT); /* ack */ + vrc3_irq_control = (vrc3_irq_control & 0xFD) | (vrc3_irq_control & 0x01) << 1; + break; + case 0xE000: + break; + case 0xF000: + prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x07) << 1); + break; + } + } + + /* Mapper #4 - MMC3/MMC6 */ + /* + flag0 - TxSROM + flag1 - mapper #189 + */ + if (mapper == 20) { + switch (((A & 0x6000) >> 12) | (A & 0x01)) { + case 0: /* $8000-$9FFE, even */ + mmc3_internal = (mmc3_internal & 0xF8) | (V & 0x07); + if (!(flags & 0x02) && !(flags & 0x04)) { + if (V & 0x40) { + prg_mode = 5; + } else { + prg_mode = 4; + } + } + if (!(flags & 0x04)) { + if (V & 0x80) { + chr_mode = 3; + } else { + chr_mode = 2; + } + } + break; + case 1: /* $8001-$9FFF, odd */ + switch (mmc3_internal & 0x07) { + case 0: + chr_bank_a = V; + break; + case 1: + chr_bank_c = V; + break; + case 2: + chr_bank_e = V; + break; + case 3: + chr_bank_f = V; + break; + case 4: + chr_bank_g = V; + break; + case 5: + chr_bank_h = V; + break; + case 6: + if (!(flags & 0x02)) { + prg_bank_a = V; + } + break; + case 7: + if (!(flags & 0x02)) { + prg_bank_b = V; + } + break; + } + break; + case 2: /* $A000-$BFFE, even (mirroring) */ + if (!(flags & 0x04)) { + mirroring = V & 0x01; + } + break; + case 3: /* RAM protect... no */ + break; + case 4: /* $C000-$DFFE, even (IRQ latch) */ + mmc3_irq_latch = V; + break; + case 5: /* $C001-$DFFF, odd */ + mmc3_irq_reload = 1; + break; + case 6: /* $E000-$FFFE, even */ + X6502_IRQEnd(FCEU_IQEXT); + mmc3_irq_enabled = 0; + break; + case 7: /* $E001-$FFFF, odd */ + if (!(flags & 0x04)) { + mmc3_irq_enabled = 1; + } + break; + } + } + + /* Mapper #112 */ + if (mapper == 21) { + switch (A & 0xE000) { + case 0x8000: + mapper112_internal = (mapper112_internal & 0xF8) | (V & 0x07); + break; + case 0xA000: + switch (mapper112_internal & 0x07) { + case 0: + prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); + break; + case 1: + prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); + break; + case 2: + chr_bank_a = V; + break; + case 3: + chr_bank_c = V; + break; + case 4: + chr_bank_e = V; + break; + case 5: + chr_bank_f = V; + break; + case 6: + chr_bank_g = V; + break; + case 7: + chr_bank_h = V; + break; + } + break; + case 0xC000: + break; + case 0xE000: + mirroring = V & 0x01; + break; + } + } + + /* Mappers #33 + #48 - Taito */ + /* flag0=0 - #33, flag0=1 - #48 */ + if (mapper == 22) { + switch (((A & 0x6000) >> 11) | (A & 0x03)) { + case 0: /* $8000, PRG Reg 0 (8k @ $8000) */ + prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); + if (!(flags & 0x01)) { /* 33 */ + mirroring = (V >> 6) & 0x01; + } + break; + case 1: /* $8001, PRG Reg 1 (8k @ $A000) */ + prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); + break; + case 2: /* $8002, CHR Reg 0 (2k @ $0000) */ + chr_bank_a = V << 1; + break; + case 3: /* $8003, CHR Reg 1 (2k @ $0800) */ + chr_bank_c = V << 1; + break; + case 4: /* $A000, CHR Reg 2 (1k @ $1000) */ + chr_bank_e = V; + break; + case 5: /* $A001, CHR Reg 2 (1k @ $1400) */ + chr_bank_f = V; + break; + case 6: /* $A002, CHR Reg 2 (1k @ $1800) */ + chr_bank_g = V; + break; + case 7: /* $A003, CHR Reg 2 (1k @ $1C00) */ + chr_bank_h = V; + break; + case 12: /* $E000, mirroring, for mapper #48 */ + if (flags & 0x01) { /* 48 */ + mirroring = (V >> 6) & 0x01; + } + break; + case 8: /* $C000, IRQ latch */ + mmc3_irq_latch = V ^ 0xFF; + break; + case 9: /* $C001, IRQ reload */ + mmc3_irq_reload = 1; + break; + case 10: /* $C002, IRQ enable */ + mmc3_irq_enabled = 1; + break; + case 11: /* $C003, IRQ disable & ack */ + mmc3_irq_enabled = 0; + X6502_IRQEnd(FCEU_IQEXT); /* ack */ + break; + } + } + + /* Mapper #42 */ + if (mapper == 23) { + switch (((A & 0x4000) >> 12) | (A & 3)) { + case 0: /* $8000, CHR Reg (8k @ $8000) */ + chr_bank_a = (chr_bank_a & 0xE0) | ((V & 0x1F) << 3); + break; + case 4: /* $E000, PRG Reg (8k @ $6000) */ + prg_bank_6000 = (prg_bank_6000 & 0xF0) | (V & 0x0F); + break; + case 5: /* Mirroring */ + mirroring = (V >> 3) & 0x01; + break; + case 6: /* IRQ */ + mapper42_irq_enabled = (V & 0x02) >> 1; + if (!mapper42_irq_enabled) { + X6502_IRQEnd(FCEU_IQEXT); + mapper42_irq_value = 0; + } + break; + } + } + + /* Mapper #23 - VRC2/4 */ + /* + flag0 - switches A0 and A1 lines. 0=A0,A1 like VRC2b (mapper #23), 1=A1,A0 like VRC2a(#22), VRC2c(#25) + flag1 - divides CHR bank select by two (mapper #22, VRC2a) + */ + if (mapper == 24) { + uint8 vrc_2b_hi = 0; + uint8 vrc_2b_low = 0; + uint8 vrc_2b_addr = 0; + + if (vrc24_compatibility) { + /* Compatibility code - for rom variants using the older firmware */ + vrc_2b_hi = ((A >> 1) & 0x01) | ((A >> 3) & 0x01) | ((A >> 5) & 0x01) | ((A >> 7) & 0x01); + vrc_2b_low = (A & 0x01) | ((A >> 2) & 0x01) | ((A >> 4) & 0x01) | ((A >> 6) & 0x01); + vrc_2b_addr = + (((flags & 0x01) ? vrc_2b_low : vrc_2b_hi) << 1) | + ((flags & 0x01) ? vrc_2b_hi : vrc_2b_low); + } else { + /* Updated code, not compatible with earlier VRC24 cart variants */ + switch (flags & 0x05) { + case 0: + vrc_2b_hi = (((A >> 7) & 0x01) | ((A >> 2) & 0x01)); /* mapper #21 */ + vrc_2b_low = (((A >> 6) & 0x01) | ((A >> 1) & 0x01)); /* mapper #21 */ + break; + case 1: + vrc_2b_hi = (A & 0x01); /* mapper #22 */ + vrc_2b_low = ((A >> 1) & 0x01); /* mapper #22 */ + break; + case 4: + vrc_2b_hi = (((A >> 5) & 0x01) | ((A >> 3) & 0x01) | ((A >> 1) & 0x01)); /* mapper #23 */ + vrc_2b_low = (((A >> 4) & 0x01) | ((A >> 2) & 0x01) | (A & 0x01)); /* mapper #23 */ + break; + default: + vrc_2b_hi = (((A >> 2) & 0x01) | (A & 0x01)); /* mapper #25 */ + vrc_2b_low = (((A >> 3) & 0x01) | ((A >> 1) & 0x01)); /* mapper #25 */ + break; + } + vrc_2b_addr = (vrc_2b_hi << 1) | vrc_2b_low; + } + + switch (((A >> 10) & 0x1C) | vrc_2b_addr) { + case 0: /* $8000-$8003, PRG0 */ + case 1: + case 2: + case 3: + prg_bank_a = (prg_bank_a & 0xE0) | (V & 0x1F); + break; + case 4: /* $9000-$9001, mirroring */ + case 5: + /* VRC2 - using games are usually well - behaved and only write 0 or 1 to this register, */ + /* but Wai Wai World in one instance writes $FF instead */ + if (V != 0xFF) { + mirroring = V & 0x03; + } + break; + case 6: /* $9002-$9004, PRG swap */ + case 7: + prg_mode = (prg_mode & 0xFE) | ((V >> 1) & 0x01); + break; + case 8: /* $A000-$A003, PRG1 */ + case 9: + case 10: + case 11: + prg_bank_b = (prg_bank_b & 0xE0) | (V & 0x1F); + break; + case 12: /* $B000, CHR0 low */ + chr_bank_a = (chr_bank_a & 0xF0) | (V & 0x0F); + break; + case 13: /* $B001, CHR0 hi */ + chr_bank_a = (chr_bank_a & 0x0F) | ((V & 0x0F) << 4); + break; + case 14: /* $B002, CHR1 low */ + chr_bank_b = (chr_bank_b & 0xF0) | (V & 0x0F); + break; + case 15: /* $B003, CHR1 hi */ + chr_bank_b = (chr_bank_b & 0x0F) | ((V & 0x0F) << 4); + break; + case 16: /* $C000, CHR2 low */ + chr_bank_c = (chr_bank_c & 0xF0) | (V & 0x0F); + break; + case 17: /* $C001, CHR2 hi */ + chr_bank_c = (chr_bank_c & 0x0F) | ((V & 0x0F) << 4); + break; + case 18: /* $C002, CHR3 low */ + chr_bank_d = (chr_bank_d & 0xF0) | (V & 0x0F); + break; + case 19: /* $C003, CHR3 hi */ + chr_bank_d = (chr_bank_d & 0x0F) | ((V & 0x0F) << 4); + break; + case 20: /* $D000, CHR4 low */ + chr_bank_e = (chr_bank_e & 0xF0) | (V & 0x0F); + break; + case 21: /* $D001, CHR4 hi */ + chr_bank_e = (chr_bank_e & 0x0F) | ((V & 0x0F) << 4); + break; + case 22: /* $D002, CHR5 low */ + chr_bank_f = (chr_bank_f & 0xF0) | (V & 0x0F); + break; + case 23: /* $D003, CHR5 hi */ + chr_bank_f = (chr_bank_f & 0x0F) | ((V & 0x0F) << 4); + break; + case 24: /* $E000, CHR6 low */ + chr_bank_g = (chr_bank_g & 0xF0) | (V & 0x0F); + break; + case 25: /* $E001, CHR6 hi */ + chr_bank_g = (chr_bank_g & 0x0F) | ((V & 0x0F) << 4); + break; + case 26: /* $E002, CHR7 low */ + chr_bank_h = (chr_bank_h & 0xF0) | (V & 0x0F); + break; + case 27: /* $E003, CHR7 hi */ + chr_bank_h = (chr_bank_h & 0x0F) | ((V & 0x0F) << 4); + break; + } + if ((A & 0x7000) == 0x7000) { + switch (vrc_2b_addr) { + case 0: /* IRQ latch low */ + vrc4_irq_latch = (vrc4_irq_latch & 0xF0) | (V & 0x0F); + break; + case 1: /* IRQ latch hi */ + vrc4_irq_latch = (vrc4_irq_latch & 0x0F) | ((V & 0x0F) << 4); + break; + case 2: /* IRQ control */ + X6502_IRQEnd(FCEU_IQEXT); /* ack */ + vrc4_irq_control = (vrc4_irq_control & 0xF8) | (V & 0x07); /* mode, enabled, enabled after ack */ + if (vrc4_irq_control & 0x02) { /* if E is set */ + vrc4_irq_prescaler_counter = 0; /* reset prescaler */ + vrc4_irq_prescaler = 0; + vrc4_irq_value = vrc4_irq_latch; /* reload with latch */ + } + break; + case 3: /* IRQ ack */ + X6502_IRQEnd(FCEU_IQEXT); + vrc4_irq_control = (vrc4_irq_control & 0xFD) | (vrc4_irq_control & 0x01) << 1; + break; + } + } + } + + /* Mapper #69 - Sunsoft FME-7 */ + if (mapper == 25) { + uint8 reg = (A & 0x6000) >> 13; + if (reg == 0) { + mapper69_internal = (mapper69_internal & 0xF0) | (V & 0x0F); + } + if (reg == 1) { + switch (mapper69_internal & 0x0F) { + case 0: /* CHR0 */ + chr_bank_a = V; + break; + case 1: /* CHR1 */ + chr_bank_b = V; + break; + case 2: /* CHR2 */ + chr_bank_c = V; + break; + case 3: /* CHR3 */ + chr_bank_d = V; + break; + case 4: /* CHR4 */ + chr_bank_e = V; + break; + case 5: /* CHR5 */ + chr_bank_f = V; + break; + case 6: /* CHR6 */ + chr_bank_g = V; + break; + case 7: /* CHR7 */ + chr_bank_h = V; + break; + case 8: /* PRG0 */ + sram_enabled = (V >> 7) & 0x01; + map_rom_on_6000 = ((V >> 6) & 0x01) ^ 0x01; + prg_bank_6000 = V & 0x3F; + break; + case 9: /* PRG1 */ + prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); + break; + case 10: /* PRG2 */ + prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); + break; + case 11: /* PRG3 */ + prg_bank_c = (prg_bank_c & 0xC0) | (V & 0x3F); + break; + case 12: /* mirroring */ + mirroring = V & 0x03; + break; + case 13: + X6502_IRQEnd(FCEU_IQEXT); /* ack */ + mapper69_counter_enabled = V >> 7; + mapper69_irq_enabled = V & 0x01; + break; + case 14: /* IRQ low */ + mapper69_irq_value = (mapper69_irq_value & 0xFF00) | V; + break; + case 15: /* IRQ high */ + mapper69_irq_value = (mapper69_irq_value & 0x00FF) | (V << 8); + break; + } + } + } + + /* Mapper #32 - Irem's G-101 */ + if (mapper == 26) { + switch (A & 0xF000) { + case 0x8000: + prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); + break; + case 0x9000: + prg_mode = (prg_mode & 0x06) | ((V >> 1) & 0x01); + mirroring = V & 0x01; + break; + case 0xA000: + prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); + break; + case 0xB000: + switch (A & 0x07) { + case 0: + chr_bank_a = V; + break; + case 1: + chr_bank_b = V; + break; + case 2: + chr_bank_c = V; + break; + case 3: + chr_bank_d = V; + break; + case 4: + chr_bank_e = V; + break; + case 5: + chr_bank_f = V; + break; + case 6: + chr_bank_g = V; + break; + case 7: + chr_bank_h = V; + break; + } + break; + } + } + + /* Mapper #36 is assigned to TXC's PCB 01-22000-400 */ + if (mapper == 29) { + if ((A & 0x7FFE) == 0x7FFE) { + prg_bank_a = (prg_bank_a & 0xC3) | ((V & 0xF0) >> 2); + chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x0F) << 3); + } + } + + /* Mapper #70 */ + if (mapper == 30) { + prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0xF0) >> 3); + chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x0F) << 3); + } + + /* Mapper #75 - VRC1 */ + if (mapper == 34) { + switch (A & 0xF000) { + case 0x8000: + prg_bank_a = (prg_bank_a & 0xF0) | (V & 0x0F); + break; + case 0x9000: + mirroring = V & 1; + chr_bank_a = (chr_bank_a & 0xBF) | ((V & 0x02) << 5); + chr_bank_e = (chr_bank_a & 0xBF) | ((V & 0x04) << 4); + break; + case 0xA000: /* $A000-$AFFF */ + prg_bank_b = (prg_bank_b & 0xF0) | (V & 0x0F); + break; + case 0xC000: + prg_bank_c = (prg_bank_c & 0xF0) | (V & 0x0F); + break; + case 0xE000: + chr_bank_a = (chr_bank_a & 0xC3) | ((V & 0x0F) << 2); + break; + case 0xF000: + chr_bank_e = (chr_bank_e & 0xC3) | ((V & 0x0F) << 2); + break; + } + } + + /* Mapper #83 - Cony/Yoko */ + /* TODO: Check for flags 4 needed? */ + if (mapper == 35) { + switch (A & 0x8300) { + case 0x8000: + prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0x0F) << 1); + break; + case 0x8100: /* $81xx */ + mirroring = V & 0x03; + prg_mode = (prg_mode & 0x03) | ((V >> 2) & 0x04); + map_rom_on_6000 = (V & 0x20) >> 5; + mapper83_irq_enabled_latch = (V & 0x80) >> 7; + break; + case 0x8200: + if (!(A & 0x01)) { + X6502_IRQEnd(FCEU_IQEXT); + mapper83_irq_counter = (mapper83_irq_counter & 0xFF00) | V; + } else { + mapper83_irq_enabled = mapper83_irq_enabled_latch; + mapper83_irq_counter = (mapper83_irq_counter & 0x00FF) | (V << 8); + } + break; + case 0x8300: + if (!(A & 0x10)) { + switch (A & 0x03) { + case 0: + prg_bank_a = V; + break; + case 1: + prg_bank_b = V; + break; + case 2: + prg_bank_b = V; + break; + case 3: + /* TODO: Verify this */ + prg_bank_6000 = V; + break; + } + } else { + if (!(flags & 0x04)) { + switch (A & 0x07) { + case 0: + chr_bank_a = V; + break; + case 1: + chr_bank_b = V; + break; + case 2: + chr_bank_c = V; + break; + case 3: + chr_bank_d = V; + break; + case 4: + chr_bank_e = V; + break; + case 5: + chr_bank_f = V; + break; + case 6: + chr_bank_g = V; + break; + case 7: + chr_bank_h = V; + break; + } + } else { + switch (A & 0x07) { + /* TODO: verify CHR mask */ + case 0: + chr_bank_a = (chr_bank_a & 0x01) | (V << 1); + break; + case 1: + chr_bank_c = (chr_bank_c & 0x01) | (V << 1); + break; + case 6: + chr_bank_e = (chr_bank_e & 0x01) | (V << 1); + break; + case 7: + chr_bank_g = (chr_bank_g & 0x01) | (V << 1); + break; + } + } + } + break; + } + } + + /* Mapper #67 - Sunsoft-3 */ + if (mapper == 36) { + if (A & 0x800) { + switch (A & 0xF800) { + case 0x8800: + chr_bank_a = (chr_bank_a & 0x81) | ((V & 0x3F) << 1); + break; + case 0x9800: + chr_bank_c = (chr_bank_c & 0x81) | ((V & 0x3F) << 1); + break; + case 0xA800: + chr_bank_e = (chr_bank_e & 0x81) | ((V & 0x3F) << 1); + break; + case 0xB800: + chr_bank_g = (chr_bank_g & 0x81) | ((V & 0x3F) << 1); + break; + case 0xC800: + mapper67_irq_latch = ~mapper67_irq_latch; + if (mapper67_irq_latch) { + mapper67_irq_counter = (mapper67_irq_counter & 0x00FF) | (V << 8); + } else { + mapper67_irq_counter = (mapper67_irq_counter & 0xFF00) | V; + } + break; + case 0xD800: + mapper67_irq_latch = 0; + mapper67_irq_enabled = (V & 0x10) >> 4; + break; + case 0xE800: + mirroring = V & 0x03; + break; + case 0xF800: + prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0x0F) << 1); + break; + } + } else { + /* Interrupt Acknowledge ($8000) */ + X6502_IRQEnd(FCEU_IQEXT); + } + } + + /* Mapper #89 - Sunsoft-2 chip on the Sunsoft-3 board */ + if (mapper == 37) { + prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x70) >> 3); + chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x80) >> 1) | ((V & 0x07) << 3); + mirroring = 2 | ((V & 0x08) >> 3); + } + } + + Sync(); +} + +static DECLFR(M342Read) { + if ((mapper == 0) && (A >= 0x5000) && (A < 0x6000)) + return 0; + + /* Mapper #163 */ + if (mapper == 6) { + if ((A & 0x7700) == 0x5100) { + return mapper163_r2 | mapper163_r0 | mapper163_r1 | ~mapper163_r3; + } + if ((A & 0x7700) == 0x5500) { + return (mapper163_r5 & 1) ? mapper163_r2 : mapper163_r1; + } + } + + /* Mapper #90 - JY */ + if (mapper == 13) { + if ((A == 0x5800)) { + return (mul1 * mul2) & 0xFF; + } + if ((A == 0x5801)) { + return ((mul1 * mul2) >> 8) & 0xFF; + } + } + + /* MMC5 */ + if (mapper == 15) { + if (A == 0x5204) { + uint8 ppuon = (PPU[1] & 0x18); + uint8 ret = (mmc5_irq_out << 7) | (!ppuon || ((scanline + 1) >= 241) ? 0 : 0x40); + X6502_IRQEnd(FCEU_IQEXT); + mmc5_irq_out = 0; + return ret; + } + } + + /* Mapper #36 is assigned to TXC's PCB 01-22000-400 */ + if ((mapper == 29) && ((A & 0xE100) == 0x4100)) { + return (prg_bank_a & 0x0C) << 2; + } + + /* Mapper #83 - Cony/Yoko */ + if ((mapper == 35) && ((A & 0x7000) == 0x5000)) { + return (flags & 3); + } + + if (sram_enabled && !map_rom_on_6000 && (A >= 0x6000) && (A < 0x8000)) { + return CartBR(A); /* SRAM */ + } + + if (map_rom_on_6000 && (A >= 0x6000) && (A < 0x8000)) { + return CartBR(A); /* PRG */ + } + + return CPU_OPENBUS; /* Open bus */ +} + +static void M342HBHook(void) { + /* for MMC3 and MMC3-based */ + if (mmc3_irq_reload || !mmc3_irq_counter) { + mmc3_irq_counter = mmc3_irq_latch; + mmc3_irq_reload = 0; + } else { + mmc3_irq_counter--; + } + if (!mmc3_irq_counter && mmc3_irq_enabled) { + X6502_IRQBegin(FCEU_IQEXT); + } + + /* for MMC5 */ + if (mmc5_irq_line == scanline + 1) { + if (mmc5_irq_enabled) { + X6502_IRQBegin(FCEU_IQEXT); + mmc5_irq_out = 1; + } + } + + /* for mapper #163 */ + if (scanline == 239) { + mapper163_latch = 0; + SyncCHR(); + } else if (scanline == 127) { + mapper163_latch = 1; + SyncCHR(); + } +} + +static void M342CPUHook(int a) { + while (a--) { + /* Mapper #23 - VRC4 */ + if (vrc4_irq_control & 0x02) { + vrc4_irq_prescaler++; /* count prescaler */ + if ((!(vrc4_irq_prescaler_counter & 0x02) && vrc4_irq_prescaler == 114) || + ((vrc4_irq_prescaler_counter & 0x02) && vrc4_irq_prescaler == 113)) { + vrc4_irq_prescaler = 0; + vrc4_irq_prescaler_counter++; + if (vrc4_irq_prescaler_counter == 3) { + vrc4_irq_prescaler_counter = 0; + } + vrc4_irq_value++; + if (vrc4_irq_value == 0) { /* if (carry) */ + X6502_IRQBegin(FCEU_IQEXT); + vrc4_irq_value = vrc4_irq_latch; + } + } + } + + /* Mapper #73 - VRC3 */ + if (vrc3_irq_control & 0x02) { + if (vrc3_irq_control & 0x04) { /* 8-bit mode */ + vrc3_irq_value = (vrc3_irq_value & 0xFF00) | ((vrc3_irq_value + 1) & 0xFF); + if ((vrc3_irq_value & 0xFF) == 0) { + X6502_IRQBegin(FCEU_IQEXT); + vrc3_irq_value = (vrc3_irq_value & 0xFF00) | (vrc3_irq_latch & 0xFF); + } + } else { /* 16-bit */ + vrc3_irq_value += 1; + if (vrc3_irq_value == 0) { + X6502_IRQBegin(FCEU_IQEXT); + vrc3_irq_value = vrc3_irq_latch; + } + } + } + + /* Mapper #69 - Sunsoft FME-7 */ + if (mapper69_counter_enabled) { + mapper69_irq_value--; + if (mapper69_irq_value == 0xFFFF) { + X6502_IRQBegin(FCEU_IQEXT); + } + } + + /* Mapper #18 */ + if (mapper18_irq_control & 0x01) { + uint8 carry; + carry = (mapper18_irq_value & 0x0F) - 1; + mapper18_irq_value = (mapper18_irq_value & 0xFFF0) | (carry & 0x0F); + carry = (carry >> 4) & 0x01; + if (!(mapper18_irq_control & 0x08)) { + carry = ((mapper18_irq_value >> 4) & 0x0F) - carry; + mapper18_irq_value = (mapper18_irq_value & 0xFF0F) | ((carry & 0x0F) << 4); + carry = (carry >> 4) & 0x01; + } + if (!(mapper18_irq_control & 0x0C)) { + carry = ((mapper18_irq_value >> 8) & 0x0F) - carry; + mapper18_irq_value = (mapper18_irq_value & 0xF0FF) | ((carry & 0x0F) << 8); + carry = (carry >> 4) & 0x01; + } + if (!(mapper18_irq_control & 0x0E)) { + carry = ((mapper18_irq_value >> 12) & 0x0F) - carry; + mapper18_irq_value = (mapper18_irq_value & 0x0FFF) | ((carry & 0x0F) << 12); + carry = (carry >> 4) & 0x01; + } + if (carry) { + X6502_IRQBegin(FCEU_IQEXT); + } + } + + /* Mapper #65 - Irem's H3001 */ + if (mapper65_irq_enabled) { + if (mapper65_irq_value != 0) { + mapper65_irq_value--; + if (!mapper65_irq_value) { + X6502_IRQBegin(FCEU_IQEXT); + } + } + } + + /* Mapper #42 */ + if (mapper42_irq_enabled) { + mapper42_irq_value++; + if (mapper42_irq_value >> 15) { + mapper42_irq_value = 0; + } + if (((mapper42_irq_value >> 13) & 0x03) == 3) { + X6502_IRQBegin(FCEU_IQEXT); + } else { + X6502_IRQEnd(FCEU_IQEXT); + } + } + + /* Mapper #83 - Cony/Yoko */ + if (mapper83_irq_enabled) { + if (mapper83_irq_counter == 0) { + X6502_IRQBegin(FCEU_IQEXT); + } + mapper83_irq_counter--; + } + + /* Mapper #67 - Sunsoft-3 */ + if (mapper67_irq_enabled) { + mapper67_irq_counter--; + if (mapper67_irq_counter == 0xFFFF) { + X6502_IRQBegin(FCEU_IQEXT); /* fire IRQ */ + mapper67_irq_enabled = 0; /* disable IRQ */ + } + } + } +} + +static void M342PPUHook(uint32 A) { + /* For TxROM */ + if ((mapper == 20) && (flags & 0x01)) { + setmirror(MI_0 + (TKSMIR[(A & 0x1FFF) >> 10] >> 7)); + } + + /* Mapper #9 and #10 - MMC2 and MMC4 */ + if (mapper == 17) { + if ((A >> 4) == 0xFD) { + ppu_latch0 = 0; + SyncCHR(); + } + if ((A >> 4) == 0xFE) { + ppu_latch0 = 1; + SyncCHR(); + } + if ((A >> 4) == 0x1FD) { + ppu_latch1 = 0; + SyncCHR(); + } + if ((A >> 4) == 0x1FE) { + ppu_latch1 = 1; + SyncCHR(); + } + } +} + +static void M342Reset(void) { + sram_enabled = 0; + sram_page = 0; + can_write_chr = 0; + map_rom_on_6000 = 0; + flags = 0; + mapper = 0; + can_write_flash = 0; + mirroring = 0; + four_screen = 0; + lockout = 0; + prg_base = 0; + prg_mask = 0xF8; + prg_mode = 0; + prg_bank_6000 = 0; + prg_bank_a = 0; + prg_bank_b = 1; + prg_bank_c = ~1; + prg_bank_d = ~0; + chr_mask = 0; + chr_mode = 0; + chr_bank_a = 0; + chr_bank_b = 1; + chr_bank_c = 2; + chr_bank_d = 3; + chr_bank_e = 4; + chr_bank_f = 5; + chr_bank_g = 6; + chr_bank_h = 7; + ppu_latch0 = 0; + ppu_latch1 = 0; + lreset = 0; + mmc1_load_register = 0; + mmc3_internal = 0; + mapper69_internal = 0; + mapper112_internal = 0; + mapper163_latch = 0; + mapper163_r0 = 0; + mapper163_r1 = 0; + mapper163_r2 = 0; + mapper163_r3 = 0; + mapper163_r4 = 0; + mapper163_r5 = 0; + mul1 = 0; + mul2 = 0; + mmc3_irq_enabled = 0; + mmc3_irq_latch = 0; + mmc3_irq_counter = 0; + mmc3_irq_reload = 0; + mmc5_irq_enabled = 0; + mmc5_irq_line = 0; + mmc5_irq_out = 0; + mapper18_irq_value = 0; + mapper18_irq_control = 0; + mapper18_irq_latch = 0; + mapper65_irq_enabled = 0; + mapper65_irq_value = 0; + mapper65_irq_latch = 0; + mapper69_irq_enabled = 0; + mapper69_counter_enabled = 0; + mapper69_irq_value = 0; + vrc4_irq_value = 0; + vrc4_irq_control = 0; + vrc4_irq_latch = 0; + vrc4_irq_prescaler = 0; + vrc4_irq_prescaler_counter = 0; + vrc3_irq_value = 0; + vrc3_irq_control = 0; + vrc3_irq_latch = 0; + mapper42_irq_enabled = 0; + mapper42_irq_value = 0; + mapper90_xor = 0; + flash_state = 0; + cfi_mode = 0; + show_error_log = 0; + Sync(); +} + +static void M342Power(void) { + FCEU_CheatAddRAM(32, 0x6000, WRAM); + SetReadHandler(0x4020, 0x7FFF, M342Read); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0xFFFF, M342Write); + M342Reset(); +} + +static void M342Close(void) { + if (SAVE_FLASH) { + FCEU_gfree(SAVE_FLASH); + } + + if (CFI) { + FCEU_gfree(CFI); + } + + SAVE_FLASH = CFI = NULL; +} + +static void StateRestore(int version) { + Sync(); + lreset = 0; +} + +#define ExState(var, varname) AddExState(&var, sizeof(var), 0, varname) + +void Mapper342_Init(CartInfo *info) { + int i; + + info->Power = M342Power; + info->Reset = M342Reset; + info->Close = M342Close; + GameStateRestore = StateRestore; + GameHBIRQHook = M342HBHook; + MapIRQHook = M342CPUHook; + PPU_hook = M342PPUHook; + + CHR_SIZE = info->CHRRamSize ? info->CHRRamSize : (512 * 1024) /* non-iNES2 or UNIF */; + + WRAMSIZE = (info->PRGRamSize + info->PRGRamSaveSize) ? (info->PRGRamSize + info->PRGRamSaveSize) : (32 * 1024); + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + memset(WRAM, 0, WRAMSIZE); + SetupCartPRGMapping(WRAM_CHIP, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } + + if (info->battery) { + SAVE_FLASH = (uint8 *)FCEU_gmalloc(SAVE_FLASH_SIZE); + SetupCartPRGMapping(FLASH_CHIP, SAVE_FLASH, SAVE_FLASH_SIZE, 1); + info->SaveGame[1] = SAVE_FLASH; + info->SaveGameLen[1] = SAVE_FLASH_SIZE; + } + + CFI = (uint8 *)FCEU_gmalloc(sizeof(cfi_data) * 2); + for (i = 0; i < (int)sizeof(cfi_data); i++) { + CFI[i * 2] = CFI[i * 2 + 1] = cfi_data[i]; + } + SetupCartPRGMapping(CFI_CHIP, CFI, sizeof(cfi_data) * 2, 0); + + switch (info->PRGCRC32) { + /* Earlier version of roms using VRC24 were using incorrect flags + * which are now incompatible with later updates of Coolgirl firmware causing + * graphics to be broken. This enables compatibily code to handle early roms while + * keeping the latest and updated VRC24 handling intact for newer roms when they become available. + */ + case 0xCF0FE3F3: /* 0b89251f6d63d49586ee3bbe41914ab7.unif */ + case 0x62BEFE75: /* 320 ¿úÓ äÑ¡ñ¿.unf */ + case 0xBF617289: /* d61e011f86b13bed9a22d3c56326e689.unif */ + case 0x3A70CB07: /* (MMK-02A-01) Gradius 10-in-1.nes */ + case 0x5352A128: /* (MMK-02D-00) Coolgirl 11-in-1.nes */ + case 0x861F89A0: /* (MMK-02E-00) Coolgirl 7-in-1.nes */ + case 0xA25CD951: /* (MMK-02F-00) Shooting Game 16-in-1.nes */ + case 0xE368F1F6: /* (MMK-033-00) Game 150-in-1.nes */ + case 0x49EE3B04: /* (YG-6014) Super Captain Tsubasa 2 Hack 6-in-1.nes (not using mapper code 24 but whatever) */ + case 0x7B85868B: /* (Yhc-4006-00) Super Konami 80-in-1.nes */ + case 0x2F0D22CD: /* (Yhc-BS-8165-01) Super Plane Game 11-in-1.nes */ + case 0x242B9218: /* (Yhc-CK-124-07) Super Konami 3-in-1.nes */ + vrc24_compatibility = 1; + break; + default: + vrc24_compatibility = 0; + break; + } + + ExState(sram_enabled, "SREN"); + ExState(sram_page, "SRPG"); + ExState(can_write_chr, "SRWR"); + ExState(map_rom_on_6000, "MR6K"); + ExState(flags, "FLGS"); + ExState(mapper, "MPPR"); + ExState(can_write_flash, "FLWR"); + ExState(mirroring, "MIRR"); + ExState(four_screen, "4SCR"); + ExState(lockout, "LOCK"); + + ExState(prg_base, "PBAS"); + ExState(prg_mask, "PMSK"); + ExState(prg_mode, "PMOD"); + ExState(prg_bank_6000, "P6BN"); + ExState(prg_bank_a, "PABN"); + ExState(prg_bank_b, "PBBN"); + ExState(prg_bank_c, "PCBN"); + ExState(prg_bank_d, "PDBN"); + ExState(prg_bank_6000_mapped, "P6BM"); + ExState(prg_bank_a_mapped, "PABM"); + ExState(prg_bank_b_mapped, "PBBM"); + ExState(prg_bank_c_mapped, "PCBM"); + ExState(prg_bank_d_mapped, "PDBM"); + + ExState(chr_mask, "CMSK"); + ExState(chr_mode, "CMOD"); + ExState(chr_bank_a, "CABN"); + ExState(chr_bank_b, "CBBN"); + ExState(chr_bank_c, "CCBN"); + ExState(chr_bank_d, "CDBN"); + ExState(chr_bank_e, "CEBN"); + ExState(chr_bank_f, "CFBN"); + ExState(chr_bank_g, "CGBN"); + ExState(chr_bank_h, "CHBN"); + + ExState(ppu_latch0, "PPU0"); + ExState(ppu_latch1, "PPU1"); + + ExState(lreset, "LRST"); + ExState(mmc1_load_register, "M01R"); + + ExState(mmc3_internal, "M01I"); + + ExState(mapper69_internal, "M69I"); + ExState(mapper112_internal, "112I"); + ExState(mapper163_latch, "163L"); + ExState(mapper163_r0, "1630"); + ExState(mapper163_r1, "1631"); + ExState(mapper163_r2, "1632"); + ExState(mapper163_r3, "1633"); + ExState(mapper163_r4, "1634"); + ExState(mapper163_r5, "1635"); + + ExState(mul1, "MUL1"); + ExState(mul2, "MUL2"); + + ExState(mmc3_irq_enabled, "M4IE"); + ExState(mmc3_irq_latch, "M4IL"); + ExState(mmc3_irq_counter, "M4IC"); + ExState(mmc3_irq_reload, "M4IR"); + + ExState(mmc5_irq_enabled, "M5IE"); + ExState(mmc5_irq_line, "M5IL"); + ExState(mmc5_irq_out, "M5IO"); + + ExState(mapper18_irq_value, "18IV"); + ExState(mapper18_irq_control, "18IC"); + ExState(mapper18_irq_latch, "18IL"); + + ExState(mapper65_irq_enabled, "65IE"); + ExState(mapper65_irq_value, "65IV"); + ExState(mapper65_irq_latch, "65IL"); + + ExState(mapper69_irq_enabled, "69IE"); + ExState(mapper69_counter_enabled, "69CE"); + ExState(mapper69_irq_value, "69IV"); + + ExState(vrc4_irq_value, "V4IV"); + ExState(vrc4_irq_control, "V4IC"); + ExState(vrc4_irq_latch, "V4IL"); + ExState(vrc4_irq_prescaler, "V4PP"); + ExState(vrc4_irq_prescaler_counter, "V4PC"); + + ExState(vrc3_irq_value, "V3IV"); + ExState(vrc3_irq_control, "V3IC"); + ExState(vrc3_irq_latch, "V3IL"); + + ExState(mapper42_irq_enabled, "42IE"); + ExState(mapper42_irq_value, "42IV"); + + ExState(mapper83_irq_enabled_latch, "M83L"); + ExState(mapper83_irq_enabled, "M83I"); + ExState(mapper83_irq_counter, "M83C"); + + ExState(mapper90_xor, "90XR"); + + ExState(mapper67_irq_enabled, "67IE"); + ExState(mapper67_irq_latch, "67IL"); + ExState(mapper67_irq_counter, "67IC"); + + ExState(flash_state, "FLST"); + ExState(flash_buffer_a, "FLBA"); + ExState(flash_buffer_v, "FLBV"); + + ExState(cfi_mode, "CFIM"); + + AddExState(ntaramExtra, 2048, 0, "ExRM"); +} diff --git a/src/mappers/mapper343.c b/src/mappers/mapper343.c new file mode 100644 index 000000000..54f56fc9d --- /dev/null +++ b/src/mappers/mapper343.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 343 + * BMC-RESETNROM-XIN1 + * - Sheng Tian 2-in-1(Unl,ResetBase)[p1] - Kung Fu (Spartan X), Super Mario Bros (alt) + * - Sheng Tian 2-in-1(Unl,ResetBase)[p2] - B-Wings, Twin-bee + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (iNESCart.submapper == 1) { + setprg32(0x8000, latch.data); + } else { + setprg16(0x8000, latch.data); + setprg16(0xC000, latch.data); + } + setchr8(latch.data); + setmirror((latch.data >> 7) & 0x01); +} + +static DECLFW(M343Write) { + Latch_Write(A, V ^ 0xFF); +} + +static void M343Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M343Write); +} + +void Mapper343_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M343Power; +} diff --git a/src/mappers/mapper344.c b/src/mappers/mapper344.c new file mode 100644 index 000000000..385afd70e --- /dev/null +++ b/src/mappers/mapper344.c @@ -0,0 +1,78 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 344 + * BMC-GN-26 + * Kuai Da Jin Ka Zhong Ji Tiao Zhan 3-in-1 (3-in-1,6-in-1,Unl) + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static uint8 prg_bank_order[2][4] = { + { 0, 1, 2, 3 }, /* normal bank order */ + { 0, 3, 1, 2 } /* wrong bank order, added for compatibility */ +}; + +static void M344CW(uint16 A, uint16 V) { + uint16 mask = (reg & 0x02) ? 0x7F : 0xFF; + uint16 base = (reg & 0x03) << 7; + + setchr1(A, base | (V & mask)); +} + +static void M344PW(uint16 A, uint16 V) { + uint8 base = prg_bank_order[(iNESCart.PRGCRC32 == 0xAB2ACA46)][reg & 0x03]; + + if (reg & 0x04) { + setprg32(0x8000, (base << 2) | ((mmc3.reg[6] & 0x0F) >> 2)); + } else { + setprg8(A, (base << 4) | (V & 0x0F)); + } +} + +static DECLFW(M344Write) { + if (MMC3_WramIsWritable()) { + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M344Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M344Power(void) { + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M344Write); +} + +void Mapper344_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M344PW; + MMC3_cwrap = M344CW; + info->Power = M344Power; + info->Reset = M344Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper345.c b/src/mappers/mapper345.c new file mode 100644 index 000000000..6807b82a0 --- /dev/null +++ b/src/mappers/mapper345.c @@ -0,0 +1,76 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 345 + * BMC-L6IN1 + * New Star 6-in-1 Game Cartridge + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_345 + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M345PW(uint16 A, uint16 V) { + uint8 base = reg >> 6; + + if (reg & 0x0C) { + setprg8(A, (base << 4) | (V & 0x0F)); + } else { + setprg32(0x8000, (base << 2) | (reg & 0x03)); + } +} + +static void M345MIR(void) { + if (reg & 0x20) { + setmirror(MI_0 + ((reg & 0x10) >> 1)); + } else { + setmirror((mmc3.mirr & 0x01) ^ 0x01); + } +} + +static DECLFW(M345Write) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } +} + +static void M345Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M345Power(void) { + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M345Write); +} + +void Mapper345_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M345PW; + MMC3_FixMIR = M345MIR; + info->Power = M345Power; + info->Reset = M345Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper346.c b/src/mappers/mapper346.c new file mode 100644 index 000000000..22bbfcf8d --- /dev/null +++ b/src/mappers/mapper346.c @@ -0,0 +1,84 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 346 - Kaiser 7012 + * UNL-KS7012 + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, reg); + setchr8(0); +} + +static DECLFW(M346Write) { +/* FCEU_printf("bs %04x %02x\n",A,V); */ + switch (A) { + case 0xE0A0: reg = 0; Sync(); break; + case 0xEE36: reg = 1; Sync(); break; + } +} + +static void M346Power(void) { + reg = 1; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xE000, 0xEFFF, M346Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M346Reset(void) { + reg = 1; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M346Close(void) { +} + +void Mapper346_Init(CartInfo *info) { + info->Power = M346Power; + info->Reset = M346Reset; + info->Close = M346Close; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper347.c b/src/mappers/mapper347.c new file mode 100644 index 000000000..7b7cfdc61 --- /dev/null +++ b/src/mappers/mapper347.c @@ -0,0 +1,193 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 347 - Kaiser 7030 + * UNIF UNL-KS7030 + * FDS Conversion - Yume Koujou: Doki Doki Panic + * + * Logical bank layot 32 K BANK 0, 64K BANK 1, 32K ~0 hardwired, 8K is missing + * need redump from MASKROM! + * probably need refix mapper after hard dump + * + */ + +/* 2020-3-6 - update mirroring + * PRG-ROM Bank Select #1/Mirroring Select ($8000-$8FFF, write) + * A~FEDC BA98 7654 3210 + * ------------------- + * 1000 .... .... MBBB + * |+++- Select 4 KiB PRG-ROM bank at CPU $7000-$7FFF + * +---- Select nametable mirroring type + * 0: Vertical + * 1: Horizontal + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg[2]; +static void (*WSync)(void); + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +/* Legacy bank order */ + +/* 6000 - 6BFF - RAM + * 6C00 - 6FFF - BANK 1K REG1 + * 7000 - 7FFF - BANK 4K REG0 + * 8000 - B7FF - PRG + * B800 - BFFF - RAM + * C000 - CBFF - BANK 3K + * CC00 - D7FF - RAM + * D800 - FFFF - PRG + */ + +static void M347Sync2(void) { + setchr8(0); + setprg32(0x8000, ~0); + setprg4(0xb800, reg[0] & 0x07); + setprg4(0xc800, reg[1] + 8); + setmirror(((reg[0] >> 3) & 0x01) ^ 0x01); +} + +static DECLFR(M347Read2) { + if ((A >= 0x6000) && (A <= 0x6BFF)) { + return WRAM[A - 0x6000]; + } else if ((A >= 0x6C00) && (A <= 0x6FFF)) { + return CartBR(0xC800 + (A - 0x6C00)); + } else if ((A >= 0x7000) && (A <= 0x7FFF)) { + return CartBR(0xB800 + (A - 0x7000)); + } else if ((A >= 0xB800) && (A <= 0xBFFF)) { + return WRAM[0x0C00 + (A - 0xB800)]; + } else if ((A >= 0xC000) && (A <= 0xCBFF)) { + return CartBR(0xCC00 + (A - 0xC000)); + } else if ((A >= 0xCC00) && (A <= 0xD7FF)) { + return WRAM[0x1400 + (A - 0xCC00)]; + } else if ((A >= 0x8000) && (A <= 0xB7FF)) { + return CartBR(A); + } else if (A >= 0xD800) { + return CartBR(A); + } + return CPU_OPENBUS; +} + +static DECLFW(M347Write2) { + if ((A >= 0x6000) && (A <= 0x6BFF)) { + WRAM[A - 0x6000] = V; + } else if ((A >= 0x6C00) && (A <= 0x6FFF)) { + CartBW(0xC800 + (A - 0x6C00), V); + } else if ((A >= 0x7000) && (A <= 0x7FFF)) { + CartBW(0xB800 + (A - 0x7000), V); + } else if ((A >= 0xB800) && (A <= 0xBFFF)) { + WRAM[0x0C00 + (A - 0xB800)] = V; + } else if ((A >= 0xC000) && (A <= 0xCBFF)) { + CartBW(0xCC00 + (A - 0xC000), V); + } else if ((A >= 0xCC00) && (A <= 0xD7FF)) { + WRAM[0x1400 + (A - 0xCC00)] = V; + } else if ((A >= 0x8000) && (A <= 0x8FFF)) { + reg[0] = A & 0x0F; + WSync(); + } else if ((A >= 0x9000) && (A <= 0x9FFF)) { + reg[1] = A & 0x0F; + WSync(); + } +} +/* end of legacy bank order handling */ + +static void Sync(void) { + setchr8(0); + setprg32(0x8000, ~0); + if (reg[0] & 8) + setmirror(MI_H); + else + setmirror(MI_V); +} + +static DECLFR(M347Read) { + if (A >= 0x6000 && A <= 0x6BFF) { + return WRAM[A - 0x6000 + 0x00000]; + } else if (A >= 0x6C00 && A <= 0x6FFF) { + return PRGptr[0][A - 0x6000 + 0x01000 * reg[1] + 0x00000]; + } else if (A >= 0x7000 && A <= 0x7FFF) { + return PRGptr[0][A - 0x7000 + 0x01000 * (reg[0] & 0x07) + 0x10000]; + } else if (A >= 0xB800 && A <= 0xBFFF) { + return WRAM[A - 0xB800 + 0x00C00]; + } else if (A >= 0xC000 && A <= 0xCBFF) { + return PRGptr[0][A - 0xC000 + 0x01000 * reg[1] + 0x00000]; + } else if (A >= 0xCC00 && A <= 0xD7FF) { + return WRAM[A - 0xCC00 + 0x01400]; + } else if (A >= 0x8000) { + return PRGptr[0][A - 0x8000 + 0x18000]; + } + return CPU_OPENBUS; +} + +static DECLFW(M347Write) { + if (A >= 0x6000 && A <= 0x6BFF) { + WRAM[A - 0x6000 + 0x0000] = V; + } else if (A >= 0xB800 && A <= 0xBFFF) { + WRAM[A - 0xB800 + 0x0C00] = V; + } else if (A >= 0xCC00 && A <= 0xD7FF) { + WRAM[A - 0xCC00 + 0x1400] = V; + } else if (A >= 0x8000 && A <= 0x8FFF) { + reg[0] = A & 15; + WSync(); + } else if (A >= 0x9000 && A <= 0x9FFF) { + reg[1] = A & 15; + WSync(); + } +} + +static void M347Power(void) { + FDSSound_Power(); + reg[0] = reg[1] = ~0; + + if (iNESCart.PRGCRC32 == 0xFA4DAC91) { + SetReadHandler(0x6000, 0xFFFF, M347Read2); + SetWriteHandler(0x6000, 0xFFFF, M347Write2); + WSync = M347Sync2; + } else { + SetReadHandler(0x6000, 0xFFFF, M347Read); + SetWriteHandler(0x6000, 0xFFFF, M347Write); + WSync = Sync; + } + WSync(); +} + +static void M347Close(void) { +} + +static void StateRestore(int version) { + WSync(); +} + +void Mapper347_Init(CartInfo *info) { + info->Power = M347Power; + info->Close = M347Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper348.c b/src/mappers/mapper348.c new file mode 100644 index 000000000..10b6883af --- /dev/null +++ b/src/mappers/mapper348.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2008 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 348 + * M-022 MMC3 based 830118C T-106 4M + 4M */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M348CW(uint16 A, uint16 V) { + uint16 mask = 0x7F; + uint16 base = (reg << 5) & 0x180; + + setchr1(A, base | (V & mask)); +} + +static void M348PW(uint16 A, uint16 V) { + uint8 mask = 0x0F; + uint8 base = (reg << 2) & 0x30; + + if ((reg & 0x0C) == 0x0C) { + setprg8(0x8000, base | ((mmc3.reg[6] & ~0x02) & mask)); + setprg8(0xA000, base | ((mmc3.reg[7] & ~0x02) & mask)); + setprg8(0xC000, base | ((mmc3.reg[6] | 0x02) & mask)); + setprg8(0xE000, base | ((mmc3.reg[7] | 0x02) & mask)); + } else { + setprg8(A, base | (V & mask)); + } +} + +static DECLFW(M348Write) { + if (MMC3_WramIsWritable()) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M348Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M348Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6800, 0x68FF, M348Write); +} + +void Mapper348_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M348PW; + MMC3_cwrap = M348CW; + info->Power = M348Power; + info->Reset = M348Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper349.c b/src/mappers/mapper349.c new file mode 100644 index 000000000..b3d07e6c1 --- /dev/null +++ b/src/mappers/mapper349.c @@ -0,0 +1,45 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 349 - BMC-G-146 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x800) { /* UNROM mode */ + setprg16(0x8000, (latch.addr & 0x1F) | (latch.addr & ((latch.addr & 0x40) >> 6))); + setprg16(0xC000, (latch.addr & 0x1F) | 0x07); + } else { + if (latch.addr & 0x40) { /* 16K mode */ + setprg16(0x8000, latch.addr & 0x1F); + setprg16(0xC000, latch.addr & 0x1F); + } else { /* 32K mode */ + setprg32(0x8000, (latch.addr >> 1) & 0x0F); + } + } + setchr8(0); + setmirror(((latch.addr & 0x80) >> 7) ^ 0x01); +} + +void Mapper349_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper350.c b/src/mappers/mapper350.c new file mode 100644 index 000000000..f349d0755 --- /dev/null +++ b/src/mappers/mapper350.c @@ -0,0 +1,88 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 350 - BMC-891227 + * Super 15-in-1 Game Card + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_350 + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank = (reg[0] & 0x18) | (reg[1] & 0x07); + + setprg8(0x6000, 1); + if (reg[0] & 0x40) { /* UNROM */ + if (reg[0] & 0x20) { + /* 2nd chip only has 128K PRG */ + bank &= 0x07; + } + setprg16(0x8000, (reg[0] & 0x20) | bank); + setprg16(0xC000, (reg[0] & 0x20) | bank | 0x07); + } else { + if (reg[0] & 0x20) { /* NROM-256 */ + setprg32(0x8000, bank >> 1); + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } + /* CHR-RAM Protect... kinda */ + SetupCartCHRMapping(0, CHRptr[0], 0x2000, (reg[0] & 0x40) != 0); + setchr8(0); + setmirror(((reg[0] >> 7) & 0x01) ^ 0x01); +} + +static DECLFW(M350Write) { + reg[(A >> 14) & 0x01] = V; + Sync(); +} + +static void M350Reset(void) { + reg[0] = reg[1] = 0; + Sync(); +} + +static void M350Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M350Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper350_Init(CartInfo *info) { + info->Power = M350Power; + info->Reset = M350Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper351.c b/src/mappers/mapper351.c new file mode 100644 index 000000000..bab223783 --- /dev/null +++ b/src/mappers/mapper351.c @@ -0,0 +1,274 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc1.h" +#include "mmc3.h" +#include "vrc24.h" + +static uint8 reg[4], dipsw; + +static SFORMAT stateRegs[] = { + { reg, 4, "REGS" }, + { &dipsw, 1, "DIPS" }, + { 0 }, +}; + +static uint32 GetPRGMask(void) { + return ((reg[2] & 0x04) ? 0x0F : 0x1F); +} + +static uint32 GetPRGBase(void) { + return (reg[1] >> 1); +} + +static uint32 GetCHRMask(void) { + if ((reg[2] & 0x10) && !(reg[2] & 0x20)) { + return 0x1F; + } + return ((reg[2] & 0x20) ? 0x7F : 0xFF); +} + +static uint32 GetCHRBase(void) { + return (reg[0] << 1); +} + +static void M351MMC1PW(uint16 A, uint16 V) { + uint8 mask = GetPRGMask() >> 1; + uint8 bank = GetPRGBase() >> 1; + + setprg16(A, (bank & ~mask) | (V & mask)); +} + +static void M351MMC1CW(uint16 A, uint16 V) { + uint16 mask = GetCHRMask() >> 2; + uint16 bank = GetCHRBase() >> 2; + + setchr4(A, (bank & ~mask) | (V & mask)); +} + +static void M351MMC3PW(uint16 A, uint16 V) { + uint8 mask = GetPRGMask(); + uint8 bank = GetPRGBase(); + + setprg8(A, (bank & ~mask) | (V & mask)); +} + +static void M351MMC3CW(uint16 A, uint16 V) { + uint16 mask = GetCHRMask(); + uint16 bank = GetCHRBase(); + + setchr1(A, (bank & ~mask) | (V & mask)); +} + +static void M351VRC24PW(uint16 A, uint16 V) { + uint8 mask = GetPRGMask(); + uint8 bank = GetPRGBase(); + + setprg8(A, (bank & ~mask) | (V & mask)); +} + +static void M351VRC24CW(uint16 A, uint16 V) { + uint16 mask = GetCHRMask(); + uint16 bank = GetCHRBase(); + + setchr1(A, (bank & ~mask) | (V & mask)); +} + +static void SyncPRG(void) { + if (reg[2] & 0x10) { /* NROM mode */ + uint32 bank = GetPRGBase(); + + if (reg[2] & 0x08) { /* NROM-64 */ + setprg8(0x8000, bank); + setprg8(0xA000, bank); + setprg8(0xC000, bank); + setprg8(0xE000, bank); + } else { + if (reg[2] & 0x04) { /* NROM-128 */ + setprg16(0x8000, bank >> 1); + setprg16(0xC000, bank >> 1); + } else { /* NROM-256 */ + setprg32(0x8000, bank >> 2); + } + } + } else { + switch (reg[0] & 0x03) { + default: + case 1: MMC3_FixPRG(); break; + case 2: MMC1_FixPRG(); break; + case 3: VRC24_FixPRG(); break; + } + } +} + +static void SyncCHR(void) { + if (reg[2] & 0x01) { /* CHR RAM mode */ + setchr8r(0x10, 0); + } else if (reg[2] & 0x40) { /* CNROM mode */ + setchr8(GetCHRBase() >> 3); + } else { + switch (reg[0] & 0x03) { + default: + case 1: MMC3_FixCHR(); break; + case 2: MMC1_FixCHR(); break; + case 3: VRC24_FixCHR(); break; + } + } +} + +static void SyncMIR(void) { + switch (reg[0] & 0x03) { + default: + case 1: MMC3_FixMIR(); break; + case 2: MMC1_FixMIR(); break; + case 3: VRC24_FixMIR(); break; + } +} + +static void Sync(void) { + SyncPRG(); + SyncCHR(); + SyncMIR(); +} + +static void M351CPUHook(int a) { + if ((reg[0] & 0x03) == 0x03) { + VRC24_IRQCPUHook(a); + } +} + +static void M351HBHook(void) { + if (!(reg[0] & 0x02)) { /* MMC3 mode */ + MMC3_IRQHBHook(); + } +} + +static DECLFR(M351ReadDIP) { + return dipsw; +} + +static DECLFW(M351WriteMirr) { + /* FDS mirroring */ + mmc3.mirr = (V >> 3) & 0x01; + SyncMIR(); +} + +static DECLFW(M351WriteReg) { + reg[A & 0x03] = V; + Sync(); +} + +static DECLFW(M351Write) { + switch (reg[0] & 0x03) { + default: + case 1: + MMC3_Write(A, V); + Sync(); + break; + case 2: + MMC1_Write(A, V); + break; + case 3: + if (!(reg[2] & 0x04)) { + A = (A & 0xF800) | ((A >> 1) & 0x3FF); + } + if (A & 0x800) { + A = (A & 0xFFF3) | ((A << 1) & 0x08) | ((A >> 1) & 0x04); + } + VRC24_Write(A, V); + break; + } +} + +static void M351Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + dipsw = 0; + + VRC24_Reset(); + MMC1_Reset(); + MMC3_Reset(); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetReadHandler(0x5000, 0x5FFF, M351ReadDIP); + SetWriteHandler(0x4025, 0x4025, M351WriteMirr); + SetWriteHandler(0x5000, 0x5FFF, M351WriteReg); + SetWriteHandler(0x8000, 0xFFFF, M351Write); +} + +static void M531Reset(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + dipsw++; + + VRC24_Reset(); + MMC1_Reset(); + MMC3_Reset(); + + FCEU_printf(" Mapper Reset! dpsw:%d\n", dipsw); +} + +static void M351Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper351_Init(CartInfo *info) { + int CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; + + VRC24_Init(info, VRC2, 0x04, 0x08, FALSE, TRUE); + VRC24_pwrap = M351VRC24PW; + VRC24_cwrap = M351VRC24CW; + + MMC1_Init(info, FALSE, FALSE); + MMC1_pwrap = M351MMC1PW; + MMC1_cwrap = M351MMC1CW; + + MMC3_Init(info, FALSE, FALSE); + MMC3_pwrap = M351MMC3PW; + MMC3_cwrap = M351MMC3CW; + + info->Reset = M531Reset; + info->Power = M351Power; + info->Close = M351Close; + + MapIRQHook = M351CPUHook; + GameHBIRQHook = M351HBHook; + + GameStateRestore = StateRestore; + AddExState(stateRegs, ~0, 0, 0); + + if (CHR_ROM_SIZE_8K) { + uint32 old_prg_size = PRG_ROM_SIZE_16K; + /* This crazy thing can map CHR-ROM into CPU address space. Allocate a + * combined PRG+CHR address space and treat it a second "chip". */ + PRG_ROM_SIZE_16K = old_prg_size + CHR_ROM_SIZE_8K; + PRG_ROM_DATA = (uint8 *)realloc(PRG_ROM_DATA, PRG_ROM_SIZE_16K); + memcpy(PRG_ROM_DATA + old_prg_size, CHR_ROM_DATA, CHR_ROM_SIZE_8K); + SetupCartPRGMapping(0, PRG_ROM_DATA, PRG_ROM_SIZE_16K, 0); + } + + if (CHRRAMSIZE) { + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); + } +} diff --git a/src/mappers/mapper352.c b/src/mappers/mapper352.c new file mode 100644 index 000000000..5282a6449 --- /dev/null +++ b/src/mappers/mapper352.c @@ -0,0 +1,62 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * NES 2.0 Mapper 352 + * BMC-KS106C + * - Kaiser 4-in-1(Unl,M352)[p1] - B-Wings, Kung Fu, 1942, SMB1 + */ + +#include "mapinc.h" + +static uint8 gameblock; + +static SFORMAT StateRegs[] = { + { &gameblock, 1, "GAME" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, gameblock); + setchr8(gameblock); + setmirror(gameblock & 0x01); +} + +static void M352Power(void) { + gameblock = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void M352Reset(void) { + gameblock++; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper352_Init(CartInfo *info) { + info->Power = M352Power; + info->Reset = M352Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper353.c b/src/mappers/mapper353.c new file mode 100644 index 000000000..2f1489f99 --- /dev/null +++ b/src/mappers/mapper353.c @@ -0,0 +1,163 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 353 is used for the 92 Super Mario Family multicart, + * consisting of an MMC3 clone ASIC together with a PAL. + * The PCB code is 81-03-05-C. + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "fdssound.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M353PW(uint16 A, uint16 V) { + uint16 base = reg << 5; + uint16 mask = 0x1F; + + if (reg == 2) { + base |= (mmc3.reg[0] & 0x80) ? 0x10 : 0x00; + mask >>= 1; + } else if ((reg == 3) && !(mmc3.reg[0] & 0x80) && (A >= 0xC000)) { + base = 0x70; + mask = 0x0F; + V = mmc3.reg[6 + ((A >> 13) & 0x01)]; + } + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M353CW(uint16 A, uint16 V) { + uint16 mask = 0x7F; + uint16 base = reg << 7; + + if ((reg == 2) && (mmc3.reg[0] & 0x80)) { + setchr8r(0x10, 0); + } else { + setchr1(A, (base & ~mask) | (V & mask)); + } +} + +static void M353MIR(void) { + if (reg == 0) { + if (mmc3.cmd & 0x80) { + setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); + } else { + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); + } + } else { + setmirror((mmc3.mirr & 0x01) ^ 0x01); + } +} + +static DECLFW(M353Write) { + if (A & 0x80) { + reg = (A >> 13) & 0x03; + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } else { + uint8 oldcmd = mmc3.cmd; + + switch (A & 0xE001) { + case 0x8000: + mmc3.cmd = V; + if ((oldcmd & 0x40) != (mmc3.cmd & 0x40)) { + MMC3_FixPRG(); + } + if ((oldcmd & 0x80) != (mmc3.cmd & 80)) { + MMC3_FixCHR(); + MMC3_FixMIR(); + } + break; + case 0x8001: + mmc3.reg[mmc3.cmd & 0x07] = V; + switch (mmc3.cmd & 0x07) { + case 0: + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + case 1: + case 2: + case 3: + case 4: + case 5: + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + case 6: + case 7: + MMC3_FixPRG(); + break; + } + break; + default: + MMC3_Write(A, V); + break; + } + } +} + +static void M353Power(void) { + FDSSound_Power(); + reg = 0; + MMC3_Power(); + SetWriteHandler(0x8000, 0xFFFF, M353Write); +} + +static void M353Reset(void) { + reg = 0; + MMC3_Reset(); + FDSSoundRegReset(); + FDSSound_SC(); +} + +static void M353Close(void) { + MMC3_Close(); +} + +void Mapper353_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + MMC3_cwrap = M353CW; + MMC3_pwrap = M353PW; + MMC3_FixMIR = M353MIR; + info->Power = M353Power; + info->Close = M353Close; + info->Reset = M353Reset; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper354.c b/src/mappers/mapper354.c new file mode 100644 index 000000000..0e6147db6 --- /dev/null +++ b/src/mappers/mapper354.c @@ -0,0 +1,87 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 354 denotes three different PCBs: + * - FAM250 for the 1992 巨作 250-in-1 劃面選關 鑽石巨王 multicart (iNESCart.submapper 0), + * - 810139C for the 1992 劃面選關 400-in-1 創新版 as well as an undumped 650-in-1 multicart (also iNESCart.submapper 0), + * - 810331C/SCHI-24 for the 1992 劃面選關 1050-in-1 multicart (iNESCart.submapper 1). + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint16 prg = ((latch.addr >> 5) & 0x80) | ((latch.addr << 2) & 0x40) | (latch.data & 0x3F); + + switch (latch.addr & 0x07) { + case 0: + case 4: + setprg32(0x8000, prg >> 1); + break; + case 1: + setprg16(0x8000, prg); + setprg16(0xC000, prg | 0x07); + break; + case 2: + case 6: + setprg8(0x8000, (prg << 1) | (latch.data >> 7)); + setprg8(0xA000, (prg << 1) | (latch.data >> 7)); + setprg8(0xC000, (prg << 1) | (latch.data >> 7)); + setprg8(0xE000, (prg << 1) | (latch.data >> 7)); + break; + case 3: + case 7: + setprg16(0x8000, prg); + setprg16(0xC000, prg); + break; + case 5: + setprg8(0x6000, (prg << 1) | (latch.data >> 7)); + setprg32(0x8000, (prg >> 1) | 0x03); + break; + } + /* CHR-RAM write protect */ + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], ((latch.addr >> 3) & 0x01) ^ 0x01); + setchr8(0); + setmirror(((latch.data >> 6) & 0x01) ^ 0x01); +} + +static DECLFW(M354Write) { + uint32 addr = 0xE000 | (iNESCart.submapper == 0) ? 0x1000 : 0; + + if (A < addr) { + return; + } + + latch.addr = A; + latch.data = V; + Sync(); +} + +static void M354_Power(void) { + Latch_Power(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M354Write); +} + +void Mapper354_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M354_Power; + info->Reset = Latch_RegReset; +} \ No newline at end of file diff --git a/src/mappers/mapper355.c b/src/mappers/mapper355.c new file mode 100644 index 000000000..33817dbc0 --- /dev/null +++ b/src/mappers/mapper355.c @@ -0,0 +1,135 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NOTE: This only emulates the UNIF variant of 3D-Blocks */ + +#include "mapinc.h" + +#include "mapper355.h" +#include "hw/pic16c5x.h" + +static uint32 address; +static uint8 *eprom = NULL; + +static uint8_t pci16c5x_read(int port) { + if (port == 0) { + return (1 | + (address & 0x0040 ? 0x02 : 0) | /* A6 -> RA1 */ + (address & 0x0020 ? 0x04 : 0) | /* A5 -> RA2 */ + (address & 0x0010 ? 0x08 : 0)); /* A4 -> RA3 */ + } else if (port == 1) { + return ( + (address & 0x1000 ? 0x01 : 0) | /* A12 -> RB0 */ + (address & 0x0080 ? 0x02 : 0) | /* A7 -> RB1 */ + (address & 0x0400 ? 0x04 : 0) | /* A10 -> RB2 */ + (address & 0x0800 ? 0x08 : 0) | /* A11 -> RB3 */ + (address & 0x0200 ? 0x10 : 0) | /* A9 -> RB4 */ + (address & 0x0100 ? 0x20 : 0) | /* A8 -> RB5 */ + (address & 0x2000 ? 0x40 : 0) | /* A13 -> RB6 */ + (address & 0x4000 ? 0x80 : 0)); /* A14 -> RB7 */ + } + return (0xFF); +} + +static void pci16c5x_write(int port, int val) { + if (port == 0) { + if (val & 0x1001) { + X6502_IRQEnd(FCEU_IQEXT); + } else { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M355CPUIRQHook(int a) { + while (a--) { + pic16c5x_run(); + } +} + +static readfunc cpuRead[0x10000]; +static writefunc cpuWrite[0x10000]; + +static DECLFR(M555Read) { + address = A; + if (A >= 0x8000) { + return CartBR(A); + } + return cpuRead[A](A); +} + +static DECLFW(M555Write) { + address = A; + if (cpuWrite[A]) { + cpuWrite[A](A, V); + } +} + +static void M555Power(void) { + int x; + + address = 0; + + pic16c5x_reset(1); + + setprg32(0x8000, 0); + setchr8(0); + + for (x = 0; x < 0x10000; x++) { + cpuRead[x] = GetReadHandler(x); + cpuWrite[x] = GetWriteHandler(x); + } + + SetReadHandler(0, 0xFFFF, M555Read); + SetWriteHandler(0, 0xFFFF, M555Write); +} + +static void M555Reset(void) { + address = 0; + pic16c5x_reset(0); +} + +static void M555Close(void) { + eprom = NULL; +} + +void Mapper355_Init(CartInfo *info) { + if (MISC_ROM_SIZE && (MISC_ROM_SIZE == 1024)) { + eprom = MISC_ROM_DATA; + } else { + if (info->CRC32 == 0x86DBA660) { /* 3D Block (Hwang Shinwei) [!].nes */ + eprom = &eprom_3d_block[0]; + } else if ((info->CRC32 == 0x3C43939D) || /* Block Force.nes */ + (info->CRC32 == 0xB655C53A)) { /* Block Force (Hwang Shinwei).nes */ + eprom = &eprom_block_force[0]; + } + } + + if (eprom) { + pic16c54_init(eprom, pci16c5x_read, pci16c5x_write); + pic16c5x_add_statesinfo(); + } + + info->Power = M555Power; + info->Reset = M555Reset; + info->Close = M555Close; + MapIRQHook = M355CPUIRQHook; + AddExState(&address, sizeof(address), 0, "ADDR"); +} diff --git a/src/mappers/mapper355.h b/src/mappers/mapper355.h new file mode 100644 index 000000000..2b4c1d063 --- /dev/null +++ b/src/mappers/mapper355.h @@ -0,0 +1,140 @@ +#ifndef _MAPPER_355_H +#define _MAPPER_355_H + +/* microcontroller ROM */ + +static uint8 eprom_3d_block[] = { + 0xFE, 0x0C, 0x05, 0x00, 0x00, 0x0C, 0x25, 0x00, 0x00, 0x00, 0xFF, 0x0C, 0x05, 0x00, 0x00, 0x08, + 0x28, 0x00, 0xE8, 0x02, 0x09, 0x0A, 0x00, 0x08, 0x28, 0x00, 0xE8, 0x02, 0x0D, 0x0A, 0xE9, 0x02, + 0x0D, 0x0A, 0x00, 0x08, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x06, 0x12, 0x0A, 0x00, 0x08, 0xE2, 0x01, + 0x00, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x00, 0x08, 0xFF, 0x08, 0xFF, 0x08, 0xFF, 0x08, + 0xE2, 0x01, 0xFF, 0x08, 0xFF, 0x08, 0x00, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x00, 0x08, + 0xFF, 0x08, 0xFF, 0x0C, 0x05, 0x00, 0xFF, 0x0C, 0x06, 0x00, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x07, + 0x2D, 0x0A, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x07, 0x2D, 0x0A, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x07, + 0x2D, 0x0A, 0x0E, 0x0C, 0x45, 0x01, 0x2A, 0x00, 0x43, 0x07, 0x44, 0x0A, 0x05, 0x0C, 0x29, 0x00, + 0x03, 0x0C, 0x0C, 0x09, 0x00, 0x09, 0x2D, 0x0A, 0x02, 0x0C, 0x8A, 0x01, 0x43, 0x07, 0x55, 0x0A, + 0x02, 0x0C, 0x29, 0x00, 0x05, 0x0C, 0x0C, 0x09, 0x00, 0x09, 0x0B, 0x0C, 0x29, 0x00, 0x90, 0x0C, + 0x08, 0x09, 0x00, 0x09, 0xE9, 0x02, 0x4F, 0x0A, 0x2D, 0x0A, 0x0E, 0x0C, 0x8A, 0x01, 0x43, 0x07, + 0x5C, 0x0A, 0xA0, 0x0C, 0x2B, 0x00, 0x2D, 0x0A, 0x04, 0x0C, 0x8A, 0x01, 0x43, 0x07, 0x98, 0x0A, + 0x02, 0x0C, 0x8B, 0x01, 0x43, 0x06, 0x2D, 0x0A, 0xEB, 0x00, 0xEB, 0x00, 0x03, 0x0C, 0x29, 0x00, + 0x2C, 0x0C, 0x0C, 0x09, 0x00, 0x09, 0x30, 0x0C, 0x2C, 0x00, 0x00, 0x0C, 0x2D, 0x00, 0x0B, 0x02, + 0x28, 0x00, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x07, 0x79, 0x0A, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x06, + 0x2D, 0x0A, 0xE8, 0x02, 0x71, 0x0A, 0x00, 0x09, 0x3B, 0x0C, 0x28, 0x00, 0xE2, 0x0C, 0x86, 0x01, + 0x43, 0x07, 0x86, 0x0A, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x06, 0x2D, 0x0A, 0xE8, 0x02, 0x7E, 0x0A, + 0x00, 0x09, 0x0B, 0x02, 0xEC, 0x01, 0x03, 0x07, 0x8E, 0x0A, 0xAD, 0x02, 0x3B, 0x0C, 0xEC, 0x01, + 0x03, 0x07, 0x93, 0x0A, 0xAD, 0x02, 0x02, 0x0C, 0x8D, 0x00, 0x03, 0x07, 0x6F, 0x0A, 0x2D, 0x0A, + 0x08, 0x0C, 0x8A, 0x01, 0x43, 0x07, 0xA1, 0x0A, 0x08, 0x0C, 0x2E, 0x00, 0xF0, 0x0C, 0x24, 0x00, + 0x5A, 0x0B, 0x0A, 0x0C, 0x8A, 0x01, 0x43, 0x07, 0xA7, 0x0A, 0x03, 0x04, 0xAC, 0x0A, 0x0C, 0x0C, + 0x8A, 0x01, 0x43, 0x07, 0x5D, 0x0B, 0x03, 0x05, 0x60, 0x03, 0xEE, 0x00, 0x43, 0x07, 0x5A, 0x0B, + 0x08, 0x0C, 0x2E, 0x00, 0xA4, 0x02, 0xF4, 0x0C, 0x84, 0x01, 0x43, 0x07, 0x5A, 0x0B, 0x1F, 0x0C, + 0x53, 0x01, 0x37, 0x00, 0x33, 0x03, 0x33, 0x03, 0x33, 0x03, 0x33, 0x03, 0x33, 0x03, 0x07, 0x0C, + 0x53, 0x01, 0x3A, 0x00, 0x0F, 0x0C, 0x52, 0x01, 0x39, 0x00, 0x28, 0x00, 0x32, 0x03, 0x32, 0x03, + 0x32, 0x03, 0x32, 0x03, 0x0F, 0x0C, 0x52, 0x01, 0x38, 0x00, 0x07, 0x0C, 0x51, 0x01, 0x35, 0x00, + 0x31, 0x03, 0x31, 0x03, 0x31, 0x03, 0x07, 0x0C, 0x51, 0x01, 0x34, 0x00, 0x31, 0x03, 0x31, 0x03, + 0x31, 0x03, 0x03, 0x0C, 0x51, 0x01, 0x33, 0x00, 0x07, 0x0C, 0x50, 0x01, 0x32, 0x00, 0x30, 0x03, + 0x30, 0x03, 0x30, 0x03, 0x07, 0x0C, 0x50, 0x01, 0x31, 0x00, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, + 0x03, 0x0C, 0x50, 0x01, 0x30, 0x00, 0x07, 0x0C, 0x79, 0x01, 0x28, 0x03, 0x04, 0x0C, 0x48, 0x01, + 0x33, 0x01, 0x08, 0x0C, 0x57, 0x01, 0x43, 0x06, 0xF6, 0x0A, 0xB8, 0x02, 0x10, 0x0C, 0x57, 0x01, + 0x43, 0x06, 0x06, 0x0B, 0x07, 0x0C, 0x77, 0x01, 0x17, 0x02, 0x17, 0x09, 0xF9, 0x01, 0xF9, 0x06, + 0xB9, 0x00, 0x17, 0x02, 0x20, 0x09, 0xFA, 0x01, 0xFA, 0x06, 0xBA, 0x00, 0x7B, 0x00, 0x02, 0x0C, + 0xB1, 0x00, 0x71, 0x02, 0xB1, 0x02, 0xF1, 0x06, 0x13, 0x0B, 0x19, 0x02, 0x91, 0x00, 0x03, 0x07, + 0x13, 0x0B, 0x11, 0x02, 0x39, 0x00, 0x02, 0x0C, 0xB2, 0x00, 0x72, 0x02, 0xB2, 0x02, 0xF2, 0x06, + 0x1F, 0x0B, 0x1A, 0x02, 0x92, 0x00, 0x03, 0x07, 0x1F, 0x0B, 0x12, 0x02, 0x3A, 0x00, 0x02, 0x0C, + 0xB0, 0x00, 0x70, 0x02, 0xB0, 0x02, 0xF0, 0x06, 0x2B, 0x0B, 0x18, 0x02, 0x90, 0x00, 0x03, 0x07, + 0x2B, 0x0B, 0x10, 0x02, 0x38, 0x00, 0x02, 0x0C, 0xB4, 0x00, 0x05, 0x0C, 0xB4, 0x00, 0x74, 0x02, + 0xB4, 0x02, 0xF4, 0x06, 0x39, 0x0B, 0x19, 0x02, 0x94, 0x00, 0x03, 0x06, 0x39, 0x0B, 0x14, 0x02, + 0x39, 0x00, 0x02, 0x0C, 0xB5, 0x00, 0x05, 0x0C, 0xB5, 0x00, 0x75, 0x02, 0xB5, 0x02, 0xF5, 0x06, + 0x47, 0x0B, 0x1A, 0x02, 0x95, 0x00, 0x03, 0x06, 0x47, 0x0B, 0x15, 0x02, 0x3A, 0x00, 0x02, 0x0C, + 0xB3, 0x00, 0x0A, 0x0C, 0xB3, 0x00, 0x73, 0x02, 0xB3, 0x02, 0xF3, 0x06, 0x58, 0x0B, 0x18, 0x02, + 0x93, 0x00, 0x43, 0x06, 0x57, 0x0B, 0x03, 0x06, 0x58, 0x0B, 0x13, 0x02, 0x38, 0x00, 0xBB, 0x02, + 0xF8, 0x0C, 0x24, 0x00, 0x12, 0x09, 0x00, 0x09, 0x2D, 0x0A, 0x12, 0x09, 0x00, 0x02, 0x43, 0x06, + 0x67, 0x0B, 0x03, 0x0C, 0x08, 0x09, 0x00, 0x09, 0xE0, 0x00, 0x43, 0x07, 0x61, 0x0B, 0xA4, 0x02, + 0x2D, 0x0A, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x29, 0x0A +}; + +static uint8 eprom_block_force[] = { + 0xFE, 0x0C, 0x05, 0x00, 0x05, 0x05, 0xFF, 0x0C, 0x06, 0x00, 0x02, 0x0C, 0x3A, 0x00, 0x00, 0x0C, + 0x3B, 0x00, 0x05, 0x0C, 0x3C, 0x00, 0x06, 0x0C, 0x3D, 0x00, 0x00, 0x0C, 0x3E, 0x00, 0x00, 0x0C, + 0x3F, 0x00, 0xDD, 0x0C, 0x86, 0x01, 0x43, 0x07, 0x11, 0x0A, 0xDD, 0x0C, 0x86, 0x01, 0x43, 0x06, + 0x15, 0x0A, 0xDF, 0x0C, 0x86, 0x01, 0x43, 0x07, 0x11, 0x0A, 0x0F, 0x0C, 0x45, 0x01, 0xE2, 0x01, + 0x30, 0x0A, 0x30, 0x0A, 0x38, 0x0A, 0x38, 0x0A, 0x34, 0x0A, 0x34, 0x0A, 0x48, 0x0A, 0x48, 0x0A, + 0x32, 0x0A, 0x32, 0x0A, 0x44, 0x0A, 0x44, 0x0A, 0x36, 0x0A, 0x36, 0x0A, 0x4B, 0x0A, 0x4B, 0x0A, + 0x64, 0x00, 0x11, 0x0A, 0xA4, 0x02, 0x11, 0x0A, 0x60, 0x00, 0x11, 0x0A, 0xA0, 0x02, 0x11, 0x0A, + 0x10, 0x02, 0x32, 0x00, 0x11, 0x02, 0x33, 0x00, 0xF2, 0x02, 0x3C, 0x0A, 0xF3, 0x02, 0x3C, 0x0A, + 0x05, 0x04, 0x05, 0x04, 0x05, 0x05, 0x11, 0x0A, 0x08, 0x02, 0xE2, 0x01, 0x50, 0x0A, 0x88, 0x0A, + 0x00, 0x02, 0x27, 0x00, 0x11, 0x0A, 0xE7, 0x02, 0x11, 0x0A, 0x05, 0x04, 0x05, 0x05, 0x11, 0x0A, + 0x19, 0x02, 0x9F, 0x00, 0x43, 0x06, 0x57, 0x0A, 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x18, 0x02, + 0x9E, 0x00, 0x43, 0x06, 0x5E, 0x0A, 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x17, 0x02, 0x9D, 0x00, + 0x43, 0x06, 0x65, 0x0A, 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x16, 0x02, 0x9C, 0x00, 0x43, 0x06, + 0x6C, 0x0A, 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x15, 0x02, 0x9B, 0x00, 0x43, 0x06, 0x73, 0x0A, + 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x14, 0x02, 0x9A, 0x00, 0x43, 0x06, 0x7A, 0x0A, 0x03, 0x07, + 0x7B, 0x0A, 0x11, 0x0A, 0x11, 0x0A, 0x14, 0x02, 0x3A, 0x00, 0x15, 0x02, 0x3B, 0x00, 0x16, 0x02, + 0x3C, 0x00, 0x17, 0x02, 0x3D, 0x00, 0x18, 0x02, 0x3E, 0x00, 0x19, 0x02, 0x3F, 0x00, 0x11, 0x0A, + 0x8B, 0x09, 0x29, 0x00, 0x11, 0x0A, 0x09, 0x02, 0xE2, 0x01, 0x00, 0x08, 0x19, 0x08, 0x33, 0x08, + 0x4C, 0x08, 0x66, 0x08, 0x80, 0x08, 0x99, 0x08, 0xB3, 0x08, 0xCC, 0x08, 0xE6, 0x08, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, + 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x0A +}; + +#endif /* _MAPPER_355_H */ \ No newline at end of file diff --git a/src/mappers/mapper356.c b/src/mappers/mapper356.c new file mode 100644 index 000000000..ab6c9f497 --- /dev/null +++ b/src/mappers/mapper356.c @@ -0,0 +1,107 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 356 - J.Y. Company's 7-in-1 Rockman (JY-208) + * All registers work as INES Mapper 045, except $6000 sequential register 2 (third write): + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; +static uint8 cmd; +static uint8 ntaramExtra[2048]; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &cmd, 1, "CMD0" }, + { 0 } +}; + +static void M356CW(uint16 A, uint16 V) { + if (reg[2] & 0x20) { + uint16 mask = 0xFF >> (~reg[2] & 0xF); + uint16 base = ((reg[2] << 4) & 0xF00) | reg[0]; + + setchr1(A, (base & ~mask) | (V & mask)); + } else { + setchr8r(0x10, 0); + } +} + +static void M356PW(uint16 A, uint16 V) { + uint16 mask = ~reg[3] & 0x3F; + uint16 base = ((reg[2] << 2) & 0x300) | reg[1]; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M356MIR(void) { + if (reg[2] & 0x40) { + /* setmirror(MI_4); */ + SetupCartMirroring(4, 0, ntaramExtra); + } else { + setmirror((mmc3.mirr & 0x01) ^ 0x01); + } +} + +static DECLFW(M356Write) { + if (!(reg[3] & 0x40)) { + reg[cmd] = V; + cmd = (cmd + 1) & 3; + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } +} + +static void M356Close(void) { + MMC3_Close(); +} + +static void M356Reset(void) { + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + MMC3_Reset(); +} + +static void M356Power(void) { + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M356Write); +} + +void Mapper356_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M356CW; + MMC3_pwrap = M356PW; + MMC3_FixMIR = M356MIR; + info->Reset = M356Reset; + info->Power = M356Power; + info->Close = M356Close; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); + AddExState(ntaramExtra, 2048, 0, "ExRM"); +} diff --git a/src/mappers/mapper357.c b/src/mappers/mapper357.c new file mode 100644 index 000000000..fe1948ed7 --- /dev/null +++ b/src/mappers/mapper357.c @@ -0,0 +1,125 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 357 is used for a 4-in-1 multicart (cartridge ID 4602) from Bit Corp. + * The first game is Bit Corp's hack of the YUNG-08 conversion of Super Mario Brothers 2 (J) named Mr. Mary 2, + * the other three games are UNROM games. + * + * Implementation is modified so reset actually sets the correct dipswitch (or outer banks) for each of the 4 games + */ + +#include "mapinc.h" + +static uint8 reg[4]; +static uint8 dipsw; +static uint8 IRQa; +static uint16 IRQCount; + +static SFORMAT StateRegs[] = { + { reg, 4, "REG" }, + { &dipsw, 1, "DPSW" }, + { &IRQCount, 2, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void Sync(void) { + if (dipsw == 0) { + static const uint8 banks[2][8] = { + { 4, 3, 5, 3, 6, 3, 7, 3 }, + { 1, 1, 5, 1, 4, 1, 5, 1 } + }; + /* SMB2J Mode */ + setprg8(0x6000, reg[1] ? 0 : 2); + setprg8(0x8000, reg[1] ? 0 : 1); + setprg8(0xA000, 0); + setprg8(0xC000, banks[reg[1]][reg[0]]); + setprg8(0xE000, reg[1] ? 8 : 10); + } else { + /* UNROM Mode */ + setprg16(0x8000, (dipsw << 3) | reg[2]); + setprg16(0xc000, (dipsw << 3) | 0x07); + } +} + +static DECLFW(M357Write) { + if (A & 0x8000) { + reg[2] = V & 0x07; + Sync(); + } + if ((A & 0x71FF) == 0x4022) { + reg[0] = V & 0x07; + Sync(); + } + if ((A & 0x71FF) == 0x4120) { + reg[1] = V & 0x01; + Sync(); + } + if ((A & 0xF1FF) == 0x4122) { + IRQa = V & 0x01; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + } +} + +static void M357Power(void) { + reg[0] = 0; + reg[1] = 0; + reg[2] = 0; + IRQa = IRQCount = 0; + setchr8(0); + setmirror(MI_V); + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0xFFFF, M357Write); +} + +static void M357Reset(void) { + reg[0] = 0; + reg[1] = 0; + reg[2] = 0; + IRQa = IRQCount = 0; + dipsw++; + dipsw &= 3; + setmirror((dipsw == 3) ? MI_H : MI_V); + Sync(); +} + +static void M357IRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount & 0x1000) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper357_Init(CartInfo *info) { + info->Reset = M357Reset; + info->Power = M357Power; + MapIRQHook = M357IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper358.c b/src/mappers/mapper358.c new file mode 100644 index 000000000..4249ebbbe --- /dev/null +++ b/src/mappers/mapper358.c @@ -0,0 +1,41 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +static uint32 GetPRGBank(uint32 V) { + return (((jyasic.mode[3] << 4) & ~0x1F) | (V & 0x1F)); +} + +static uint32 GetCHRBank(uint32 V) { + if (jyasic.mode[3] & 0x20) { + return (((jyasic.mode[3] << 7) & 0x600) | (V & 0x1FF)); + } else { + return (((jyasic.mode[3] << 7) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); + } +} + +void Mapper358_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} diff --git a/src/mappers/mapper359.c b/src/mappers/mapper359.c new file mode 100644 index 000000000..096e7982d --- /dev/null +++ b/src/mappers/mapper359.c @@ -0,0 +1,226 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 359 - BMC-SB-5013 + * NES 2.0 Mapper 540 - UNL-82112C + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 prg[4]; +static uint8 chr[8]; +static uint8 reg[4]; + +static uint8 IRQReload; +static uint8 IRQa; +static uint8 irqPA12; +static uint8 IRQAutoEnable; +static uint8 IRQLatch; +static uint8 IRQCount; +static int16 IRQCount16; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { reg, 4, "EXPR" }, + { &IRQReload, 1, "IRQL" }, + { &IRQa, 1, "IRQa" }, + { &irqPA12, 1, "IRQp" }, + { &IRQAutoEnable, 1, "IRQe" }, + { &IRQLatch, 1, "IRQl" }, + { &IRQCount, 1, "IRQ8" }, + { &IRQCount16, 2, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + uint16 prgMask = 0x3F; + uint16 prgBase = (reg[0] & 0x38) << 1; + + switch (reg[1] & 0x03) { + case 0: prgMask = 0x3F; break; + case 1: prgMask = 0x1F; break; + case 2: prgMask = 0x2F; break; + case 3: prgMask = 0x0F; break; + } + + setprg8(0x6000, prgBase | (prg[3] & prgMask)); + setprg8(0x8000, prgBase | (prg[0] & prgMask)); + setprg8(0xA000, prgBase | (prg[1] & prgMask)); + setprg8(0xC000, prgBase | (prg[2] & prgMask)); + setprg8(0xE000, prgBase | ( ~0 & prgMask)); + + if (!CHR_ROM_SIZE_8K) { + setchr8(0); + } else { + if (iNESCart.mapper == 540) { + setchr2(0x0000, chr[0]); + setchr2(0x0800, chr[1]); + setchr2(0x1000, chr[6]); + setchr2(0x1800, chr[7]); + } else { + uint16 chrMask = (reg[1] & 0x40) ? 0xFF : 0x7F; + uint16 chrBase = (reg[3] << 7); + + setchr1(0x0000, chrBase | (chr[0] & chrMask)); + setchr1(0x0400, chrBase | (chr[1] & chrMask)); + setchr1(0x0800, chrBase | (chr[2] & chrMask)); + setchr1(0x0C00, chrBase | (chr[3] & chrMask)); + setchr1(0x1000, chrBase | (chr[4] & chrMask)); + setchr1(0x1400, chrBase | (chr[5] & chrMask)); + setchr1(0x1800, chrBase | (chr[6] & chrMask)); + setchr1(0x1C00, chrBase | (chr[7] & chrMask)); + } + } + + switch (reg[2] & 0x03) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } +} + +static DECLFW(M359Write) { + switch (A & 0xF000) { + case 0x8000: + prg[A & 0x03] = V; + Sync(); + break; + case 0x9000: + reg[A & 0x03] = V; + Sync(); + break; + case 0xA000: + case 0xB000: + chr[((A >> 10) & 0x04) | (A & 0x03)] = V; + Sync(); + break; + case 0xC000: + switch (A & 0x03) { + case 0: + if (IRQAutoEnable) { + IRQa = FALSE; + } + IRQCount16 &= 0xFF00; + IRQCount16 |= V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 1: + if (IRQAutoEnable) { + IRQa = TRUE; + } + IRQCount16 &= 0x00FF; + IRQCount16 |= (V << 8); + IRQReload = TRUE; + IRQLatch = V; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 2: + IRQa = (V & 0x01); + irqPA12 = (V & 0x02) >> 1; + IRQAutoEnable = (V & 0x04) >> 2; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 3: + IRQa = (V & 0x01); + X6502_IRQEnd(FCEU_IQEXT); + break; + } + } +} + +static void M359Power(void) { + prg[0] = ~3; + prg[1] = ~2; + prg[2] = ~1; + prg[3] = ~0; + chr[0] = 0; + chr[1] = 1; + chr[2] = 2; + chr[3] = 3; + chr[4] = 4; + chr[5] = 5; + chr[6] = 6; + chr[7] = 7; + reg[0] = 0; + reg[1] = 0x40; + reg[2] = 0; + reg[3] = 0; + IRQReload = IRQa = irqPA12 = IRQAutoEnable = 0; + IRQLatch = IRQCount = IRQCount16 = 0; + Sync(); + FDSSound_Power(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xCFFF, M359Write); +} + +static void M359Reset(void) { + Sync(); + FDSSoundRegReset(); + FDSSound_SC(); +} + +static void M359CPUHook(int a) { + if (!irqPA12) { + if (IRQa && IRQCount16) { + IRQCount16 -= a; + if (IRQCount16 <= 0) + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M359IRQHook(void) { + if (irqPA12) { + if (!IRQCount || IRQReload) { + IRQCount = IRQLatch; + } else { + IRQCount--; + } + if (!IRQCount && IRQa) { + X6502_IRQBegin(FCEU_IQEXT); + } + IRQReload = FALSE; + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper359_Init(CartInfo *info) { + info->Power = M359Power; + info->Reset = M359Reset; + MapIRQHook = M359CPUHook; + GameHBIRQHook = M359IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} + +void Mapper540_Init(CartInfo *info) { + info->Power = M359Power; + MapIRQHook = M359CPUHook; + GameHBIRQHook = M359IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper360.c b/src/mappers/mapper360.c new file mode 100644 index 000000000..59b9453e2 --- /dev/null +++ b/src/mappers/mapper360.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 360 - Bit Corp's 31-in-1 multicart (3150) */ + +#include "mapinc.h" + +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + /* dip 0 and 1 is the same game SMB) */ + if (dipsw < 2) { + setprg32(0x8000, dipsw >> 1); + } else { + setprg16(0x8000, dipsw); + setprg16(0xC000, dipsw); + } + setchr8(dipsw); + setmirror(((dipsw & 0x10) >> 4) ^ 1); +} + +static void M360Power(void) { + dipsw = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0XFFFF, CartBW); +} + +static void M360Reset(void) { + dipsw = (dipsw + 1) & 31; + Sync(); + FCEU_printf("dipsw = %d\n", dipsw); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper360_Init(CartInfo *info) { + info->Reset = M360Reset; + info->Power = M360Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper361.c b/src/mappers/mapper361.c new file mode 100644 index 000000000..bde1dc07e --- /dev/null +++ b/src/mappers/mapper361.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 361 (YY841101C): + * JY-009 + * JY-018 + * JY-019 + * OK-411 +*/ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M361PW(uint16 A, uint16 V) { + setprg8(A, (reg & 0xF0) | (V & 0x0F)); +} + +static void M361CW(uint16 A, uint16 V) { + setchr1(A, ((reg & 0xF0) << 3) | (V & 0x7F)); +} + +static void M361Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static DECLFW(M361Write) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M361Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M361Write); +} + +void Mapper361_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M361PW; + MMC3_cwrap = M361CW; + info->Power = M361Power; + info->Reset = M361Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper362.c b/src/mappers/mapper362.c new file mode 100644 index 000000000..f141b51ee --- /dev/null +++ b/src/mappers/mapper362.c @@ -0,0 +1,92 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 362 - PCB 830506C + * 1995 Super HiK 4-in-1 (JY-005) + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 game; +static uint8 PPUCHRBus; + +static SFORMAT StateRegs[] = { + { &game, 1, "GAME" }, + { &PPUCHRBus, 1, "PPUC" }, + { 0 }, +}; + +static void M362PW(uint16 A, uint16 V) { + uint16 prgBase = (game == 0) ? ((vrc24.chr[PPUCHRBus] & 0x180) >> 3) : 0x40; + + setprg8(A, prgBase | (V & 0x0F)); +} + +static void M362CW(uint16 A, uint16 V) { + uint16 chrBase = (game == 0) ? (vrc24.chr[PPUCHRBus] & 0x180) : 0x200; + uint16 chrMask = (game == 0) ? 0x7F : 0x1FF; + + setchr1(A, chrBase | (V & chrMask)); +} + +static DECLFW(M362CHRWrite) { + VRC24_Write(A, V); + if (A & 0x01) { + /* NOTE: Because the lst higher 2 CHR-ROM bits are repurposed as PRG/CHR outer bank, + an extra PRG sync after a CHR write. */ + VRC24_FixPRG(); + } +} + +static void M362PPUHook(uint32 A) { + uint8 bank = (A & 0x1FFF) >> 10; + if ((game == 0) && (PPUCHRBus != bank) && ((A & 0x3000) != 0x2000)) { + PPUCHRBus = bank; + VRC24_FixCHR(); + VRC24_FixPRG(); + } +} + +static void M362Reset(void) { + if (PRGsize[0] <= (512 * 1024)) { + game = 0; + } else { + game = (game + 1) & 0x01; + } + VRC24_FixCHR(); + VRC24_FixPRG(); +} + +static void M362Power(void) { + PPUCHRBus = game = 0; + VRC24_Power(); + SetWriteHandler(0xB000, 0xEFFF, M362CHRWrite); +} + +void Mapper362_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x01, 0x02, 0, 0); + info->Reset = M362Reset; + info->Power = M362Power; + PPU_hook = M362PPUHook; + VRC24_pwrap = M362PW; + VRC24_cwrap = M362CW; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper364.c b/src/mappers/mapper364.c new file mode 100644 index 000000000..dca449c0c --- /dev/null +++ b/src/mappers/mapper364.c @@ -0,0 +1,62 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M364CW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x20) ? 0x7F : 0xFF; + + setchr1(A, ((reg << 4) & 0x100) | (V & mask)); +} + +static void M364PW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x20) ? 0x0F : 0x1F; + + setprg8(A, ((reg >> 1) & 0x20) | (V & mask)); +} + +static DECLFW(M364Write) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M364Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M364Write); +} + +void Mapper364_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = M364PW; + MMC3_cwrap = M364CW; + info->Power = M364Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper366.c b/src/mappers/mapper366.c new file mode 100644 index 000000000..991f64cd4 --- /dev/null +++ b/src/mappers/mapper366.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Mapper 366 (GN-45): + * K-3131GS + * K-3131SS +*/ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M366PW(uint16 A, uint16 V) { + setprg8(A, reg | (V & 0x0F)); +} + +static void M366CW(uint16 A, uint16 V) { + setchr1(A, (reg << 3) | (V & 0x7F)); +} + +static void M366Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static DECLFW(M366Write) { + CartBW(A, V); + if (!(reg & 0x80)) { + reg = A & 0xF0; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M366Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M366Write); +} + +void Mapper366_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = M366PW; + MMC3_cwrap = M366CW; + info->Power = M366Power; + info->Reset = M366Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper368.c b/src/mappers/mapper368.c new file mode 100644 index 000000000..9c7177e9d --- /dev/null +++ b/src/mappers/mapper368.c @@ -0,0 +1,123 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 357 is used for a 4-in-1 multicart (cartridge ID 4602) from Bit Corp. + * The first game is Bit Corp's hack of the YUNG-08 conversion of Super Mario Brothers 2 (J) named Mr. Mary 2, + * the other three games are UNROM games. + */ + + +#include "mapinc.h" + +static uint8 reg[2]; +static uint8 IRQa; +static uint16 IRQCount; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &IRQCount, 2, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void Sync(void) { + /* + The actual bank number is: + Value Bank# + ------------ + 0 4 + 1 3 + 2 5 + 3 3 + 4 6 + 5 3 + 6 7 + 7 3 */ + uint8 prg = (reg[0] & 0x01) ? 0x03 : (0x04 | ((reg[0] >> 1) & 0x03)); + + setprg8(0x6000, 0x02); + setprg8(0x8000, 0x01); + setprg8(0xA000, 0x00); + setprg8(0xC000, prg); + setprg8(0xE000, 0x08); + setchr8(0); +} + +static DECLFR(M368Read) { + if ((A & 0xF1FF) == 0x4122) { + return (0x8A | (reg[1] & 0x35)); + } + return CartBR(A); +} + +static DECLFW(M368Write) { + switch (A & 0xF1FF) { + case 0x4022: + reg[0] = V; + Sync(); + break; + case 0x4122: + reg[1] = V; + IRQa = V & 0x01; + if (!IRQa) { + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + break; + } +} + +static void M368Power(void) { + reg[0] = reg[1] = 0; + IRQa = IRQCount = 0; + Sync(); + SetReadHandler(0x4020, 0x4FFF, M368Read); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0x4FFF, M368Write); +} + +static void M368Reset(void) { + reg[0] = reg[1] = 0; + IRQa = IRQCount = 0; + Sync(); +} + +static void M368IRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount >= 4096) { + IRQCount -= 4096; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper368_Init(CartInfo *info) { + info->Reset = M368Reset; + info->Power = M368Power; + MapIRQHook = M368IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper369.c b/src/mappers/mapper369.c new file mode 100644 index 000000000..ff72ff4c6 --- /dev/null +++ b/src/mappers/mapper369.c @@ -0,0 +1,165 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 369 (BMC-N49C-300) - Super Mario Bros. Party multicart */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 smb2j; +static uint8 IRQa; +static uint16 IRQCount; + +static SFORMAT StateRegs[] = { + { ®, 1, "MODE" }, + { &smb2j, 1, "SMB2" }, + { &IRQa, 1, "MIQA" }, + { &IRQCount, 2, "MIQC" }, + { 0 } +}; + +static void M369PW(uint16 A, uint16 V) { + uint8 mask = (reg == 0xFF) ? 0x1F : 0x0F; + uint8 base = (reg == 0xFF) ? 0x20 : 0x10; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M369CW(uint16 A, uint16 V) { + uint16 mask = (reg == 0xFF) ? 0xFF : 0x7F; + uint16 base = (reg == 0xFF) ? 0x100 : 0x80; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M369Sync(void) { + switch (reg) { + case 0x00: + case 0x01: /* NROM */ + setprg32(0x8000, reg); + setchr8(reg & 0x03); + break; + case 0x13: /* SMB2J */ + setprg8r(0, 0x6000, 0x0E); + setprg8(0x8000, 0x0C); + setprg8(0xA000, 0x0D); + setprg8(0xC000, 0x08 | (smb2j & 0x03)); + setprg8(0xE000, 0x0F); + setchr8(reg & 0x03); + break; + case 0x37: /* MMC3: 128 KiB CHR */ + case 0xFF: /* MMC3: 256 KiB CHR */ + setprg8r(0x10, 0x6000, 0); + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static DECLFW(M369WriteLo) { + if (A & 0x100) { + reg = V; + M369Sync(); + } +} + +static DECLFW(M369Write) { + switch (A & 0xE000) { + case 0x8000: + if (reg == 0x13) { + IRQa = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + if (A & 0x01) { + mmc3.reg[mmc3.cmd & 0x07] = V; + M369Sync(); + } else { + mmc3.cmd = V; + M369Sync(); + } + break; + case 0xA000: + if (reg == 0x13) { + IRQa = (V & 0x02) != 0; + } + MMC3_CMDWrite(A, V); + break; + case 0xC000: + MMC3_IRQWrite(A, V); + break; + case 0xE000: + if (reg == 0x13) { + smb2j = V; + M369Sync(); + } + MMC3_IRQWrite(A, V); + break; + } +} + +static void SMB2JIRQHook(int a) { + if (reg == 0x13) { + if (IRQa) { + IRQCount += a; + if (IRQCount >= 4096) { + IRQCount -= 4096; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void MMC3IRQHook(void) { + if (reg != 0x13) { + MMC3_IRQHBHook(); + } +} + +static void M369Reset(void) { + reg = smb2j = 0; + IRQa = IRQCount = 0; + MMC3_Reset(); + M369Sync(); +} + +static void StateRestore(int version) { + M369Sync(); +} + +static void M369Power(void) { + reg = smb2j = 0; + IRQa = IRQCount = 0; + MMC3_Power(); + SetWriteHandler(0x4100, 0x4FFF, M369WriteLo); + SetWriteHandler(0x8000, 0xFFFF, M369Write); + M369Sync(); +} + +void Mapper369_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = M369PW; + MMC3_cwrap = M369CW; + info->Power = M369Power; + info->Reset = M369Reset; + MapIRQHook = SMB2JIRQHook; + GameHBIRQHook = MMC3IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper370.c b/src/mappers/mapper370.c new file mode 100644 index 000000000..4dec16211 --- /dev/null +++ b/src/mappers/mapper370.c @@ -0,0 +1,136 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 370 - F600 + * Golden Mario Party II - Around the World (6-in-1 multicart) + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static void M370CW(uint16 A, uint16 V) { + uint16 mask = (reg & 0x04) ? 0xFF : 0x7F; + uint16 base = reg << 7; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M370PW(uint16 A, uint16 V) { + uint16 mask = reg & 0x20 ? 0x0F : 0x1F; + uint16 base = reg << 1; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M370MIR(void) { + if ((reg & 0x07) == 1) { + if (mmc3.cmd & 0x80) { + setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); + } else { + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); + } + } else { + setmirror((mmc3.mirr & 0x01) ^ 0x01); + } +} + +static DECLFR(M370Read) { + return (((dipsw << 7) & 0x80) | (CPU_OPENBUS & 0x7F)); +} + +static DECLFW(M370Write) { + reg = (A & 0xFF); + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); +} + +static DECLFW(M370WriteCMD) { + uint8 oldcmd = mmc3.cmd; + + switch (A & 0xE001) { + case 0x8000: + mmc3.cmd = V; + if ((oldcmd & 0x40) != (mmc3.cmd & 0x40)) { + MMC3_FixPRG(); + } + if ((oldcmd & 0x80) != (mmc3.cmd & 0x80)) { + MMC3_FixCHR(); + MMC3_FixMIR(); + } + break; + case 0x8001: + switch (mmc3.cmd & 0x07) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + mmc3.reg[mmc3.cmd & 0x07] = V; + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + default: + MMC3_CMDWrite(A, V); + break; + } + break; + default: + MMC3_CMDWrite(A, V); + break; + } +} + +static void M370Reset(void) { + reg = 0; + dipsw ^= 1; + FCEU_printf("solderpad=%02x\n", dipsw); + MMC3_Reset(); +} + +static void M370Power(void) { + reg = 0; + dipsw = 1; /* start off with the 6-in-1 menu */ + MMC3_Power(); + SetReadHandler(0x5000, 0x5FFF, M370Read); + SetWriteHandler(0x5000, 0x5FFF, M370Write); + SetWriteHandler(0x8000, 0x9FFF, M370WriteCMD); +} + +void Mapper370_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_FixMIR = M370MIR; + MMC3_cwrap = M370CW; + MMC3_pwrap = M370PW; + info->Power = M370Power; + info->Reset = M370Reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&dipsw, 1, 0, "DPSW"); +} diff --git a/src/mappers/mapper372.c b/src/mappers/mapper372.c new file mode 100644 index 000000000..8b912e270 --- /dev/null +++ b/src/mappers/mapper372.c @@ -0,0 +1,95 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* added 2020-1-28 - */ +/* NES 2.0 Mapper 372 is used for a revision of the Rockman I-VI multicart (PCB ID SFC-12). + * It is INES Mapper 045 but with one bit of outer bank register #2 working as a CHR-ROM/RAM switch. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; +static uint8 cmd; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &cmd, 1, "CMD0" }, + { 0 } +}; + +static void M372CW(uint16 A, uint16 V) { + if (reg[2] & 0x20) { + setchr8r(0x10, 0); + } else { + uint32 mask = 0xFF >> (~reg[2] & 0x0F); + uint32 base = ((reg[2] << 4) & 0xF00) | reg[0]; + + setchr1(A, (base & ~mask) | (V & mask)); + } +} + +static void M372PW(uint16 A, uint16 V) { + uint32 mask = ~reg[3] & 0x3F; + uint32 base = ((reg[2] << 2) & 0x300) | reg[1]; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M372Write) { + if (!(reg[3] & 0x40)) { + reg[cmd] = V; + cmd = (cmd + 1) & 0x03; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M372Reset(void) { + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + MMC3_Reset(); +} + +static void M372Power(void) { + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M372Write); +} + +static void M372Close(void) { + MMC3_Close(); +} + +void Mapper372_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M372CW; + MMC3_pwrap = M372PW; + info->Reset = M372Reset; + info->Power = M372Power; + info->Close = M372Close; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper374.c b/src/mappers/mapper374.c new file mode 100644 index 000000000..c994570a4 --- /dev/null +++ b/src/mappers/mapper374.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 374 + * 1995 Super HiK 4-in-1 - 新系列機器戰警组合卡 (JY-022) + * 1996 Super HiK 4-in-1 - 新系列超級飛狼組合卡 (JY-051) + */ + +#include "mapinc.h" +#include "mmc1.h" + +static uint8 game = 0; + +static SFORMAT StateRegs[] = { + { &game, 1, "GAME" }, + { 0 } +}; + +static void M374PRG(uint16 A, uint16 V) { + setprg16(A, (game << 3) | (V & 0x07)); +} + +static void M374CHR(uint16 A, uint16 V) { + setchr4(A, (game << 5) | (V & 0x1F)); +} + +static void M374Reset(void) { + game = (game + 1) & 0x03; + MMC1_Reset(); +} + +void Mapper374_Init(CartInfo *info) { + MMC1_Init(info, 0, 0); + MMC1_cwrap = M374CHR; + MMC1_pwrap = M374PRG; + info->Reset = M374Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper375.c b/src/mappers/mapper375.c new file mode 100644 index 000000000..727b6e0b5 --- /dev/null +++ b/src/mappers/mapper375.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint32 prg = ((latch.addr >> 4) & 0x40) | ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); + uint32 cpuA14 = latch.addr & 0x01; + uint32 nrom = (latch.addr >> 7) & 0x01; + uint32 unrom = (latch.addr >> 9) & 0x01; + uint32 unrom_like = (latch.addr >> 11) & 0x01; + + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, ((prg & ~cpuA14) & ~(0x07 * unrom_like)) | (unrom_like * latch.data)); + setprg16(0xC000, ((prg | cpuA14) & ~(0x07 * !nrom * !unrom)) | (0x07 * !nrom * unrom)); + + setchr8(0); + setmirror(((latch.addr >> 1) & 1) ^ 1); + if ((latch.addr & 0x80) == 0x80) { + /* CHR-RAM write protect hack, needed for some multicarts */ + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); + } else { + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); + } +} + +static DECLFW(M375Write) { + if (latch.addr & 0x800) { + latch.data = V; + } else { + latch.addr = A; + latch.data = V; + } + Sync(); +} + +static void M375Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M375Write); +} + +void Mapper375_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, FALSE); + info->Power = M375Power; + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper376.c b/src/mappers/mapper376.c new file mode 100644 index 000000000..d123c46a8 --- /dev/null +++ b/src/mappers/mapper376.c @@ -0,0 +1,71 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void M376CW(uint16 A, uint16 V) { + uint16 base = ((reg[1] << 8) & 0x100) | ((reg[0] << 1) & 0x80); + + setchr1(A, base | (V & 0x7F)); +} + +static void M376PW(uint16 A, uint16 V) { + uint16 base = ((reg[1] << 4) & 0x10) | ((reg[0] >> 3) & 0x08) | (reg[0] & 0x07); + + if (reg[0] & 0x80) { + if (reg[0] & 0x20) { + setprg32(0x8000, base >> 1); + } else { + setprg16(0x8000, base); + setprg16(0xC000, base); + } + } else { + setprg8(A, ((base << 1) & ~0x0F) | (V & 0x0F)); + } +} + +static DECLFW(M376Write) { + reg[A & 0x01] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M376Power(void) { + reg[0] = 0; + reg[1] = 0; + MMC3_Power(); + SetWriteHandler(0x7000, 0x7FFF, M376Write); +} + +void Mapper376_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M376PW; + MMC3_cwrap = M376CW; + info->Power = M376Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper377.c b/src/mappers/mapper377.c new file mode 100644 index 000000000..f0bcd06a8 --- /dev/null +++ b/src/mappers/mapper377.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 377 - NES 2.0 Mapper 377 is used for the + * 1998 Super Game 8-in-1 (JY-111) pirate multicart. It works similarly to Mapper 267 except it has an outer 256KiB + * PRG-ROM bank. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M377CW(uint16 A, uint16 V) { + uint16 base = ((reg & 0x20) >> 2) | (reg & 0x06); + + setchr1(A, (base << 6) | (V & 0x7F)); +} + +static void M377PW(uint16 A, uint16 V) { + uint16 base = ((reg & 0x20) >> 2) | (reg & 0x06); + + setprg8(A, (base << 3) | (V & 0x0F)); +} + +static DECLFW(M377Write) { + if (!(reg & 0x80)) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M377Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M377Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M377Write); +} + +void Mapper377_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M377CW; + MMC3_pwrap = M377PW; + info->Reset = M377Reset; + info->Power = M377Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper380.c b/src/mappers/mapper380.c new file mode 100644 index 000000000..9b663b38e --- /dev/null +++ b/src/mappers/mapper380.c @@ -0,0 +1,64 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 380 denotes the 970630C circuit board, + * used on a 512 KiB multicart having 42 to 80,000 listed NROM and UNROM games. */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint32 prg = (latch.addr >> 2) & 0x1F; + uint32 cpuA14 = (latch.addr & 0x01) != 0x01; + uint32 ourom = (latch.addr >> 8) & 0x01; + uint32 nrom = (latch.addr >> 9) & 0x01; + + setprg16(0x8000, prg & ~(cpuA14 * nrom)); + setprg16(0xC000, (prg | (cpuA14 * nrom)) | (0x07 * !nrom) | (0x08 * (iNESCart.submapper == 1) * !nrom * ourom)); + + setchr8(0); + setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); + SetupCartCHRMapping(0, CHRptr[0], 0x2000, !(latch.addr & 0x80)); +} + +static DECLFR(M380Read) { + if ((iNESCart.submapper == 0) && (latch.addr & 0x100)) { + A |= dipsw; + } + return CartBR(A); +} + +static void M380Reset(void) { + dipsw = (dipsw + 1) & 0xF; + Latch_RegReset(); +} + +void Mapper380_Init(CartInfo *info) { + Latch_Init(info, Sync, M380Read, FALSE, FALSE); + info->Reset = M380Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper381.c b/src/mappers/mapper381.c new file mode 100644 index 000000000..00bbf6b9a --- /dev/null +++ b/src/mappers/mapper381.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Map 381 - 2-in-1 High Standard Game (BC-019), reset-based */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reset = 0; + +static void Sync(void) { + setprg16(0x8000, (reset << 4) | ((latch.data & 0x07) << 1) | ((latch.data >> 4) & 0x0F)); + setprg16(0xC000, (reset << 4) | 0x0F); + setchr8(0); +} + +static void M381Reset(void) { + reset++; + Sync(); +} + +void Mapper381_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = M381Reset; + AddExState(&reset, 1, 0, "RST0"); +} diff --git a/src/mappers/mapper382.c b/src/mappers/mapper382.c new file mode 100644 index 000000000..cdabe4688 --- /dev/null +++ b/src/mappers/mapper382.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 382 - denotes the 830928C circuit board, + * used on a 512 KiB 5-in-1 and a 1 MiB 9-in-1 multicart containing + * the BNROM game Journey to the West and Capcom/Konami UNROM games. + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 base; + +static SFORMAT StateRegs[] = { + { &base, 1, "BASE"}, + { 0 } +}; + +static void Sync(void) { + if (!(base & 0x20)) { + base = latch.addr & 0x3F; + } + switch (base & 0x08) { + case 8: + /* bnrom */ + setprg32(0x8000, (base << 2) | (latch.data & 0x03)); + break; + default: + /* unrom */ + setprg16(0x8000, (base << 3) | (latch.data & 0x07)); + setprg16(0xC000, (base << 3) | 0x07); + break; + } + setchr8(0); + setmirror(((base >> 4) & 0x01) ^ 0x01); + /* FCEU_printf("inB[0]:%02x outB[1]:%02x mode:%02x mirr:%02x lock:%02x\n", latch.data, latch.addr, mode, mirr, lock); */ +} + +static void M382Reset(void) { + base = 0; + Latch_RegReset(); +} + +void Mapper382_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Reset = M382Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper383.c b/src/mappers/mapper383.c new file mode 100644 index 000000000..b1ca33193 --- /dev/null +++ b/src/mappers/mapper383.c @@ -0,0 +1,121 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* 晶太 YY840708C PCB + Solely used for the "1995 Soccer 6-in-1 足球小将專輯 (JY-014)" multicart. + MMC3+PAL16L8 combination, resulting in a bizarre mapper that switches banks in part upon *reads*. +*/ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 pal_A15, pal_A16, pal_A1718; + +static SFORMAT StateRegs[] = { + { &pal_A15, 1, "A15_"}, + { &pal_A16, 1, "A16_"}, + { &pal_A1718, 1, "A178"}, + { 0 } +}; + +static void M383PW(uint16 A, uint16 V) { + uint16 base; + uint16 mask; + + switch (pal_A1718) { + case 0x00: + /* "Setting 0 provides a round-about means of dividing the first 128 KiB bank into two 32 KiB and one 64 KiB bank." */ + base = pal_A1718 | pal_A16 | (pal_A16 ? 0x00 : pal_A15); + mask = pal_A16 ? 0x07 : 0x03; + break; + case 0x30: + /* "Setting 3 provides 128 KiB MMC3 banking with the CPU A14 line fed to the MMC3 clone reversed. + This is used for the game Tecmo Cup: Soccer Game (renamed "Tecmo Cup Soccer"), + originally an MMC1 game with the fixed bank at $8000-$BFFF and the switchable bank at $C000-$FFFF, + a configuration that could not be reproduced with an MMC3 alone." */ + base = pal_A1718; + mask = 0x0F; + A ^= 0x4000; + + /* "It is also used for the menu, + which in part executes from PRG-ROM mapped to the CPU $6000-$7FFF address range on the MMC3 clone's fixed + banks alone, as no MMC3 PRG bank register is written to before JMPing to this address range." */ + if (A == 0xA000) { + setprg8(0x6000, base | (V & 0x0B)); + } + break; + default: + /* "Settings 1 and 2 provide normal 128 KiB MMC3 banking." */ + base = pal_A1718; + mask = 0x0F; + break; + } + + setprg8(A, base | (V & mask)); +} + +static void M383CW(uint16 A, uint16 V) { + setchr1(A, (pal_A1718 << 3) | (V & 0x7F)); +} + +static DECLFR(M383Read) { + if (pal_A1718 == 0x00) { /* "PAL PRG pal_A16 is updated with the content of the corresponding MMC3 PRG bank bit by reading from the + respective address range, which in turn will then be applied across the entire ROM address range." */ + pal_A16 = mmc3.reg[0x06 | ((A >> 13) & 0x01)] & 0x08; + MMC3_FixPRG(); + } + return CartBR(A); +} + +static DECLFW(M383Write) { + if (A & 0x0100) { + pal_A15 = (A >> 11) & 0x04; + pal_A1718 = A & 0x30; + MMC3_FixPRG(); + MMC3_FixCHR(); + } + MMC3_Write(A, V); +} + +static void M383Reset(void) { + pal_A15 = 0; + pal_A16 = 0; + pal_A1718 = 0; + MMC3_Reset(); +} + +static void M383Power(void) { + pal_A15 = 0; + pal_A16 = 0; + pal_A1718 = 0; + MMC3_Power(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xBFFF, M383Read); + SetWriteHandler(0x8000, 0xFFFF, M383Write); +} + +void Mapper383_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M383PW; + MMC3_cwrap = M383CW; + info->Power = M383Power; + info->Reset = M383Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper385.c b/src/mappers/mapper385.c new file mode 100644 index 000000000..75265b8e9 --- /dev/null +++ b/src/mappers/mapper385.c @@ -0,0 +1,34 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.addr >> 1); + setprg16(0xc000, latch.addr >> 1); + setmirror((latch.addr & 0x01) ^ 0x01); + setchr8(0); +} + +void Mapper385_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); +} diff --git a/src/mappers/mapper386.c b/src/mappers/mapper386.c new file mode 100644 index 000000000..ab79ee997 --- /dev/null +++ b/src/mappers/mapper386.c @@ -0,0 +1,41 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +static uint32 GetPRGBank(uint32 V) { + return (((jyasic.mode[3] << 3) & 0x40) | ((jyasic.mode[3] << 4) & 0x20) | (V & 0x1F)); +} + +static uint32 GetCHRBank(uint32 V) { + if (jyasic.mode[3] & 0x20) { + return (((jyasic.mode[3] << 7) & 0x600) | (V & 0x1FF)); + } else { + return (((jyasic.mode[3] << 7) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); + } +} + +void Mapper386_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} diff --git a/src/mappers/mapper387.c b/src/mappers/mapper387.c new file mode 100644 index 000000000..c90dede4d --- /dev/null +++ b/src/mappers/mapper387.c @@ -0,0 +1,41 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +static uint32 GetPRGBank(uint32 V) { + return (((jyasic.mode[3] << 2) & 0x20) | ((jyasic.mode[3] << 3) & 0x10) | (V & 0x0F)); +} + +static uint32 GetCHRBank(uint32 V) { + if (jyasic.mode[3] & 0x20) { + return (((jyasic.mode[3] << 7) & 0x600) | (V & 0x1FF)); + } else { + return (((jyasic.mode[3] << 7) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); + } +} + +void Mapper387_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} diff --git a/src/mappers/mapper388.c b/src/mappers/mapper388.c new file mode 100644 index 000000000..62c83e0c0 --- /dev/null +++ b/src/mappers/mapper388.c @@ -0,0 +1,41 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +static uint32 GetPRGBank(uint32 V) { + return (((jyasic.mode[3] << 3) & 0x60) | (V & 0x1F)); +} + +static uint32 GetCHRBank(uint32 V) { + if (jyasic.mode[3] & 0x20) { + return (((jyasic.mode[3] << 8) & 0x200) | (V & 0x1FF)); + } else { + return (((jyasic.mode[3] << 8) & 0x200) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); + } +} + +void Mapper388_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, FALSE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} diff --git a/src/mappers/mapper389.c b/src/mappers/mapper389.c new file mode 100644 index 000000000..4ef1ae603 --- /dev/null +++ b/src/mappers/mapper389.c @@ -0,0 +1,84 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* Mapper 389 - Caltron 9-in-1 multicart */ + +#include "mapinc.h" + +static uint8 regs[3]; + +static SFORMAT StateRegs[] = { + { ®s, 3, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (regs[1] & 0x02) { + /* UNROM-064 */ + setprg16(0x8000, (regs[0] >> 2) | ((regs[2] >> 2) & 0x03)); + setprg16(0xC000, (regs[0] >> 2) | 0x03); + } else { + /* NROM-256 */ + setprg32(0x8000, regs[0] >> 3); + } + setchr8(((regs[1] >> 1) & 0x1C) | (regs[2] & 0x03)); + setmirror((regs[0] & 0x01) ^ 1); +} + +static DECLFW(M389Write) { + switch (A & 0xF000) { + case 0x8000: + regs[0] = (A & 0xFF); + Sync(); + break; + case 0x9000: + regs[1] = (A & 0xFF); + Sync(); + break; + default: + regs[2] = (A & 0x0F); + Sync(); + break; + } +} + +static void M389Reset(void) { + regs[0] = regs[1] = regs[2] = 0; + Sync(); +} + +static void M389Power(void) { + regs[0] = regs[1] = regs[2] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M389Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper389_Init(CartInfo *info) { + info->Power = M389Power; + info->Reset = M389Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper390.c b/src/mappers/mapper390.c new file mode 100644 index 000000000..2d146bbe1 --- /dev/null +++ b/src/mappers/mapper390.c @@ -0,0 +1,90 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 390 - Realtec 8031 */ +/* NOTE: Duplicate of Mapper 236 (CHR-ROM variant */ + +#include "mapinc.h" + +static uint8 reg[2]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + switch (reg[1] & 0x30) { + case 0x00: + case 0x10: /* UNROM */ + setprg16(0x8000, reg[1]); + setprg16(0xC000, reg[1] | 0x07); + break; + case 0x20: /* Maybe unused, NROM-256? */ + setprg32(0x8000, reg[1] >> 1); + break; + case 0x30: /* NROM-128 */ + setprg16(0x8000, reg[1]); + setprg16(0xC000, reg[1]); + break; + } + setchr8(reg[0]); + setmirror(((reg[0] & 0x20) >> 5) ^ 1); +} + +static DECLFR(M390Read) { + uint8 ret = CartBR(A); + if ((reg[1] & 0x30) == 0x10) + ret |= dipsw; + return ret; +} + +static DECLFW(M390Write) { + reg[(A >> 14) & 0x01] = A & 0x3F; + Sync(); +} + +static void M390Power(void) { + reg[0] = 0; + reg[1] = 0; + dipsw = 11; /* hard-coded 150-in-1 menu */ + Sync(); + SetReadHandler(0x8000, 0xFFFF, M390Read); + SetWriteHandler(0x8000, 0xFFFF, M390Write); +} + +static void M390Reset(void) { + dipsw = 11; /* hard-coded 150-in-1 menu */ + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper390_Init(CartInfo *info) { + info->Reset = M390Reset; + info->Power = M390Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper391.c b/src/mappers/mapper391.c new file mode 100644 index 000000000..85daa4d1d --- /dev/null +++ b/src/mappers/mapper391.c @@ -0,0 +1,90 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* BS-110 PCB, previously called NC7000M due to a mix-up. */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void M391PW(uint16 A, uint16 V) { + uint8 mask = (reg[0] & 0x08) ? 0x0F : 0x1F; + uint8 base = (reg[0] << 4) & 0x30; + + if (reg[0] & 0x20) { + if (reg[0] & 0x04) { /* NROM-256 */ + setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~0x03) | 0); + setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & mask) & ~0x03) | 1); + setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~0x03) | 2); + setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] & mask) & ~0x03) | 3); + } else { /* NROM-128 */ + setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~0x01) | 0); + setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & mask) & ~0x01) | 1); + setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~0x01) | 0); + setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] & mask) & ~0x01) | 1); + } + } else { + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static void M391CW(uint16 A, uint16 V) { + uint16 mask = (reg[0] & 0x40) ? 0x7F : 0xFF; + uint16 base = ((reg[0] << 3) & 0x80) | ((reg[1] << 8) & 0x100); + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M391Write) { + if (MMC3_WramIsWritable()) { + if (!(reg[0] & 0x80)) { + reg[0] = V; + reg[1] = ((A >> 8) & 0xFF); + MMC3_FixPRG(); + MMC3_FixCHR(); + } + } +} + +static void M391Reset(void) { + reg[0] = reg[1] = 0; + MMC3_Reset(); +} + +static void M391Power(void) { + reg[0] = reg[1] = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M391Write); +} + +void Mapper391_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M391CW; + MMC3_pwrap = M391PW; + info->Power = M391Power; + info->Reset = M391Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper393.c b/src/mappers/mapper393.c new file mode 100644 index 000000000..305f14200 --- /dev/null +++ b/src/mappers/mapper393.c @@ -0,0 +1,106 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void M393CW(uint16 A, uint16 V) { + if (reg[0] & 0x08) { + setchr8r(0x10, 0); + } else { + setchr1(A, (reg[0] << 8) | (V & 0xFF)); + } +} + +static void M393PW(uint16 A, uint16 V) { + if (reg[0] & 0x20) { + if (reg[0] & 0x10) { + setprg16(0x8000, (reg[0] << 3) | (reg[1] & 0x07)); + setprg16(0xC000, (reg[0] << 3) | 0x07); + } else { + setprg32(0x8000, (reg[0] << 2) | ((mmc3.reg[6] >> 2) & 0x03)); + } + } else { + setprg8(A, (reg[0] << 4) | (V & 0x0F)); + } +} + +static DECLFW(M393Write) { + reg[1] = V; + switch (A & 0xE001) { + case 0x8001: + mmc3.reg[mmc3.cmd & 0x07] = V; + if ((mmc3.cmd & 0x07) < 6) { + MMC3_FixCHR(); + } + MMC3_FixPRG(); + break; + default: + MMC3_Write(A, V); + MMC3_FixPRG(); + break; + } +} + +static DECLFW(M393WriteReg) { + if (MMC3_WramIsWritable()) { + reg[0] = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M393Power(void) { + reg[0] = reg[1] = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M393WriteReg); + SetWriteHandler(0x8000, 0xFFFF, M393Write); +} + +static void M393Reset(void) { + reg[0] = reg[1] = 0; + MMC3_Reset(); +} + +static void M393lose(void) { + MMC3_Close(); +} + +void Mapper393_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = M393PW; + MMC3_cwrap = M393CW; + info->Power = M393Power; + info->Reset = M393Reset; + info->Close = M393lose; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper394.c b/src/mappers/mapper394.c new file mode 100644 index 000000000..7abf9ae40 --- /dev/null +++ b/src/mappers/mapper394.c @@ -0,0 +1,140 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 394: HSK007 circuit board that can simulate J.Y. ASIC, MMC3, and NROM. */ + +#include "mapinc.h" +#include "jyasic.h" +#include "mmc3.h" + +static uint8 reg[4]; + +static uint32 M394_PRGBank_JY(uint32 V) { + uint8 base = ((reg[1] << 5) & 0x020) | ((reg[3] << 1) & 0x010); + + return (base | (V & 0x1F)); +} + +static uint32 M394_CHRBank_JY(uint32 V) { + uint32 base = ((reg[1] << 8) & 0x100) | ((reg[3] << 1) & 0x080); + + return (base | (V & 0x0FF)); +} + +static void M394MMC3PW(uint16 A, uint16 V) { + uint8 mask = (reg[3] & 0x10) ? 0x1F : 0x0F; + uint8 base = ((reg[1] << 5) & 0x020) | ((reg[3] << 1) & 0x010); + + if (reg[1] & 0x08) { + setprg8(A, base | (V & mask)); + } else { + setprg32(0x8000, (base | ((reg[3] << 1) & 0x0F)) >> 2); + } +} + +static void M394MMC3CW(uint16 A, uint16 V) { + uint16 mask = (reg[3] & 0x80) ? 0xFF : 0x7F; + uint16 base = ((reg[3] << 1) & 0x080) | ((reg[1] << 8) & 0x100); + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M394WriteReg) { + uint8 oldMode = reg[1]; + + A &= 3; + reg[A] = V; + if (A == 1) { + if (!(oldMode & 0x10) && (V & 0x10)) { + JYASIC_Power(); + } else if ((oldMode & 0x10) && !(V & 0x10)) { + JYASIC_restoreWriteHandlers(); + MMC3_Power(); + } + } else { + if (reg[1] & 0x10) { + JYASIC_FixPRG(); + JYASIC_FixCHR(); + JYASIC_FixMIR(); + } else { + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } + } +} + +static void M394StateRestore(int version) { + int i; + + JYASIC_restoreWriteHandlers(); + if (reg[1] & 0x10) { + SetWriteHandler(0x5000, 0x5FFF, JYASIC_WriteALU); + SetWriteHandler(0x6000, 0x7fff, CartBW); + SetWriteHandler(0x8000, 0x87FF, JYASIC_WritePRG); /* 8800-8FFF ignored */ + SetWriteHandler(0x9000, 0x97FF, JYASIC_WriteCHRLow); /* 9800-9FFF ignored */ + SetWriteHandler(0xA000, 0xA7FF, JYASIC_WriteCHRHigh); /* A800-AFFF ignored */ + SetWriteHandler(0xB000, 0xB7FF, JYASIC_WriteNT); /* B800-BFFF ignored */ + SetWriteHandler(0xC000, 0xCFFF, JYASIC_WriteIRQ); + SetWriteHandler(0xD000, 0xD7FF, JYASIC_WriteMode); /* D800-DFFF ignored */ + for (i = 0; i < 0x10000; i++) { + JYASIC_cpuWrite[i] = GetWriteHandler(i); + } + SetWriteHandler(0x0000, 0xFFFF, JYASIC_trapCPUWrite); /* Trap all CPU writes for IRQ clocking purposes */ + JYASIC_CPUWriteHandlersSet = 1; + SetReadHandler(0x5000, 0x5FFF, JYASIC_ReadALU_DIP); + SetReadHandler(0x6000, 0xFFFF, CartBR); + JYASIC_FixPRG(); + JYASIC_FixCHR(); + JYASIC_FixMIR(); + } else { + SetWriteHandler(0x8000, 0xBFFF, MMC3_CMDWrite); + SetWriteHandler(0xC000, 0xFFFF, MMC3_IRQWrite); + SetReadHandler(0x8000, 0xFFFF, CartBR); + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M394Power(void) { + reg[0] = 0x00; + reg[1] = 0x0F; /* start in MMC3 mode */ + reg[2] = 0x00; + reg[3] = 0x10; + MMC3_Power(); + SetWriteHandler(0x5000, 0x5FFF, M394WriteReg); +} + +void Mapper394_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = M394_PRGBank_JY; + JYASIC_GetCHRBank = M394_CHRBank_JY; + + MMC3_Init(info, 0, 0); + MMC3_pwrap = M394MMC3PW; + MMC3_cwrap = M394MMC3CW; + + info->Reset = M394Power; + info->Power = M394Power; + + AddExState(reg, 4, 0, "HSK"); + GameStateRestore = M394StateRestore; +} diff --git a/src/mappers/mapper395.c b/src/mappers/mapper395.c new file mode 100644 index 000000000..dadc03204 --- /dev/null +++ b/src/mappers/mapper395.c @@ -0,0 +1,78 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 395 - Realtec 8210 + * Super Card 12-in-1 (SPC002) + * Super Card 13-in-1 (SPC003) + * Super Card 14-in-1 (King006) + * Super Card 14-in-1 (King007) + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void M395CW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x40) ? 0x7F : 0xFF; + uint16 base = ((reg[0] << 4) & 0x300) | ((reg[1] << 5) & 0x400) | ((reg[1] << 3) & 0x80); + + setchr1(A, base | (V & mask)); +} + +static void M395PW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x08) ? 0x0F : 0x1F; + uint16 base = ((reg[0] << 4) & 0x80) | ((reg[0] << 1) & 0x60) | ((reg[1] << 4) & 0x10); + + setprg8(A, base | (V & mask)); +} + +static DECLFW(M395Write) { + if (!(reg[1] & 0x80)) { + reg[(A >> 4) & 0x01] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M395Reset(void) { + reg[0] = reg[1] = 0; + MMC3_Reset(); +} + +static void M395Power(void) { + reg[0] = reg[1] = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M395Write); +} + +void Mapper395_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M395CW; + MMC3_pwrap = M395PW; + info->Power = M395Power; + info->Reset = M395Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper396.c b/src/mappers/mapper396.c new file mode 100644 index 000000000..0d6e063a6 --- /dev/null +++ b/src/mappers/mapper396.c @@ -0,0 +1,56 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 396 - BMC-830752C + * 1995 Super 8-in-1 (JY-050 rev0) + * Super 8-in-1 Gold Card Series (JY-085) + * Super 8-in-1 Gold Card Series (JY-086) + * 2-in-1 (GN-51) + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if ((latch.addr & 0x6000) == 0x2000) { + reg = latch.data; + } + setprg16(0x8000, (reg << 3) | (latch.data & 0x07)); + setprg16(0xC000, (reg << 3) | 0x07); + setchr8(0); + setmirror((reg & 0x60) ? MI_H : MI_V); +} + +static void M396Reset(void) { + reg = 0; + Latch_RegReset(); +} + +void Mapper396_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = M396Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper397.c b/src/mappers/mapper397.c new file mode 100644 index 000000000..60dd580a9 --- /dev/null +++ b/src/mappers/mapper397.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" +#include "fdssound.h" + +static uint32 GetPRGBank(uint32 V) { + return (((jyasic.mode[3] << 4) & ~0x1F) | (V & 0x1F)); +} + +static uint32 GetCHRBank(uint32 V) { + return ((jyasic.mode[3] << 7) | (V & 0x07F)); +} + +static void M397Power(void) { + JYASIC_Power(); + FDSSound_Power(); +} + +void Mapper397_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; + info->Power = M397Power; +} diff --git a/src/mappers/mapper398.c b/src/mappers/mapper398.c new file mode 100644 index 000000000..808325954 --- /dev/null +++ b/src/mappers/mapper398.c @@ -0,0 +1,92 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 398 - PCB YY840820C + * 1995 Super HiK 5-in-1 - 新系列米奇老鼠組合卡 (JY-048) + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 reg; +static uint8 PPUCHRBus; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { &PPUCHRBus, 1, "PPUC" }, + { 0 }, +}; + +static void M398PW(uint16 A, uint16 V) { + if (reg & 0x80) { + /* GNROM-like */ + setprg32(0x8000, ((reg >> 5) & 0x06) | ((vrc24.chr[PPUCHRBus] >> 2) & 0x01)); + } else { + setprg8(A, V & 0x0F); + } +} + +static void M398CW(uint16 A, uint16 V) { + if (reg & 0x80) { + /* GNROM-like */ + setchr8(0x40 | ((reg >> 3) & 0x08) | (vrc24.chr[PPUCHRBus] & 0x07)); + } else { + setchr1(A, V & 0x1FF); + } +} + +static DECLFW(M398WriteLatch) { + reg = A & 0xFF; + VRC24_FixPRG(); + VRC24_FixCHR(); + VRC24_Write(A, V); +} + +static void M398PPUHook(uint32 A) { + uint8 bank = (A & 0x1FFF) >> 10; + if ((PPUCHRBus != bank) && ((A & 0x3000) != 0x2000)) { + PPUCHRBus = bank; + VRC24_FixPRG(); + VRC24_FixCHR(); + } +} + +static void M398Reset(void) { + reg = 0xC0; + VRC24_FixPRG(); + VRC24_FixCHR(); +} + +static void M398Power(void) { + PPUCHRBus = 0; + reg = 0xC0; + VRC24_Power(); + SetWriteHandler(0x8000, 0xFFFF, M398WriteLatch); +} + +void Mapper398_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x01, 0x02, 0, 1); + info->Reset = M398Reset; + info->Power = M398Power; + PPU_hook = M398PPUHook; + VRC24_pwrap = M398PW; + VRC24_cwrap = M398CW; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper399.c b/src/mappers/mapper399.c new file mode 100644 index 000000000..84ad92a23 --- /dev/null +++ b/src/mappers/mapper399.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 prg[2]; +static uint8 chr[2]; + +static SFORMAT StateRegs[] = { + { prg, 2, "PREG" }, + { chr, 2, "CREG" }, + { 0 } +}; + +static void M399PRG(void) { + if (iNESCart.submapper == 1) { + setprg8(0x6000, 0xFE); + setprg8(0x8000, prg[0] << 1 | 0); + setprg8(0xA000, prg[0] << 1 | 1); + setprg8(0xC000, prg[1]); + setprg8(0xE000, 0xFF); + } else { + setprg8(0x8000, 0x00); + setprg8(0xA000, prg[0]); + setprg8(0xC000, prg[1]); + setprg8(0xE000, 0xFF); + } +} + +static void M399CHR(void) { + setchr4(0x0000, chr[0]); + setchr4(0x1000, chr[1]); +} + +static DECLFW(M399WriteReg) { + if (A & 0x01) { + prg[V >> 7] = V; + MMC3_FixPRG(); + } else { + chr[V >> 7] = V; + MMC3_FixCHR(); + } +} + +static DECLFW(M399Write1) { + MMC3_Write(0x2000 + A, V); +} + +static void M399Power(void) { + prg[0] = chr[0] = 0; + prg[1] = chr[1] = 1; + MMC3_Power(); + if (iNESCart.submapper == 1) { + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x8000, 0xDFFF, M399Write1); + SetWriteHandler(0xE000, 0xFFFF, M399WriteReg); + } else { + SetWriteHandler(0x8000, 0x9FFF, M399WriteReg); + } +} + +void Mapper399_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_FixPRG = M399PRG; + MMC3_FixCHR = M399CHR; + info->Power = M399Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper400.c b/src/mappers/mapper400.c new file mode 100644 index 000000000..5d091aa4b --- /dev/null +++ b/src/mappers/mapper400.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 400 is used for retroUSB's 8-BIT XMAS 2017 homebrew cartridge. + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg; +static uint8 led; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, (reg & ~0x07) | (latch.data & 0x07)); + setprg16(0xC000, (reg & ~0x07) | 0x07); + setchr8(0); + if (reg != 0x80) { + setmirror(((reg >> 5) & 0x01) ^ 0x01); + } +} + +static DECLFW(M400WriteReg) { + reg = V; + Sync(); +} + +static DECLFW(M400WriteLED) { + led = V; +} + +static void M400Reset(void) { + reg = 0x80; + Latch_RegReset(); +} + +static void M400Power(void) { + reg = 0x80; + Latch_Power(); + SetWriteHandler(0x7800, 0x7FFF, M400WriteReg); + SetWriteHandler(0x8000, 0xBFFF, M400WriteLED); +} + +void Mapper400_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Power = M400Power; + info->Reset = M400Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper401.c b/src/mappers/mapper401.c new file mode 100644 index 000000000..ef9898ba2 --- /dev/null +++ b/src/mappers/mapper401.c @@ -0,0 +1,97 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 - Mapper 401 (reference from NewRisingSun) + * Super 19-in-1 (VIP19) (crc 0x2F497313) + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; +static uint8 cmd; +static uint8 dipsw = 0; + +static void M401CW(uint16 A, uint16 V) { + uint32 mask = (0xFF >> (~reg[2] & 0xF)); + uint32 bank = (reg[0] | ((reg[2] << 4) & 0xF00)); + + setchr1(A, bank | (V & mask)); +} + +static void M401PW(uint16 A, uint16 V) { + uint32 mask = (~reg[3] & 0x1F); + uint32 bank = (reg[1] & 0x1F) | (reg[2] & 0x80) | + ((dipsw & 2) ? (reg[2] & 0x20) : ((reg[1] >> 1) & 0x20)) | + ((dipsw & 4) ? (reg[2] & 0x40) : ((reg[1] << 1) & 0x40)); + setprg8(A, bank | (V & mask)); +} + +static DECLFR(M401Read) { + if ((dipsw & 0x01) && (reg[1] & 0x80)) { + return CPU_OPENBUS; + } + return CartBR(A); +} + +static DECLFW(M401Write) { + /* FCEU_printf("Wr A:%04x V:%02x index:%d\n", A, V, cmd); */ + if (!(reg[3] & 0x40)) { + reg[cmd] = V; + cmd = (cmd + 1) & 0x03; + MMC3_FixPRG(); + MMC3_FixCHR(); + } + CartBW(A, V); +} + +static void M401Reset(void) { + dipsw = (dipsw + 1) & 7; + FCEU_printf("dipsw = %d\n", dipsw); + reg[0] = 0x00; + reg[1] = 0x00; + reg[2] = 0x0F; + reg[3] = 0x00; + cmd = 0x00; + MMC3_Reset(); +} + +static void M401Power(void) { + dipsw = 7; + reg[0] = 0x00; + reg[1] = 0x00; + reg[2] = 0x0F; + reg[3] = 0x00; + cmd = 0x00; + MMC3_Power(); + SetReadHandler(0x8000, 0xFFFF, M401Read); + SetWriteHandler(0x6000, 0x7FFF, M401Write); +} + +void Mapper401_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_cwrap = M401CW; + MMC3_pwrap = M401PW; + info->Power = M401Power; + info->Reset = M401Reset; + AddExState(reg, 4, 0, "EXPR"); + AddExState(&cmd, 1, 0, "CMD0"); + AddExState(&dipsw, 1, 0, "DPSW"); +} diff --git a/src/mappers/mapper402.c b/src/mappers/mapper402.c new file mode 100644 index 000000000..d645670ac --- /dev/null +++ b/src/mappers/mapper402.c @@ -0,0 +1,47 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 0x800) { + setprg8(0x6000, ((latch.addr & 0x1F) << 1) | 3); + } + if ((latch.addr & 0x40)) { + setprg16(0x8000, latch.addr & 0x1F); + setprg16(0xC000, latch.addr & 0x1F); + } else { + setprg32(0x8000, (latch.addr & 0x1F) >> 1); + } + if ((latch.addr & 0x400) == 0) { + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); + } else { + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); + } + setchr8(0); + setmirror(((latch.addr >> 7) & 0x01) ^ 0x01); +} + +void Mapper402_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper403.c b/src/mappers/mapper403.c new file mode 100644 index 000000000..5afff3ba7 --- /dev/null +++ b/src/mappers/mapper403.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 403 denotes the 89433 circuit board with up to 1 MiB PRG-ROM and 32 KiB of CHR-RAM, bankable with 8 + * KiB granularity. + * + * Tetris Family - 玩家 19-in-1 智瑟實典 (NO-1683) + * Sachen Superpack (versions A-C) + */ + +#include "mapinc.h" + +static uint8 reg[3]; + +static SFORMAT StateRegs[] = { + { reg, 3, "REGS" }, + { 0 } +}; + +static void Sync(void) { + if (reg[2] & 0x01) { /* NROM-128 */ + setprg16(0x8000, reg[0] >> 1); + setprg16(0xC000, reg[0] >> 1); + } else { /* NROM-256 */ + setprg32(0x8000, reg[0] >> 2); + } + setchr8(reg[1]); + setmirror(((reg[2] >> 4) & 0x01) ^ 0x01); +} + +static DECLFW(M403Write4) { + if (A & 0x100) { + reg[A & 0x03] = V; + Sync(); + } +} + +static DECLFW(M403Write8) { + if (reg[2] & 0x04) { + reg[1] = V; + Sync(); + } +} + +static void M403Reset(void) { + reg[0] = reg[1] = reg[2] = 0; + Sync(); +} + +static void M403Power(void) { + reg[0] = reg[1] = reg[2] = 0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); /* For TetrisA (Tetris Family 19-in-1 NO 1683) */ + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, M403Write4); + SetWriteHandler(0x8000, 0xFFFF, M403Write8); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper403_Init(CartInfo *info) { + info->Reset = M403Reset; + info->Power = M403Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper404.c b/src/mappers/mapper404.c new file mode 100644 index 000000000..1695cb3d7 --- /dev/null +++ b/src/mappers/mapper404.c @@ -0,0 +1,65 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 404 - JY012005 + * 1998 Super HiK 8-in-1 (JY-021B) + */ + +#include "mapinc.h" +#include "mmc1.h" + +static uint8 reg; + +static void M404PW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x40) ? 0x07 : 0x0F; + setprg16(A, ((reg << 3) & ~mask) | (V & mask)); +} + +static void M404CW(uint16 A, uint16 V) { + setchr4(A, (reg << 5) | (V & 0x1F)); +} + +static DECLFW(M404Write) { + if (!(reg & 0x80)) { + reg = V; + MMC1_FixPRG(); + MMC1_FixCHR(); + } +} + +static void M404Reset(void) { + reg = 0; + MMC1_Reset(); +} + +static void M404Power(void) { + reg = 0; + MMC1_Power(); + SetWriteHandler(0x6000, 0x7FFF, M404Write); +} + +void Mapper404_Init(CartInfo *info) { + MMC1_Init(info, 0, 0); + info->Power = M404Power; + info->Reset = M404Reset; + MMC1_cwrap = M404CW; + MMC1_pwrap = M404PW; + AddExState(®, 1, 0, "BANK"); +} diff --git a/src/mappers/mapper406.c b/src/mappers/mapper406.c new file mode 100644 index 000000000..d1bf6810f --- /dev/null +++ b/src/mappers/mapper406.c @@ -0,0 +1,87 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 406 */ +/* Uses flashrom to save high scores. */ + +#include "mapinc.h" +#include "mmc3.h" +#include "flashrom.h" + +static uint8 *FLASHROM_data = NULL; +static uint32 FLASHROM_size = 0; + +static void M406PW(uint16 A, uint16 V) { + setprg8r(0x10, A, V & 0x3F); +} + +static DECLFR(M406Read) { + return FlashROM_Read(A); +} + +static DECLFW(M406Write) { + FlashROM_Write(A, V); + if (iNESCart.submapper == 0) { + A = (A & 0xFFFC) | ((A << 1) & 2) | ((A >> 1) & 1); + } else if ((A <= 0x9000) || (A >= 0xE000)) { + A = A ^ 0x6000; + } + MMC3_Write(A, V); +} + +static void M406Power(void) { + MMC3_Power(); + SetReadHandler(0x8000, 0xFFFF, M406Read); + SetWriteHandler(0x8000, 0xFFFF, M406Write); +} + +static void M406Close(void) { + MMC3_Close(); + if (FLASHROM_data) { + FCEU_free(FLASHROM_data); + } + FLASHROM_data = NULL; +} + +void Mapper406_Init(CartInfo *info) { + uint32 w, r, id; + + MMC3_Init(info, 0, 0); + info->Power = M406Power; + info->Close = M406Close; + MMC3_pwrap = M406PW; + MapIRQHook = FlashROM_CPUCyle; + + info->battery = 1; + FLASHROM_size = PRGsize[0]; + FLASHROM_data = (uint8 *)FCEU_gmalloc(FLASHROM_size); + info->SaveGame[0] = FLASHROM_data; + info->SaveGameLen[0] = FLASHROM_size; + AddExState(FLASHROM_data, FLASHROM_size, 0, "FROM"); + /* copy PRG ROM into FLASHROM_data, use it instead of PRG ROM */ + for (w = 0, r = 0; w < FLASHROM_size; w++) { + FLASHROM_data[w] = PRGptr[0][r]; + ++r; + } + SetupCartPRGMapping(0x10, FLASHROM_data, FLASHROM_size, 0); + + id = (info->submapper == 0) ? 0xC2 : 0x01; + FlashROM_Init(FLASHROM_data, FLASHROM_size, id, 0xA4, 65536, 0x5555, 0x02AAA); +} diff --git a/src/mappers/mapper409.c b/src/mappers/mapper409.c new file mode 100644 index 000000000..9729dfa54 --- /dev/null +++ b/src/mappers/mapper409.c @@ -0,0 +1,33 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg16(0x8000, latch.addr); + setprg16(0xC000, ~0); + setchr8(0); +} + +void Mapper409_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper410.c b/src/mappers/mapper410.c new file mode 100644 index 000000000..67094a78b --- /dev/null +++ b/src/mappers/mapper410.c @@ -0,0 +1,96 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 410 is a variant of mapper 45 where the + * ASIC's PRG A21/CHR A20 output (set by bit 6 of the third write to $6000) + * selects between regularly-banked CHR-ROM (=0) and 8 KiB of unbanked CHR-RAM (=1). + * It is used solely for the Super 8-in-1 - 98格鬥天王+熱血 (JY-302) multicart. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; +static uint8 cmd; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &cmd, 1, "CMD0" }, + { 0 } +}; + +static void M410PW(uint16 A, uint16 V) { + uint32 mask = ~reg[3] & 0x3F; + uint32 base = ((reg[2] << 2) & 0x300) | reg[1]; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M410CW(uint16 A, uint16 V) { + if (!(reg[2] & 0x40)) { + uint32 mask = 0xFF >> (~reg[2] & 0x0F); + uint32 base = ((reg[2] << 4) & 0xF00) | reg[0]; + + setchr1(A, (base & ~mask) | (V & mask)); + } else { + setchr8r(0x10, 0); + } +} + +static DECLFW(M410Write) { + if (!(reg[3] & 0x40)) { + reg[cmd] = V; + cmd = (cmd + 1) & 0x03; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M410Close(void) { + MMC3_Close(); +} + +static void M410Reset(void) { + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + MMC3_Reset(); +} + +static void M410Power(void) { + MMC3_Power(); + reg[0] = reg[1] = reg[3] = cmd = 0; + reg[2] = 0x0F; + SetWriteHandler(0x6000, 0x7FFF, M410Write); +} + +void Mapper410_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M410CW; + MMC3_pwrap = M410PW; + info->Reset = M410Reset; + info->Power = M410Power; + info->Close = M410Close; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAM = (uint8 *)FCEU_gmalloc(8192); + SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); + AddExState(CHRRAM, 8192, 0, "CRAM"); +} \ No newline at end of file diff --git a/src/mappers/mapper411.c b/src/mappers/mapper411.c new file mode 100644 index 000000000..b60ff8ad7 --- /dev/null +++ b/src/mappers/mapper411.c @@ -0,0 +1,89 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Mapper 411 - A88S-1 + * 1997 Super 7-in-1 (JY-201) + * 1997 Super 6-in-1 (JY-202) + * 1997 Super 7-in-1 (JY-203) + * 1997 龍珠武鬥會 7-in-1 (JY-204) + * 1997 Super 7-in-1 (JY-205) + * 1997 Super 7-in-1 (JY-206) + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; +static uint8 dipsw; + +static void M411CW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x02) ? 0xFF : 0x7F; + uint16 base = ((reg[0] << 4) & 0x100) | ((reg[1] << 5) & 0x80); + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M411PW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x02) ? 0x1F : 0x0F; + uint16 base = ((reg[1] >> 1) & 0x40) | ((reg[1] << 1) & 0x10); + + /* NROM Mode */ + if ((reg[0] & 0x40) && !(reg[0] & 0x20)) { /* $5xx0 bit 5 check required for JY-212 */ + uint16 bank = (base >> 1) | (reg[0] & 0x05) | ((reg[0] >> 2) & 0x02); + if (reg[0] & 0x02) { /* NROM-256 */ + setprg32(0x8000, bank >> 1); + } else { /* NROM-128 */ + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { /* MMC3 */ + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static DECLFW(M411Write) { + reg[A & 0x01] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M411Reset(void) { + reg[0] = 0x80; + reg[1] = 0x82; + MMC3_Reset(); +} + +static void M411Power(void) { + reg[0] = 0x80; + reg[1] = 0x82; + MMC3_Power(); + SetWriteHandler(0x5800, 0x5FFF, M411Write); +} + +void Mapper411_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M411PW; + MMC3_cwrap = M411CW; + info->Power = M411Power; + info->Reset = M411Reset; + AddExState(reg, 2, 0, "EXPR"); +} diff --git a/src/mappers/mapper412.c b/src/mappers/mapper412.c new file mode 100644 index 000000000..75040dfe9 --- /dev/null +++ b/src/mappers/mapper412.c @@ -0,0 +1,93 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 412 is a variant of mapper 45 where the + * ASIC's PRG A21/CHR A20 output (set by bit 6 of the third write to $6000) + * selects between regularly-banked CHR-ROM (=0) and 8 KiB of unbanked CHR-RAM (=1). + * It is used solely for the Super 8-in-1 - 98格鬥天王+熱血 (JY-302) multicart. + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; + +static void M412CW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x20) ? 0x7F : 0xFF; + uint16 base = ((reg[1] << 5) & 0x100) | (reg[1] & 0x80); + uint16 bank = reg[0] >> 2; + + if (reg[2] & 0x02) { + setchr8(bank); + } else { + setchr1(A, (base & ~mask) | (V & mask)); + } +} + +static void M412PW(uint16 A, uint16 V) { + uint16 mask = 0x3F & ~(((reg[1] << 4) & 0x20) | (reg[1] & 0x10)); + uint16 base = ((reg[1] << 3) & 0x20) | ((reg[1] >> 2) & 0x10); + uint16 bank = reg[2] >> 3; + + if (reg[2] & 0x02) { + if (reg[2] & 0x04) { + setprg32(0x8000, bank >> 1); + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static DECLFW(M412Write) { + if (MMC3_WramIsWritable()) { + CartBW(A, V); + if (!(reg[1] & 0x01)) { + reg[A & 0x03] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } + } +} + +static void M412Reset(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Reset(); + mmc3.wram = 0x80; +} + +static void M412Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Power(); + mmc3.wram = 0x80; + SetWriteHandler(0x6000, 0x7FFF, M412Write); +} + +void Mapper412_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M412CW; + MMC3_pwrap = M412PW; + info->Reset = M412Reset; + info->Power = M412Power; + AddExState(reg, 4, 0, "EXPR"); +} diff --git a/src/mappers/mapper413.c b/src/mappers/mapper413.c new file mode 100644 index 000000000..c9ec72832 --- /dev/null +++ b/src/mappers/mapper413.c @@ -0,0 +1,147 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * Copyright (C) 2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[4]; +static uint8 IRQCount; +static uint8 IRQReload; +static uint8 IRQa; +static uint8 serialControl; +static uint32 serialAddress; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &IRQCount, 1, "IRQC" }, + { &IRQReload, 1, "IRQR" }, + { &IRQa, 1, "IRQA" }, + { &serialAddress, 4, "ADDR" }, + { &serialControl, 1, "CTRL" }, + { 0 } +}; + +static void Sync(void) { + setprg4(0x5000, 0x01); + setprg8(0x6000, reg[0]); + + setprg8(0x8000, reg[1]); + setprg8(0xA000, reg[2]); + setprg4(0xD000, 0x07); + setprg8(0xE000, 0x04); + + setchr4(0x0000, reg[3]); + setchr4(0x1000, ~0x02); +} + +static uint64 lreset; +static uint32 laddr; +static DECLFR(M413ReadPCM) { + uint8 ret = CPU_OPENBUS; + if ((A == laddr) && ((timestampbase + timestamp) < (lreset + 4))) { + return ret; + } + if (serialControl & 0x02) { + ret = MISC_ROM_DATA[serialAddress++ & (MISC_ROM_SIZE - 1)]; + } else { + ret = MISC_ROM_DATA[serialAddress & (MISC_ROM_SIZE - 1)]; + } + laddr = A; + lreset = timestampbase + timestamp; + return ret; +} + +static DECLFW(M413Write) { + switch (A & 0xF000) { + case 0x8000: + IRQReload = V; + break; + case 0x9000: + IRQCount = 0; + break; + case 0xA000: + case 0xB000: + IRQa = (A & 0x1000) != 0; + if (!IRQa) { + X6502_IRQEnd(FCEU_IQEXT); + } + break; + case 0xC000: + serialAddress = (serialAddress << 1) | (V >> 7); + break; + case 0xD000: + serialControl = V; + break; + case 0xE000: + case 0xF000: + reg[V >> 6] = V & 0x3F; + Sync(); + break; + } +} + +static void M413Power(void) { + serialAddress = 0; + serialControl = 0; + + IRQCount = 0; + IRQReload = 0; + IRQa = 0; + + reg[0] = 0; + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + + laddr = 0; + lreset = 0; + + Sync(); + + SetReadHandler(0x4800, 0x4FFF, M413ReadPCM); + SetReadHandler(0xC000, 0xCFFF, M413ReadPCM); + SetReadHandler(0x5000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xBFFF, CartBR); + SetReadHandler(0xD000, 0xFFFF, CartBR); + + SetWriteHandler(0x8000, 0xFFFF, M413Write); +} + +static void M413IRQHook(void) { + if (IRQCount == 0) { + IRQCount = IRQReload; + } else { + IRQCount--; + } + if ((IRQCount == 0) && IRQa) { + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper413_Init(CartInfo *info) { + info->Power = M413Power; + GameHBIRQHook = M413IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/mappers/mapper414.c b/src/mappers/mapper414.c new file mode 100644 index 000000000..8064142e5 --- /dev/null +++ b/src/mappers/mapper414.c @@ -0,0 +1,60 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + if (latch.addr & 0x2000) { /* NROM-256 */ + setprg32(0x8000, latch.addr >> 2); + } else { /* NROM-128 */ + setprg16(0x8000, latch.addr >> 1); + setprg16(0xC000, latch.addr >> 1); + } + setchr8(latch.data); + setmirror((latch.addr & 0x01) ^ 0x01); +} + +static DECLFR(M414Read) { + if ((A >= 0xC000) && !(latch.addr & 0x100) && (latch.addr & (dipsw << 4))) { + return CPU_OPENBUS; + } + return CartBR(A); +} + +static void M414Reset(void) { + dipsw++; + dipsw &= 0x0F; + Sync(); +} + +void Mapper414_Init(CartInfo *info) { + Latch_Init(info, Sync, M414Read, FALSE, TRUE); + info->Reset = M414Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper415.c b/src/mappers/mapper415.c new file mode 100644 index 000000000..c6a4fde57 --- /dev/null +++ b/src/mappers/mapper415.c @@ -0,0 +1,40 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg8(0x6000, latch.data); + setprg32(0x8000, ~0); + setchr8(0); + setmirror(((latch.data >> 4) & 0x01) ^ 0x01); +} + +static void M415Power(void) { + Latch_Power(); + SetReadHandler(0x6000, 0x7FFF, CartBR); +} + +void Mapper415_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M415Power; +} diff --git a/src/mappers/mapper416.c b/src/mappers/mapper416.c new file mode 100644 index 000000000..ed9ccde82 --- /dev/null +++ b/src/mappers/mapper416.c @@ -0,0 +1,110 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 smb2j_reg; +static uint8 IRQa; +static uint16 IRQCount; + +static SFORMAT StateRegs[] = { + { &smb2j_reg, 1, "SMB2" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + uint8 prg = ((latch.data >> 1) & 0x04) | ((latch.data >> 6) & 0x02) | ((latch.data >> 5) & 0x01); + + if (latch.addr >= 0xA000) { + /* latch should not respond to $A000-$FFFF */ + return; + } + + setprg8(0x6000, 0x07); + if (latch.data & 0x08) { + switch (latch.data & 0xC0) { + case 0x00: + setprg8(0x8000, prg << 1); + setprg8(0xA000, prg << 1); + setprg8(0xC000, prg << 1); + setprg8(0xE000, prg << 1); + break; + case 0x40: + setprg16(0x8000, prg); + setprg16(0xC000, prg); + break; + case 0x80: + case 0xC0: + setprg32(0x8000, prg >> 1); + break; + } + } else { + setprg8(0x8000, 0x00); + setprg8(0xA000, 0x01); + setprg8(0xC000, smb2j_reg); + setprg8(0xE000, 0x03); + } + setchr8((latch.data >> 1) & 0x03); + setmirror(((latch.data >> 2) & 0x01) ^ 0x01); +} + +static DECLFW(M416WriteReg) { + if ((A & 0x20) && !(A & 0x40)) { + if (A & 0x100) { + IRQa = V & 0x01; + if (!IRQa) { + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + } else { + smb2j_reg = (V & ~0x07) | ((V << 2) & 0x04) | ((V >> 1) & 0x03); + Sync(); + } + } +} + +static void M416Power(void) { + smb2j_reg = IRQa = IRQCount = 0; + Latch_Power(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x4020, 0x5FFF, M416WriteReg); +} + +static void M416IRQHook(int a) { + if (IRQa & 0x01) { + IRQCount += a; + if (IRQCount & 0x1000) { + X6502_IRQBegin(FCEU_IQEXT); + } else { + X6502_IRQEnd(FCEU_IQEXT); + } + } +} + +void Mapper416_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M416Power; + MapIRQHook = M416IRQHook; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper417.c b/src/mappers/mapper417.c new file mode 100644 index 000000000..b5667b895 --- /dev/null +++ b/src/mappers/mapper417.c @@ -0,0 +1,115 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[4]; +static uint8 chr[8]; +static uint8 nt[4]; +static uint8 IRQa; +static uint16 IRQCount; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { nt, 4, "NREG" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, ~0); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + setmirrorw(nt[0] & 0x01, nt[1] & 0x01, nt[2] & 0x01, nt[3] & 0x01); +} + +static DECLFW(M417Write) { + switch ((A >> 4) & 0x07) { + case 0: + prg[A & 0x03] = V; + Sync(); + break; + case 1: + chr[0 | (A & 0x03)] = V; + if (iNESCart.submapper == 1) nt[A & 0x03] = V >> 7; + Sync(); + break; + case 2: + chr[4 | (A & 0x03)] = V; + Sync(); + break; + break; + case 3: + IRQCount = 0; + IRQa = TRUE; + break; + case 4: + IRQa = FALSE; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 5: + if (iNESCart.submapper == 0) nt[A & 0x03] = V & 0x01; + Sync(); + break; + } +} + +static void M417Power(void) { + memset(prg, 0, sizeof(prg)); + memset(chr, 0, sizeof(chr)); + memset(nt, 0, sizeof(nt)); + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M417Write); +} + +static void M417IRQHook(int a) { + uint16 mask = (iNESCart.submapper == 1) ? 0x1000 : 0x400; + + IRQCount += a; + if (IRQa && (IRQCount > mask)) { + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper417_Init(CartInfo *info) { + info->Power = M417Power; + MapIRQHook = M417IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper418.c b/src/mappers/mapper418.c new file mode 100644 index 000000000..cb757380f --- /dev/null +++ b/src/mappers/mapper418.c @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 418 denotes the 820106-C/821007C circuit boards for the LH42 bootleg cartridge versions of Highway Star. */ + +#include "mapinc.h" +#include "n118.h" + +static void M418FixCHR(void) { + setchr2(0x0000, (n118.reg[0] & 0x3F) >> 1); + setchr2(0x0800, (n118.reg[1] & 0x3F) >> 1); + setchr1(0x1000, n118.reg[2] & 0x3F); + setchr1(0x1400, n118.reg[3] & 0x3F); + setchr1(0x1800, n118.reg[4] & 0x3F); + setchr1(0x1C00, n118.reg[5] & 0x3F); + setmirror((n118.reg[5] & 0x01) ^ 0x01); +} + +void Mapper418_Init(CartInfo *info) { + N118_Init(info, 0, 0); + N118_FixCHR = M418FixCHR; +} diff --git a/src/mappers/mapper420.c b/src/mappers/mapper420.c new file mode 100644 index 000000000..ce92ed691 --- /dev/null +++ b/src/mappers/mapper420.c @@ -0,0 +1,70 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[4]; + +static void M420CW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x80) ? 0x7F : 0xFF; + uint16 base = ((reg[1] << 1) & 0x100) | ((reg[1] << 5) & 0x80); + + setchr1(A, base | (V & mask)); +} + +static void M420PW(uint16 A, uint16 V) { + if (reg[0] & 0x80) { + setprg32(0x8000, ((reg[2] >> 2) & 0x08) | ((reg[0] >> 1) & 0x07)); + } else { + uint8 mask = (reg[0] & 0x20) ? 0x0F : ((reg[3] & 0x20) ? 0x1F : 0x3F); + uint8 base = (reg[3] << 3) & 0x20; + + setprg8(A, base | (V & mask)); + } +} + +static DECLFW(M420Write) { + /* writes possible regardless of MMC3 wram state */ + CartBW(A, V); + reg[A & 0x03] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M420Reset(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Reset(); +} + +static void M420Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M420Write); +} + +void Mapper420_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M420CW; + MMC3_pwrap = M420PW; + info->Reset = M420Reset; + info->Power = M420Power; + AddExState(reg, 4, 0, "EXPR"); +} diff --git a/src/mappers/mapper421.c b/src/mappers/mapper421.c new file mode 100644 index 000000000..46a6ff3a0 --- /dev/null +++ b/src/mappers/mapper421.c @@ -0,0 +1,41 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "jyasic.h" + +static uint32 GetPRGBank(uint32 V) { + if (jyasic.mode[3] & 0x04) { + return (((jyasic.mode[3] << 4) & ~0x3F) | (V & 0x3F)); + } else { + return (((jyasic.mode[3] << 4) & ~0x1F) | (V & 0x1F)); + } +} + +static uint32 GetCHRBank(uint32 V) { + return (((jyasic.mode[3] << 8) & 0x300) | (V & 0x01FF)); +} + +void Mapper421_Init(CartInfo *info) { + /* Multicart */ + JYASIC_Init(info, TRUE); + JYASIC_GetPRGBank = GetPRGBank; + JYASIC_GetCHRBank = GetCHRBank; +} diff --git a/src/mappers/mapper428.c b/src/mappers/mapper428.c new file mode 100644 index 000000000..445ac1896 --- /dev/null +++ b/src/mappers/mapper428.c @@ -0,0 +1,84 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[4]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { reg, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + int mask = reg[2] >> 6; /* There is an CNROM mode that takes either two or four inner CHR banks from a CNROM-like + latch register at $8000-$FFFF. */ + + if (reg[1] & 0x10) { + setprg32(0x8000, reg[1] >> 6); + } else { + setprg16(0x8000, reg[1] >> 5); + setprg16(0xC000, reg[1] >> 5); + } + + setchr8(((reg[1] & 0x07) & ~mask) | (latch.data & mask)); + + setmirror(((reg[1] >> 3) & 0x01) ^ 0x01); +} + +static DECLFW(M428Write) { + reg[A & 0x03] = V; + Sync(); +} + +static DECLFR(M428Read) { + return (CPU_OPENBUS & ~0x03) | (dipsw & 0x03); +} + +static void M428Power(void) { + dipsw = 0; + reg[0] = 0; + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + Latch_Power(); + SetWriteHandler(0x6000, 0x7FFF, M428Write); + SetReadHandler(0x6000, 0x7FFF, M428Read); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void M428Reset(void) { + dipsw++; + reg[0] = 0; + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + Sync(); +} + +void Mapper428_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M428Power; + info->Reset = M428Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper429.c b/src/mappers/mapper429.c new file mode 100644 index 000000000..29b8474d8 --- /dev/null +++ b/src/mappers/mapper429.c @@ -0,0 +1,40 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* Mapper 429: LIKO BBG-235-8-1B/Milowork FCFC1 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.data >> 2); + setchr8(latch.data); +} + +static void Mapper429_Reset(void) { + latch.data = 4; /* Initial CHR bank 0, initial PRG bank 1 */ + Sync(); +} + +void Mapper429_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Mapper429_Reset; +} diff --git a/src/mappers/mapper430.c b/src/mappers/mapper430.c new file mode 100644 index 000000000..db9b3decd --- /dev/null +++ b/src/mappers/mapper430.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M430PW(uint16 A, uint16 V) { + uint8 mask = 0x0F; + uint8 base = (reg << 4) & 0x30; + + if (reg & 0x08) { + setprg8(0x8000, (base | ((mmc3.reg[6] & ~0x02) & mask))); + setprg8(0xA000, (base | ((mmc3.reg[7] & ~0x02) & mask))); + setprg8(0xC000, (base | ((mmc3.reg[6] | 0x02) & mask))); + setprg8(0xE000, (base | ((mmc3.reg[7] | 0x02) & mask))); + } else { + setprg8(A, (base | (V & mask))); + } +} + +static void M430CW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x04) ? 0x7F : 0xFF; + + setchr1(A, ((reg << 6) & ~mask) | (V & mask)); +} + +static DECLFW(M430Write) { + if (MMC3_WramIsWritable()) { + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M430Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M430Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M430Write); +} + +void Mapper430_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M430CW; + MMC3_pwrap = M430PW; + info->Reset = M430Reset; + info->Power = M430Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper431.c b/src/mappers/mapper431.c new file mode 100644 index 000000000..85e5f3bdc --- /dev/null +++ b/src/mappers/mapper431.c @@ -0,0 +1,64 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, ((reg[0] >> 2) & ~0x07) | (reg[1] & 0x07)); + setprg16(0xC000, ((reg[0] >> 2) & ~0x07) | 0x07); + setchr8(0); + setmirror((reg[0] & 0x01) ^ 0x01); +} + +static DECLFW(M431Write) { + reg[(A >> 14) & 0x01] = V; + Sync(); +} + +static void M431Reset(void) { + reg[1] = reg[0] = 0; + Sync(); +} + +static void M431Power(void) { + reg[1] = reg[0] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M431Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper431_Init(CartInfo *info) { + info->Power = M431Power; + info->Reset = M431Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper432.c b/src/mappers/mapper432.c new file mode 100644 index 000000000..96bc096bc --- /dev/null +++ b/src/mappers/mapper432.c @@ -0,0 +1,98 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; +static uint8 dipsw; + +static void M432CW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x04) ? 0x7F : 0xFF; + uint16 base = ((reg[1] << 7) & 0x080) | ((reg[1] << 5) & 0x100) | ((reg[1] << 4) & 0x200); + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M432PW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x02) ? 0x0F : 0x1F; + uint16 base = ((reg[1] << 4) & 0x10) | ((reg[1] << 1) & 0x60); + + if (reg[1] & 0x40) { /* NROM */ + if (reg[1] & 0x80) { /* NROM-256 */ + setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & ~0x02) & mask)); + setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & ~0x02) & mask)); + setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] | 0x02) & mask)); + setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] | 0x02) & mask)); + } else { /* NROM-128 */ + setprg8(0x8000, (base & ~mask) | (mmc3.reg[6] & mask)); + setprg8(0xA000, (base & ~mask) | (mmc3.reg[7] & mask)); + setprg8(0xC000, (base & ~mask) | (mmc3.reg[6] & mask)); + setprg8(0xE000, (base & ~mask) | (mmc3.reg[7] & mask)); + } + } else { /* MMC3 */ + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static DECLFR(M432Read) { + if ((reg[0] & 0x01) || ((reg[1] & 0x20) && (PRG_ROM_SIZE_16K < (1024 * 1024)))) { + return dipsw; + } + return CartBR(A); +} + +static DECLFW(M432Write) { + if (MMC3_WramIsWritable()) { + reg[A & 0x01] = V; + if (!(A & 0x01) && !(V & 0x01) && (PRG_ROM_SIZE_16K < (1024 * 1024))) { + reg[1] &= ~0x20; /* Writing 0 to register 0 clears register 1's DIP bit */ + } + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M432Reset(void) { + reg[0] = 0; + reg[1] = 0; + dipsw++; + MMC3_Reset(); +} + +static void M432Power(void) { + reg[0] = 0; + reg[1] = 0; + dipsw = 0; + MMC3_Power(); + SetReadHandler(0x8000, 0xFFFF, M432Read); + SetWriteHandler(0x6000, 0x7FFF, M432Write); +} + +void Mapper432_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M432CW; + MMC3_pwrap = M432PW; + info->Power = M432Power; + info->Reset = M432Reset; + AddExState(reg, 2, 0, "EXPR"); + AddExState(&dipsw, 1, 0, "CMD0"); +} diff --git a/src/mappers/mapper433.c b/src/mappers/mapper433.c new file mode 100644 index 000000000..e7e4ae67a --- /dev/null +++ b/src/mappers/mapper433.c @@ -0,0 +1,44 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 433 denotes the NC-20MB PCB, used for the 20-in-1 (CA-006) multicart. It is almost identical to INES Mapper 433, except that mirroring is selected just by single bit 6 (1=Horizontal). + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = latch.data & 0x1F; + + if (latch.data & 0x20) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { + setprg32(0x8000, prg >> 1); + } + setmirror(((latch.data >> 6) & 0x01) ^ 0x01); + setchr8(0); +} + +void Mapper433_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper434.c b/src/mappers/mapper434.c new file mode 100644 index 000000000..f2e1210ba --- /dev/null +++ b/src/mappers/mapper434.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* S-009. UNROM plus outerbank register at $6000-$7FFF. */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg; + +static void Sync(void) { + setprg16(0x8000, (reg << 3) | (latch.data & 0x07)); + setprg16(0xC000, (reg << 3) | 0x07); + setchr8(0); + setmirror((reg >> 5) & 0x01); +} + +static DECLFW(M434WriteOuterBank) { + reg = V; + Sync(); +} + +static void M434Reset(void) { + reg = 0; + Sync(); +} + +static void M434Power(void) { + reg = 0; + Latch_Power(); + SetWriteHandler(0x6000, 0x7FFF, M434WriteOuterBank); +} + +void Mapper434_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Reset = M434Reset; + info->Power = M434Power; + AddExState(®, 1, 0, "REGS"); +} diff --git a/src/mappers/mapper435.c b/src/mappers/mapper435.c new file mode 100644 index 000000000..779920a5f --- /dev/null +++ b/src/mappers/mapper435.c @@ -0,0 +1,53 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint16 prg = ((latch.addr >> 4) & 0x40) | ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); + + if (latch.addr & 0x200) { + if (latch.addr & 0x001) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { + setprg32(0x8000, prg >> 1); + } + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg | 0x07); + } + + if (latch.addr & 0x800) { + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); + } else { + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); + } + + setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); + setchr8(0); +} + +void Mapper435_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper436.c b/src/mappers/mapper436.c new file mode 100644 index 000000000..6a914ce25 --- /dev/null +++ b/src/mappers/mapper436.c @@ -0,0 +1,66 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2008 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 436: 820401/T-217 */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M436PW(uint16 A, uint16 V) { + if (reg & 0x01) { + setprg8(A, ((reg >> 2) & 0x30) | (V & 0x0F)); + } else { + setprg32(0x8000, (reg >> 4)); + } +} + +static void M436CW(uint16 A, uint16 V) { + setchr1(A, ((reg << 1) & ~0x7F) | (V & 0x7F)); +} + +static DECLFW(M436Write) { + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M436Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M436Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M436Write); +} + +void Mapper436_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = M436PW; + MMC3_cwrap = M436CW; + info->Power = M436Power; + info->Reset = M436Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper437.c b/src/mappers/mapper437.c new file mode 100644 index 000000000..70c2cc1da --- /dev/null +++ b/src/mappers/mapper437.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NTDEC TH2348 circuit board. UNROM plus reg bank register at $5FFx. */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg; + +static void Sync(void) { + setprg16(0x8000, (reg << 3) | (latch.data & 0x07)); + setprg16(0xC000, (reg << 3) | 0x07); + setchr8(0); + setmirror(((reg >> 3) & 0x01) ^ 0x01); +} + +static DECLFW(M437Write) { + reg = A & 0x0F; + Sync(); +} + +static void M437_Reset(void) { + reg = 0; + Sync(); +} + +static void M437_Power(void) { + reg = 0; + Latch_Power(); + SetWriteHandler(0x5000, 0x5FFF, M437Write); +} + +void Mapper437_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Reset = M437_Reset; + info->Power = M437_Power; + AddExState(®, 1, 0, "OUTB"); +} diff --git a/src/mappers/mapper438.c b/src/mappers/mapper438.c new file mode 100644 index 000000000..a8be1301c --- /dev/null +++ b/src/mappers/mapper438.c @@ -0,0 +1,46 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* K-3071 */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint16 prg = latch.addr >> 1; + uint16 chr = latch.data >> 1; + uint16 mirr = (latch.data & 0x01) ^ 0x01; + + if (latch.addr & 1) + setprg32(0x8000, prg >> 1); + else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + setchr8(chr); + setmirror(mirr); +} + +void Mapper438_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper439.c b/src/mappers/mapper439.c new file mode 100644 index 000000000..eb3885762 --- /dev/null +++ b/src/mappers/mapper439.c @@ -0,0 +1,66 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 439 denotes the YS2309 multicart PCB. + * Its UNIF MAPRs are BMC-DS-07 and BMC-K86B. + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[2]; + +static void Sync(void) { + uint8 mask = ((~reg[1] >> 1) & 0x38) | 0x07; + uint8 base = reg[0] >> 1; + setprg16(0x8000, (base & ~mask) | (latch.data & mask)); + setprg16(0xC000, (base & ~mask) | (0x3F & mask)); + setchr8(0); + setmirror(((latch.data >> 7) & 0x01) ^ 0x01); +} + +static DECLFW(M439WriteReg) { + reg[A & 0x01] = V; + Sync(); +} + +static DECLFW(M439WriteLatch) { + uint8 mask = (reg[1] & 0x80) | ((reg[1] >> 1) & 0x38); + Latch_Write(A, (V & ~mask) | (latch.data & mask)); +} + +static void M439Reset(void) { + reg[0] = reg[1] = 0; + Latch_RegReset(); +} + +static void M439Power(void) { + reg[0] = reg[1] = 0; + Latch_Power(); + SetWriteHandler(0x6000, 0x7FFF, M439WriteReg); + SetWriteHandler(0x8000, 0xFFFF, M439WriteLatch); +} + +void Mapper439_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M439Power; + info->Reset = M439Reset; + AddExState(reg, 2, 0, "REGS"); +} diff --git a/src/mappers/mapper441.c b/src/mappers/mapper441.c new file mode 100644 index 000000000..902d2f256 --- /dev/null +++ b/src/mappers/mapper441.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* 841026C and 850335C multicart circuit boards */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M441PW(uint16 A, uint16 V) { + uint8 mask = (reg & 0x08) ? 0x0F : 0x1F; + uint8 base = (reg << 4) & 0x30; + + if (reg & 0x04) { + setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & ~0x02) & mask)); + setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & ~0x02) & mask)); + setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] | 0x02) & mask)); + setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] | 0x02) & mask)); + } else { + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static void M441CW(uint16 A, uint16 V) { + uint16 mask = (reg & 0x40) ? 0x7F : 0xFF; + uint16 base = (reg << 3) & 0x180; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M441Write) { + if (MMC3_WramIsWritable()) { + if (!(reg & 0x80)) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } + } +} + +static void M441Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M441Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M441Write); +} + +void Mapper441_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M441CW; + MMC3_pwrap = M441PW; + info->Power = M441Power; + info->Reset = M441Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper443.c b/src/mappers/mapper443.c new file mode 100644 index 000000000..cc9aabc30 --- /dev/null +++ b/src/mappers/mapper443.c @@ -0,0 +1,84 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NC3000M PCB */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static void M443PW(uint16 A, uint16 V) { + uint8 mask = 0x0F; + uint8 base = ((reg << 4) & 0x20) | (reg & 0x10); + + if (reg & 0x04) { /* NROM */ + uint16 bank = (base & ~mask) | (mmc3.reg[6] & mask); + if (reg & 0x08) { /* NROM-128 */ + setprg16(0x8000, bank >> 1); + setprg16(0xC000, bank >> 1); + } else { /* NROM-256 */ + setprg32(0x8000, bank >> 2); + } + } else { /* MMC3 */ + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static void M443CW(uint16 A, uint16 V) { + setchr1(A, ((reg << 8) & ~0xFF) | (V & 0xFF)); +} + +static DECLFR(M443Read) { + return (((reg & 0x0C) == 0x08) ? dipsw : CartBR(A)); +} + +static DECLFW(M443Write) { + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M443Reset(void) { + dipsw++; + dipsw &= 15; + reg = 0; + MMC3_Reset(); +} + +static void M443Power(void) { + dipsw = 0; + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M443Write); + SetReadHandler(0x8000, 0xFFFF, M443Read); +} + +void Mapper443_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M443CW; + MMC3_pwrap = M443PW; + info->Power = M443Power; + info->Reset = M443Reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&dipsw, 1, 0, "DIPS"); +} diff --git a/src/mappers/mapper444.c b/src/mappers/mapper444.c new file mode 100644 index 000000000..7896492fe --- /dev/null +++ b/src/mappers/mapper444.c @@ -0,0 +1,92 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NC7000M PCB, with incorrect UNIF MAPR BS-110 due to a mix-up. Submapper bits 0 and 1. denote the setting of two + * solder info->submapper that configure CHR banking. */ +/* NC8000M PCB, indicated by submapper bit 2. */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static void M444PW(uint16 A, uint16 V) { + uint16 mask = ((iNESCart.submapper & 0x04) && (reg & 0x02)) ? 0x1F : 0x0F; + uint16 base = reg << 4; + + if (reg & 0x04) { /* NROM */ + uint16 bank = (base & ~mask) | (mmc3.reg[6] & mask); + if (reg & 0x08) { /* NROM-128 */ + setprg16(0x8000, bank >> 1); + setprg16(0xC000, bank >> 1); + } else { /* NROM-256 */ + setprg32(0x8000, bank >> 2); + } + } else { /* MMC3 */ + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static void M444CW(uint16 A, uint16 V) { + uint16 mask = (iNESCart.submapper & 0x01) ? 0xFF : 0x7F; + uint16 base = ((reg << 7) & ((iNESCart.submapper & 0x01) ? 0x00 : 0x80)) | ((reg << ((iNESCart.submapper & 0x02) ? 4 : 7)) & 0x100); + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static DECLFR(M444Read) { + if ((reg & 0x0C) == 0x08) { + return dipsw; + } + return CartBR(A); +} + +static DECLFW(M444Write) { + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static void M444Reset(void) { + dipsw++; + dipsw &= 3; + reg = 0; + MMC3_Reset(); +} + +static void M444Power(void) { + dipsw = 0; + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M444Write); + SetReadHandler(0x8000, 0xFFFF, M444Read); +} + +void Mapper444_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M444CW; + MMC3_pwrap = M444PW; + info->Power = M444Power; + info->Reset = M444Reset; + AddExState(®, 1, 0, "EXPR"); + AddExState(&dipsw, 1, 0, "DIPS"); +} diff --git a/src/mappers/mapper445.c b/src/mappers/mapper445.c new file mode 100644 index 000000000..745fdbf7c --- /dev/null +++ b/src/mappers/mapper445.c @@ -0,0 +1,120 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 445 + * DG574B MMC3-compatible multicart circuit board. + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "vrc24.h" + +#define MAPPER_MMC3 0x00 +#define MAPPER_VRC4 0x10 + +static uint8 reg[4]; + +static void M445PW(uint16 A, uint16 V) { + uint8 mask = (reg[2] & 0x01) ? 0x0F : 0x1F; + uint8 base = reg[0]; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M445CW(uint16 A, uint16 V) { + uint16 mask = (reg[2] & 0x08) ? 0x7F : 0xFF; + uint16 base = reg[1] << 3; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M445WriteREG) { + if (!(reg[3] & 0x20)) { + reg[A & 0x03] = V; + vrc24.A0 = reg[3] & 0x01 ? 0x0A : 0x05; + vrc24.A1 = reg[3] & 0x01 ? 0x05 : 0x0A; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static DECLFW(M445WriteASIC) { + switch (reg[3] & 0x10) { + case MAPPER_VRC4: + VRC24_Write(A, V); + break; + case MAPPER_MMC3: + default: + MMC3_Write(A, V); + break; + } +} + +static void M445Reset(void) { + reg[0] = 0x00; + reg[1] = 0x00; + reg[2] = 0x00; + reg[3] = 0x00; + VRC24_Reset(); + MMC3_Reset(); +} + +static void M445Power(void) { + reg[0] = 0x00; + reg[1] = 0x00; + reg[2] = 0x00; + reg[3] = 0x00; + VRC24_Power(); + MMC3_Power(); + SetWriteHandler(0x5000, 0x5FFF, M445WriteREG); + SetWriteHandler(0x8000, 0xFFFF, M445WriteASIC); +} + +static void StateRestore(int version) { + switch (reg[3] & 0x10) { + case MAPPER_VRC4: + VRC24_FixPRG(); + VRC24_FixCHR(); + VRC24_FixMIR(); + break; + case MAPPER_MMC3: + default: + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + } +} + +void Mapper445_Init(CartInfo *info) { + MMC3_Init(info, info->PRGRamSize + info->PRGRamSaveSize, info->battery); + MMC3_pwrap = M445PW; + MMC3_cwrap = M445CW; + + VRC24_Init(info, VRC4, 0x01, 0x02, FALSE, TRUE); + VRC24_pwrap = M445PW; + VRC24_cwrap = M445CW; + + info->Power = M445Power; + info->Reset = M445Reset; + + GameStateRestore = StateRestore; + AddExState(reg, 4, 0, "EXPR"); +} diff --git a/src/mappers/mapper446.c b/src/mappers/mapper446.c new file mode 100644 index 000000000..f8a69b9df --- /dev/null +++ b/src/mappers/mapper446.c @@ -0,0 +1,475 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" +#include "mmc1.h" +#include "mmc3.h" +#include "vrc24.h" +#include "vrc6.h" +#include "flashrom.h" + +#define MAPPER_UNROM 0x00 +#define MAPPER_MMC3 0x01 +#define MAPPER_NROM 0x02 +#define MAPPER_CNROM 0x03 +#define MAPPER_ANROM 0x04 +#define MAPPER_SLROM 0x05 +#define MAPPER_SNROM 0x06 +#define MAPPER_SUROM 0x07 +#define MAPPER_GNROM 0x08 +#define MAPPER_PNROM 0x09 +#define MAPPER_HKROM 0x0A +#define MAPPER_BANDAI152 0x0B +#define MAPPER_TLSROM 0x0E +#define MAPPER_189 0x0F +#define MAPPER_VRC6 0x10 +#define MAPPER_VRC2_22 0x12 +#define MAPPER_VRC4_25 0x15 +#define MAPPER_VRC4_23 0x18 +#define MAPPER_VRC1 0x1A + +#define WRAM_CHIP 0x10 +#define FLASH_CHIP 0x11 + +static uint8 *flash = NULL; +static uint8_t reg[9]; + +static SFORMAT StateRegs[] = { + { reg, 9, "REGS" }, + { 0 } +}; + +static uint32 GetPRGBase(void) { + return ((reg[2] << 8) | reg[1]); +} + +static uint32 GetPRGMask(void) { + return (~reg[3]); +} + +static uint32 GetCHRBase(void) { + return reg[6]; +} + +static void M446MMC1PW(uint16 A, uint16 V) { + setprg16r(FLASH_CHIP, A, (GetPRGBase() >> 1) | (V & (GetPRGMask() >> 1))); +} +static void M446MMC1CW(uint16 A, uint16 V) { + setchr4(A, (GetCHRBase() >> 2) | (V & 0x1F)); +} + +static void M446MMC3PW(uint16 A, uint16 V) { + switch (reg[0] & 0x1F) { + case MAPPER_MMC3: + case MAPPER_TLSROM: + setprg8r(FLASH_CHIP, A, GetPRGBase() | (V & GetPRGMask())); + break; + + case MAPPER_189: + setprg32r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 2) | (reg[8] & 0x03)); + break; + } +} +static void M446MMC3CW(uint16 A, uint16 V) { + switch (reg[0] & 0x1F) { + case MAPPER_TLSROM: + setchr1(A, GetCHRBase() | (V & 0x7F)); + break; + + case MAPPER_MMC3: + case MAPPER_189: + setchr1(A, GetCHRBase() | (V & 0xFF)); + break; + } +} + +static void M446VRC24PW(uint16 A, uint16 V) { + switch (reg[0] & 0x1F) { + case MAPPER_VRC2_22: + case MAPPER_VRC4_23: + case MAPPER_VRC4_25: + setprg8r(FLASH_CHIP, A, GetPRGBase() | (V & GetPRGMask())); + break; + } +} +static void M446VRC24CW(uint16 A, uint16 V) { + switch (reg[0] & 0x1F) { + case MAPPER_VRC2_22: + setchr1(A, V >> 1); + break; + + case MAPPER_VRC4_23: + case MAPPER_VRC4_25: + setchr1(A, V & 0xFF); + break; + } +} + +static void M446VRC6PW(uint16 A, uint16 V) { + setprg8r(FLASH_CHIP, A, GetPRGBase() | (V & GetPRGMask())); +} + +static void M446VRC6CW(uint16 A, uint16 V) { + setchr1(A, V & 0xFF); +} + +static void Sync(void) { + /* CHR-RAM Protect */ + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], (reg[5] & 0x04) ? 0 : 1); + + if (reg[0] & 0x80) { + switch (reg[0] & 0x1F) { + case MAPPER_NROM: + setprg8r(FLASH_CHIP, 0x8000, GetPRGBase() | (0x00 & GetPRGMask())); + setprg8r(FLASH_CHIP, 0xA000, GetPRGBase() | (0x01 & GetPRGMask())); + setprg8r(FLASH_CHIP, 0xC000, GetPRGBase() | (0x02 & GetPRGMask())); + setprg8r(FLASH_CHIP, 0xE000, GetPRGBase() | (0x03 & GetPRGMask())); + setchr8(GetCHRBase()); + setmirror(reg[4] & 0x01); + break; + + case MAPPER_CNROM: + setprg8r(FLASH_CHIP, 0x8000, GetPRGBase() | (0x00 & GetPRGMask())); + setprg8r(FLASH_CHIP, 0xA000, GetPRGBase() | (0x01 & GetPRGMask())); + setprg8r(FLASH_CHIP, 0xC000, GetPRGBase() | (0x02 & GetPRGMask())); + setprg8r(FLASH_CHIP, 0xE000, GetPRGBase() | (0x03 & GetPRGMask())); + setchr8(latch.data & 3); + setmirror(reg[4] & 0x01); + break; + + case MAPPER_UNROM: + setprg16r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 1) | (latch.data & (GetPRGMask() >> 1))); + setprg16r(FLASH_CHIP, 0xC000, (GetPRGBase() >> 1) | ((GetPRGMask() >> 1) & 0x1F)); + setchr8(GetCHRBase()); + setmirror(reg[4] & 0x01); + break; + + case MAPPER_BANDAI152: + setprg16r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 1) | ((latch.data >> 4) & (GetPRGMask() >> 1))); + setprg16r(FLASH_CHIP, 0xC000, (GetPRGBase() >> 1) | (0xFF & (GetPRGMask() >> 1))); + setchr8(latch.data & 0xF); + setmirror(MI_0 + ((latch.data & 0x80) >> 7)); + break; + + case MAPPER_ANROM: + setprg32r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 2) | (latch.data & (GetPRGMask() >> 2))); + setchr8(GetCHRBase()); + setmirror(MI_0 + ((latch.data & 0x10) >> 4)); + break; + + case MAPPER_GNROM: + setprg32r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 2) | ((latch.data >> 4) & (GetPRGMask() >> 2))); + setchr8(latch.data & 0x03); + setmirror(reg[4] & 0x01); + break; + + case MAPPER_SLROM: + case MAPPER_SNROM: + setprg8r(WRAM_CHIP, 0x6000, 0); + MMC1_FixPRG(); + MMC1_FixCHR(); + MMC1_FixMIR(); + break; + + case MAPPER_MMC3: + setprg8r(WRAM_CHIP, 0x6000, 0); + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + + case MAPPER_TLSROM: + setprg8r(WRAM_CHIP, 0x6000, 0); + MMC3_FixPRG(); + MMC3_FixCHR(); + if (mmc3.cmd & 0x80) { + setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); + } else { + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); + } + break; + + case MAPPER_189: + setprg8r(WRAM_CHIP, 0x6000, 0); + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + + case MAPPER_VRC2_22: + setprg8r(WRAM_CHIP, 0x6000, 0); + VRC24_FixPRG(); + VRC24_FixCHR(); + VRC24_FixMIR(); + break; + + case MAPPER_VRC4_23: + case MAPPER_VRC4_25: + setprg8r(WRAM_CHIP, 0x6000, 0); + VRC24_FixPRG(); + VRC24_FixCHR(); + VRC24_FixMIR(); + break; + + case MAPPER_VRC6: + setprg8r(WRAM_CHIP, 0x6000, 0); + VRC6_FixPRG(); + VRC6_FixCHR(); + break; + } + } else { + setprg8r(FLASH_CHIP, 0x8000, GetPRGBase()); + setprg8r(FLASH_CHIP, 0xA000, 0x3D); + setprg8r(FLASH_CHIP, 0xC000, 0x3E); + setprg8r(FLASH_CHIP, 0xE000, 0x3F); + setchr8(GetCHRBase()); + setmirror(reg[4] & 0x01); + } +} + +static void apply_mode(void) { + if (reg[0] & 0x80) { + switch (reg[0] & 0x1F) { + case MAPPER_ANROM: + case MAPPER_CNROM: + case MAPPER_UNROM: + case MAPPER_GNROM: + case MAPPER_BANDAI152: + Latch_RegReset(); + break; + case MAPPER_SLROM: + case MAPPER_SNROM: + MMC1_Reset(); + break; + case MAPPER_189: + case MAPPER_MMC3: + case MAPPER_TLSROM: + MMC3_Reset(); + break; + case MAPPER_VRC2_22: + vrc24.VRC4 = FALSE; + vrc24.A0 = 0x02; + vrc24.A1 = 0x01; + VRC24_Reset(); + break; + case MAPPER_VRC4_23: + vrc24.VRC4 = TRUE; + vrc24.A0 = 0x05; + vrc24.A1 = 0x0A; + VRC24_Reset(); + break; + case MAPPER_VRC4_25: + vrc24.VRC4 = TRUE; + vrc24.A0 = 0x0A; + vrc24.A1 = 0x05; + VRC24_Reset(); + break; + case MAPPER_VRC6: + VRC6_Reset(); + break; + } + } +} + +static DECLFR(M446Read) { + return FlashROM_Read(A); +} + +static DECLFW(M446WriteLatch) { + CartBW(A, V); + if (reg[0] & 0x1F == MAPPER_189) { + reg[8] = A & 0xFF; + Sync(); + } +} + +static DECLFW(M446WriteReg) { + if (!(reg[0] & 0x80)) { + A &= 0x07; + if (!A && !iNESCart.submapper && ((V & 0x1F) == 0x01)) { + V = (V & ~0x1F) | MAPPER_SNROM; + } + reg[A] = V; + apply_mode(); + Sync(); + } +} + +static DECLFW(M446Write) { + if (reg[0] & 0x80) { + switch (reg[0] & 0x1F) { + case MAPPER_ANROM: + case MAPPER_CNROM: + case MAPPER_UNROM: + case MAPPER_GNROM: + case MAPPER_BANDAI152: + Latch_Write(A, V); + break; + + case MAPPER_SLROM: + case MAPPER_SNROM: + MMC1_Write(A, V); + break; + + case MAPPER_189: + case MAPPER_MMC3: + case MAPPER_TLSROM: + MMC3_Write(A, V); + break; + + case MAPPER_VRC2_22: + VRC24_Write(A, V); + break; + + case MAPPER_VRC4_23: + VRC24_Write(A, V); + break; + + case MAPPER_VRC4_25: + VRC24_Write(A, V); + break; + + case MAPPER_VRC6: + VRC6_Write(A, V); + break; + } + } else { + FlashROM_Write(A, V); + } +} + +static void M446HBIRQHook(void) { + if (reg[0] & 0x80) { + switch (reg[0] & 0x1F) { + case MAPPER_MMC3: + case MAPPER_TLSROM: + case MAPPER_189: + MMC3_IRQHBHook(); + break; + } + } +} + +static void M446CPUIRQHook(int a) { + FlashROM_CPUCyle(a); + + if (reg[0] & 0x80) { + switch (reg[0] & 0x1F) { + case MAPPER_VRC2_22: + case MAPPER_VRC4_23: + case MAPPER_VRC4_25: + VRC24_IRQCPUHook(a); + break; + + case MAPPER_VRC6: + VRC6_IRQCPUHook(a); + break; + } + } +} + +static void M446Close(void) { + if (flash) { + FCEU_free(flash); + flash = NULL; + } +} + +static void M446Reset(void) { + memset(reg, 0, sizeof(reg)); + apply_mode(); + Sync(); +} + +static void M446Power(void) { + memset(reg, 0, sizeof(reg)); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + + SetReadHandler(0x8000, 0xFFFF, M446Read); + + SetWriteHandler(0x5000, 0x5FFF, M446WriteReg); + SetWriteHandler(0x6000, 0x6FFF, M446WriteLatch); + SetWriteHandler(0x8000, 0xFFFF, M446Write); + + apply_mode(); + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper446_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + + MMC1_Init(info, FALSE, FALSE); + MMC1_pwrap = M446MMC1PW; + MMC1_cwrap = M446MMC1CW; + + MMC3_Init(info, FALSE, FALSE); + MMC3_pwrap = M446MMC3PW; + MMC3_cwrap = M446MMC3CW; + + VRC24_Init(info, VRC4, 0x01, 0x02, FALSE, TRUE); + VRC24_pwrap = M446VRC24PW; + VRC24_cwrap = M446VRC24CW; + + VRC6_Init(info, 0x01, 0x02, FALSE); + VRC6_pwrap = M446VRC6PW; + VRC6_cwrap = M446VRC6CW; + + info->Power = M446Power; + info->Reset = M446Reset; + info->Close = M446Close; + + MapIRQHook = M446CPUIRQHook; + GameHBIRQHook = M446HBIRQHook; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(WRAM_CHIP, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } + + /* Allocate memory for flash */ + flash = (uint8 *)FCEU_gmalloc(PRGsize[0]); + SetupCartPRGMapping(FLASH_CHIP, flash, PRGsize[0], 1); + AddExState(flash, PRGsize[0], 0, "FLSH"); + memcpy(flash, PRGptr[0], PRGsize[0]); + FlashROM_Init(flash, PRGsize[0], 0x01, 0x7E, 131072, 0xAAA, 0x555); +} diff --git a/src/mappers/mapper447.c b/src/mappers/mapper447.c new file mode 100644 index 000000000..68345ea7f --- /dev/null +++ b/src/mappers/mapper447.c @@ -0,0 +1,94 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 447 - KL-06 (VRC4 clone) + * 1993 New 860-in-1 Over-Valued Golden Version Games multicart + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 reg; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 }, +}; + +static void M447PW(uint16 A, uint16 V) { + uint16 mask = 0x0F; + uint16 base = reg << 4; + + if (reg & 0x04) { + uint8 A14 = (reg & 0x02) ^ 0x02; + setprg8(0x8000, (base & ~mask) | ((vrc24.prg[0] & ~A14) & mask)); + setprg8(0xA000, (base & ~mask) | ((vrc24.prg[1] & ~A14) & mask)); + setprg8(0xC000, (base & ~mask) | ((vrc24.prg[0] | A14) & mask)); + setprg8(0xE000, (base & ~mask) | ((vrc24.prg[1] | A14) & mask)); + } else { + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static void M447CW(uint16 A, uint16 V) { + setchr1(A, (reg << 7) | (V & 0x7F)); +} + +static DECLFR(M447Read) { + if ((A & 0x8000) && (reg & 0x08)) { + return CartBR((A & ~0x03) | (dipsw & 0x03)); + } + return CartBR(A); +} + +static DECLFW(M447WriteReg) { + CartBW(A, V); + if ((vrc24.cmd & 0x01) && !(reg & 0x01)) { + reg = A & 0xFF; + VRC24_FixPRG(); + VRC24_FixCHR(); + } +} + +static void M447Reset(void) { + reg = 0; + dipsw++; + VRC24_FixPRG(); + VRC24_FixCHR(); +} + +static void M447Power(void) { + reg = 0; + dipsw = 0; + VRC24_Power(); + SetReadHandler(0x8000, 0xFFFF, M447Read); + SetWriteHandler(0x6000, 0x7FFF, M447WriteReg); +} + +void Mapper447_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x04, 0x08, 1, 1); + info->Reset = M447Reset; + info->Power = M447Power; + VRC24_pwrap = M447PW; + VRC24_cwrap = M447CW; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper448.c b/src/mappers/mapper448.c new file mode 100644 index 000000000..106aaa775 --- /dev/null +++ b/src/mappers/mapper448.c @@ -0,0 +1,98 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 448 + * VRC4-based 830768C multicart circuit board used by a Super 6-in-1 multicart. + */ + +#include "mapinc.h" +#include "latch.h" +#include "vrc24.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 }, +}; + +static void Sync(void) { + if (reg & 0x08) { /* AOROM */ + setprg32(0x8000, ((reg << 2) & ~0x07) | (latch.data & 0x07)); + setmirror(MI_0 + ((latch.data >> 4) & 0x01)); + } else { + if (reg & 0x04) { /* UOROM */ + setprg16(0x8000, ((reg << 3) & ~0x0F) | (vrc24.prg[0] & 0x0F)); + setprg16(0xC000, ((reg << 3) & ~0x0F) | 0x0F); + } else { /* UNROM */ + setprg16(0x8000, (reg << 3) | (vrc24.prg[0] & 0x07)); + setprg16(0xC000, (reg << 3) | 0x07); + } + switch (vrc24.mirr & 0x03) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } + } + setchr8(0); +} + +static DECLFW(M448WriteReg) { + if (vrc24.cmd & 0x01) { + reg = A & 0xFF; + Sync(); + } +} + +static DECLFW(M448WriteASIC) { + Latch_Write(A, V); + VRC24_Write(A, V); + Sync(); +} + +static void M448Reset(void) { + reg = 0; + Sync(); +} + +static void M448Power(void) { + reg = 0; + Latch_Power(); + VRC24_Power(); + Sync(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M448WriteReg); + SetWriteHandler(0x8000, 0xFFFF, M448WriteASIC); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper448_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + VRC24_Init(info, VRC4, 0x04, 0x08, 0, 1); + info->Reset = M448Reset; + info->Power = M448Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper449.c b/src/mappers/mapper449.c new file mode 100644 index 000000000..43943dd34 --- /dev/null +++ b/src/mappers/mapper449.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint32 prg = ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); + uint32 cpuA14 = latch.addr & 0x01; + uint32 nrom = (latch.addr >> 7) & 0x01; + + setprg16(0x8000, prg & ~(cpuA14 * nrom)); + setprg16(0xC000, prg | (cpuA14 * nrom) | (0x07 * !nrom)); + + setchr8(latch.data); + setmirror((((latch.addr >> 1) & 0x01) ^ 0x01)); +} + +static DECLFR(M449Read) { + if (latch.addr & 0x200) { + A |= dipsw; + } + return CartBR(A); +} + +static void M449Reset(void) { + dipsw = (dipsw + 1) & 0xF; + Latch_RegReset(); +} + +void Mapper449_Init(CartInfo *info) { + Latch_Init(info, Sync, M449Read, FALSE, FALSE); + info->Reset = M449Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper450.c b/src/mappers/mapper450.c new file mode 100644 index 000000000..4522711ea --- /dev/null +++ b/src/mappers/mapper450.c @@ -0,0 +1,39 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 450 - YY841157C + */ + +#include "mapinc.h" +#include "vrc24.h" + +static void M450PW(uint16 A, uint16 V) { + setprg8(A, (vrc24.latch << 4) | (V & 0x0F)); +} + +static void M450CW(uint16 A, uint16 V) { + setchr1(A, (vrc24.latch << 7) | (V & 0x7F)); +} + +void Mapper450_Init(CartInfo *info) { + VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); + VRC24_pwrap = M450PW; + VRC24_cwrap = M450CW; +} diff --git a/src/mappers/mapper451.c b/src/mappers/mapper451.c new file mode 100644 index 000000000..e1d471641 --- /dev/null +++ b/src/mappers/mapper451.c @@ -0,0 +1,111 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 451 */ +/* Uses flashrom to save high scores. */ + +#include "mapinc.h" +#include "mmc3.h" +#include "flashrom.h" + +static uint8 reg; + +static uint8 *FLASHROM = NULL; +static uint32 FLASHROM_size = 0; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M451FixPRG(void) { + setprg8r(0x10, 0x8000, 0); + setprg8r(0x10, 0xA000, 0x10 | ((reg << 2) & 0x08) | (reg & 0x01)); + setprg8r(0x10, 0xC000, 0x20 | ((reg << 2) & 0x08) | (reg & 0x01)); + setprg8r(0x10, 0xE000, 0x30); +} + +static void M451FixCHR(void) { + setchr8(reg & 0x01); +} + +static DECLFR(M451Read) { + return FlashROM_Read(A); +} + +static DECLFW(M451Write) { + FlashROM_Write(A, V); + switch (A & 0xE000) { + case 0xA000: + MMC3_CMDWrite(0xA000, A & 0x01); + break; + case 0xC000: + A &= 0xFF; + MMC3_IRQWrite(0xC000, A - 1); + MMC3_IRQWrite(0xC001, 0); + MMC3_IRQWrite(0xE000 + ((A == 0xFF) ? 0x00 : 0x01), 0x00); + break; + case 0xE000: + reg = A & 0x03; + MMC3_FixPRG(); + MMC3_FixCHR(); + break; + } +} + +static void M451Power(void) { + MMC3_Power(); + SetReadHandler(0x8000, 0xFFFF, M451Read); + SetWriteHandler(0x8000, 0xFFFF, M451Write); +} + +static void M451Close(void) { + MMC3_Close(); + if (FLASHROM) { + FCEU_free(FLASHROM); + } + FLASHROM = NULL; +} + +void Mapper451_Init(CartInfo *info) { + uint32 w, r; + + MMC3_Init(info, 0, 0); + info->Power = M451Power; + info->Close = M451Close; + MMC3_FixPRG = M451FixPRG; + MMC3_FixCHR = M451FixCHR; + MapIRQHook = FlashROM_CPUCyle; + AddExState(StateRegs, ~0, 0, NULL); + + info->battery = 1; + FLASHROM_size = PRGsize[0]; + FLASHROM = (uint8 *)FCEU_gmalloc(FLASHROM_size); + info->SaveGame[0] = FLASHROM; + info->SaveGameLen[0] = FLASHROM_size; + AddExState(FLASHROM, FLASHROM_size, 0, "FLAS"); + /* copy PRG ROM into FLASHROM, use it instead of PRG ROM */ + for (w = 0, r = 0; w < FLASHROM_size; w++) { + FLASHROM[w] = PRGptr[0][r]; + ++r; + } + SetupCartPRGMapping(0x10, FLASHROM, FLASHROM_size, 0); + FlashROM_Init(FLASHROM, FLASHROM_size, 0x37, 0x86, 65536, 0x0555, 0x02AA); +} diff --git a/src/mappers/mapper452.c b/src/mappers/mapper452.c new file mode 100644 index 000000000..b42fd992a --- /dev/null +++ b/src/mappers/mapper452.c @@ -0,0 +1,80 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* DS-9-27. Absolutely insane PCB that overlays 8 KiB of WRAM into a selectable position between $8000 and $E000. */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint16 prgbank = latch.addr >> 1; + uint16 prgram_addr = 0x8000 | ((latch.data << 9) & 0x6000); + + if (latch.data & 0x02) { + setprg8(0x8000, prgbank); + setprg8(0xA000, prgbank); + setprg8(0xC000, prgbank); + setprg8(0xE000, prgbank); + } else if (latch.data & 0x08) { + setprg8(0x8000, (prgbank & ~0x01) | 0); + setprg8(0xA000, (prgbank & ~0x01) | 1); + setprg8(0xC000, (prgbank & ~0x01) | 2); + setprg8(0xE000, (prgbank & ~0x01) | 3 + | (latch.data & 0x04) + | ((latch.data & 0x04) && (latch.data & 0x40) ? 0x08 : 0x00)); + } else { + setprg16(0x8000, latch.addr >> 2); + setprg16(0xC000, 0); + } + + setchr8(0); + setmirror((latch.data & 0x01) ^ 0x01); + + setprg8r(0x10, prgram_addr, 0); + if (latch.data & 0x02) { + setprg8r(0x10, prgram_addr ^ 0x4000, 0); + } +} + +static DECLFW(M452Write) { + switch (A & 0xE000) { + case 0x8000: + case 0xA000: + case 0xC000: + Latch_Write(A, V); + break; + case 0xE000: + CartBW(A, V); + break; + } +} + +static void M452Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M452Write); +} + +void Mapper452_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, TRUE, FALSE); + info->Reset = Latch_RegReset; + info->Power = M452Power; +} diff --git a/src/mappers/mapper453.c b/src/mappers/mapper453.c new file mode 100644 index 000000000..11eb0aea5 --- /dev/null +++ b/src/mappers/mapper453.c @@ -0,0 +1,59 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 453 - Realtec 8042 + * 3-in-1 1995 World Competitive Champion Edition (DG-002) + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.data & 0x40) { + setprg32(0x8000, ((latch.data >> 3) & 0x18) | (latch.data & 0x07)); + setmirror(MI_0 + (((latch.data >> 4) & 0x01) ^ 0x01)); + } else { + setprg16(0x8000, ((latch.data >> 2) & 0x38) | (latch.data & 0x07)); + setprg16(0xC000, (latch.data >> 2 & 0x38) | 0x07); + setmirror(((latch.data >> 4) & 0x01) ^ 0x01); + } + setchr8(0); +} + +static DECLFW(M453Write) { + if (latch.data & 0xE0) { + latch.data = (latch.data & 0xE0) | (V & ~0xE0); + } else { + latch.data = V; + } + Sync(); +} + +static void M453Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M453Write); +} + +void Mapper453_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M453Power; + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper454.c b/src/mappers/mapper454.c new file mode 100644 index 000000000..644cbbd87 --- /dev/null +++ b/src/mappers/mapper454.c @@ -0,0 +1,63 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NOTE: Only loading Contra after a reset? RAM init also affects powerup */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); + uint8 cpuA14 = latch.addr & 0x01; + uint8 nrom = (latch.addr >> 7) & 0x01; + uint8 unrom = (latch.addr >> 9) & 0x01; + + setprg16(0x8000, ((prg & ~cpuA14) & ~(0x07 * unrom)) | (latch.data * unrom)); + setprg16(0xC000, ((prg | cpuA14) & ~(0x07 * !nrom * !unrom)) | (0x07 * !nrom * unrom)); + setchr8(0); + setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); + if (nrom) { + /* CHR-RAM write protect hack, needed for some multicarts */ + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); + } else { + SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); + } +} + +static DECLFW(M454Write) { + if (latch.addr & 0x100) { + latch.data = V & 0x07; + } else { + latch.data = V; + latch.addr = A; + } + Sync(); +} + +static void M454Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M454Write); +} + +void Mapper454_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, 0, 0); + info->Power = M454Power; +} diff --git a/src/mappers/mapper455.c b/src/mappers/mapper455.c new file mode 100644 index 000000000..f578d1afb --- /dev/null +++ b/src/mappers/mapper455.c @@ -0,0 +1,79 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; + +static void M455PW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x01) ? 0x1F : 0x0F; + uint16 base = ((reg[0] >> 2) & 0x10) | ((reg[1] << 1) & 0x08) | ((reg[0] >> 2) & 0x07); + + if (reg[0] & 0x01) { + if (reg[0] & 0x02) { + setprg32(0x8000, base >> 1); + } else { + setprg16(0x8000, base); + setprg16(0xC000, base); + } + } else { + setprg8(A, ((base << 1) & ~mask) | (V & mask)); + } +} + +static void M455CW(uint16 A, uint16 V) { + uint16 mask = (reg[1] & 0x02) ? 0xFF : 0x7F; + uint16 base = ((reg[0] >> 2) & 0x10) | ((reg[1] << 1) & 0x08) | ((reg[0] >> 2) & 0x07); + + setchr1(A, ((base << 4) & ~mask) | (V & mask)); +} + +static DECLFW(M455Write) { + if (A & 0x100) { + reg[0] = V; + reg[1] = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M455Reset(void) { + reg[0] = 1; + reg[1] = 0; + MMC3_Reset(); +} + +static void M455Power(void) { + reg[0] = 1; + reg[1] = 0; + MMC3_Power(); + SetWriteHandler(0x4100, 0x5FFF, M455Write); +} + +void Mapper455_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M455CW; + MMC3_pwrap = M455PW; + info->Power = M455Power; + info->Reset = M455Reset; + AddExState(reg, 2, 0, "EXPR"); +} diff --git a/src/mappers/mapper456.c b/src/mappers/mapper456.c new file mode 100644 index 000000000..9139dfacf --- /dev/null +++ b/src/mappers/mapper456.c @@ -0,0 +1,61 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M456PW(uint16 A, uint16 V) { + setprg8(A, (reg << 4) | (V & 0x0F)); +} + +static void M456CW(uint16 A, uint16 V) { + setchr1(A, (reg << 7) | (V & 0x7F)); +} + +static DECLFW(M456Write) { + if (A & 0x100) { + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M456Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M456Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x4100, 0x5FFF, M456Write); +} + +void Mapper456_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_cwrap = M456CW; + MMC3_pwrap = M456PW; + info->Power = M456Power; + info->Reset = M456Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper457.c b/src/mappers/mapper457.c new file mode 100644 index 000000000..f47c83f28 --- /dev/null +++ b/src/mappers/mapper457.c @@ -0,0 +1,67 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M457CW(uint16 A, uint16 V) { + uint32 mask = (reg & 0x08) ? 0xFF : 0x7F; + uint32 base = reg << 7; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M457PW(uint16 A, uint16 V) { + uint32 mask = (reg & 0x08) ? 0x1F : 0x0F; + uint32 base = reg << 4; + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static DECLFW(M457Write) { + if (MMC3_WramIsWritable()) { + CartBW(A, V); + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M457Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M457Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, M457Write); +} + +void Mapper457_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M457CW; + MMC3_pwrap = M457PW; + info->Reset = M457Reset; + info->Power = M457Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper458.c b/src/mappers/mapper458.c new file mode 100644 index 000000000..07eb85ead --- /dev/null +++ b/src/mappers/mapper458.c @@ -0,0 +1,82 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static void M458CW(uint16 A, uint16 V) { + uint16 mask = 0x7F; + uint16 base = reg << 4; + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M458PW(uint16 A, uint16 V) { + uint8 prg = reg & 0x0F; + + if (reg & 0x10) { + setprg32(0x8000, prg >> 1); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } +} + +static DECLFR(M458Read) { + if ((reg & 0x20) && (dipsw & 0x03)) { + return CartBR((A & ~0x1F) | (dipsw & 0x1F)); + } + return CartBR(A); +} + +static DECLFW(M458Write) { + if (MMC3_WramIsWritable()) { + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M458Reset(void) { + reg = 0; + dipsw++; + MMC3_Reset(); +} + +static void M458Power(void) { + reg = 0; + dipsw = 0; + MMC3_Power(); + SetReadHandler(0x8000, 0xFFFF, M458Read); + SetWriteHandler(0x6000, 0x7FFF, M458Write); +} + +void Mapper458_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M458CW; + MMC3_pwrap = M458PW; + info->Reset = M458Reset; + info->Power = M458Power; + AddExState(®, 1, 0, "EXPR"); + AddExState(&dipsw, 1, 0, "CMD0"); +} diff --git a/src/mappers/mapper459.c b/src/mappers/mapper459.c new file mode 100644 index 000000000..52ad00122 --- /dev/null +++ b/src/mappers/mapper459.c @@ -0,0 +1,42 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = latch.addr >> 4; + uint8 chr = (latch.addr & 0x03) | ((latch.addr >> 2) & 0x04) | ((latch.addr >> 4) & 0x08); + uint8 mirr = ((latch.addr >> 8) & 0x01) ^ 0x01; + + if (latch.addr & 0x04) { + setprg32(0x8000, prg >> 1); + } else { + setprg16(0x8000, prg ); + setprg16(0xC000, prg | 0x07); + } + setchr8(chr); + setmirror(mirr); +} + +void Mapper459_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper460.c b/src/mappers/mapper460.c new file mode 100644 index 000000000..f69db9184 --- /dev/null +++ b/src/mappers/mapper460.c @@ -0,0 +1,112 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void M460PW(uint16 A, uint16 V) { + uint32 mask = 0x0F; + uint32 base = reg << 4; + + if (reg & 0x20) { + /* Menu selection by selectively connecting CPU D7 to reg or not */ + if (reg & 0x10) { + setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & ~0x02) & mask)); + setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & ~0x02) & mask)); + setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] | 0x02) & mask)); + setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] | 0x02) & mask)); + } else { + setprg8(0x8000, (base & ~mask) | (mmc3.reg[6] & mask)); + setprg8(0xA000, (base & ~mask) | (mmc3.reg[7] & mask)); + setprg8(0xC000, (base & ~mask) | (mmc3.reg[6] & mask)); + setprg8(0xE000, (base & ~mask) | (mmc3.reg[7] & mask)); + } + } else { + setprg8(A, (base & ~mask) | (V & mask)); + } +} + +static void M460CW(uint16 A, uint16 V) { + if (reg & 0x04) { + setchr2(0x0000, mmc3.reg[0] & 0xFE); + setchr2(0x0800, mmc3.reg[1] | 0x01); + setchr2(0x1000, mmc3.reg[2]); + setchr2(0x1800, mmc3.reg[5]); + } else { + setchr8r(0x10, 0); + } +} + +static DECLFR(M460Read) { + /* Menu selection by selectively connecting reg's D7 to PRG /CE or not */ + if ((reg & 0x80) && (dipsw & 0x01)) { + return CPU_OPENBUS; + } + return CartBR(A); +} + +static DECLFW(M460Write) { + if (MMC3_WramIsWritable()) { + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); + } +} + +static void M460Reset(void) { + reg = 0; + dipsw++; + MMC3_Reset(); +} + +static void M460Power(void) { + reg = 0; + dipsw = 0; + MMC3_Power(); + SetReadHandler(0x8000, 0xFFFF, M460Read); + SetWriteHandler(0x6000, 0x7FFF, M460Write); +} + +static void M460close(void) { + MMC3_Close(); +} + +void Mapper460_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M460CW; + MMC3_pwrap = M460PW; + info->Power = M460Power; + info->Reset = M460Reset; + info->Close = M460close; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAM = (uint8 *)FCEU_gmalloc(8192); + SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); + AddExState(CHRRAM, 8192, 0, "CRAM"); +} diff --git a/src/mappers/mapper461.c b/src/mappers/mapper461.c new file mode 100644 index 000000000..01fad0118 --- /dev/null +++ b/src/mappers/mapper461.c @@ -0,0 +1,40 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = (latch.addr << 1) | ((latch.addr >> 5) & 0x01); + uint8 chr = latch.addr >> 8; + + if (!(latch.addr & 0x10)) { + setprg32(0x8000, prg >> 1); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + setchr8(chr); + setmirror(((latch.addr >> 7) & 0x01) ^ 0x01); +} + +void Mapper461_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); +} diff --git a/src/mappers/mapper463.c b/src/mappers/mapper463.c new file mode 100644 index 000000000..813afe95f --- /dev/null +++ b/src/mappers/mapper463.c @@ -0,0 +1,77 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 regs[4]; +static uint8 dipsw; + +static SFORMAT StateRegs[] = { + { regs, 4, "EXPR" }, + { &dipsw, 1, "DPSW" }, + { 0 } +}; + +static void Sync(void) { + uint8 prg = regs[1]; + uint8 chr = regs[2]; + uint8 mirr = (regs[0] & 0x01) ^ 0x01; + + if (regs[0] & 0x04) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { + setprg32(0x8000, prg >> 1); + } + setchr8(chr); + setmirror(mirr); +} + +static DECLFW(M463Write5000) { + if (A & (0x10 << dipsw)) { + regs[A & 0x03] = V; + Sync(); + } +} + +static void M463Reset(void) { + dipsw = (dipsw + 1) & 0x07; + regs[0] = regs[1] = regs[2] = regs[3] = 0; + Sync(); +} + +static void M463Power(void) { + dipsw = 0; + regs[0] = regs[1] = regs[2] = regs[3] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, M463Write5000); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper463_Init(CartInfo *info) { + info->Power = M463Power; + info->Reset = M463Reset; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper464.c b/src/mappers/mapper464.c new file mode 100644 index 000000000..327f94254 --- /dev/null +++ b/src/mappers/mapper464.c @@ -0,0 +1,42 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = latch.addr >> 7; + uint8 chr = latch.addr & 0x1F; + uint8 mirr = ((latch.addr >> 5) & 0x01) ^ 0x01; + + if (latch.addr & 0x40) { + setprg32(0x8000, prg >> 1); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + setchr8(chr); + setmirror(mirr); +} + +void Mapper464_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper465.c b/src/mappers/mapper465.c new file mode 100644 index 000000000..272c43e3a --- /dev/null +++ b/src/mappers/mapper465.c @@ -0,0 +1,62 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + uint8 prg = ((latch.addr >> 2) & 0x1F) | ((latch.addr >> 5) & 0x20); + + if (latch.addr & 0x200) { + /* unrom */ + setprg16(0x8000, (prg & ~0x07) | (latch.data & 0x07)); + setprg16(0xC000, prg | 0x07); + } else { + if (latch.addr & 0x01) { + setprg32(0x8000, prg >> 1); + } else { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } + } + setchr8(0); + setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); +} + +static DECLFW(M465WriteLatch) { + if (latch.addr & 0x200) { + /* unrom latch */ + latch.data = V; + } else { + latch.addr = A & 0xFFFF; + } + Sync(); +} + +static void M465Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M465WriteLatch); +} + +void Mapper465_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M465Power; + info->Reset = Latch_RegReset; +} \ No newline at end of file diff --git a/src/mappers/mapper466.c b/src/mappers/mapper466.c new file mode 100644 index 000000000..216a3de33 --- /dev/null +++ b/src/mappers/mapper466.c @@ -0,0 +1,108 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 regs[4]; + +static SFORMAT StateRegs[] = { + { regs, 4, "EXPR" }, + { 0 } +}; + +static uint32 getPRGBank(void) { + return ((regs[1] << 5) | ((regs[0] << 1) & 0x1E) | ((regs[0] >> 5) & 0x01)); +} + +static void Sync(void) { + uint32 prg = getPRGBank(); + + if (regs[0] & 0x40) { + if (regs[0] & 0x10) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else { + setprg32(0x8000, prg >> 1); + } + } else { + setprg16(0x8000, (prg & ~0x07) | (regs[2] & 0x07)); + setprg16(0xC000, (prg & ~0x07) | 0x07); + } + setprg8r(0x10, 0x6000, 0); + setchr8(0); + setmirror(((regs[0] >> 7) & 0x01) ^ 0x01); +} + +static DECLFR(M466ReadLatch) { + /* Return open bus when selecting unpopulated PRG chip */ + if ((getPRGBank() & 0x20) && (PRGsize[0] < (1024 * 1024))) { + return CPU_OPENBUS; + } + return CartBR(A); +} + +static DECLFW(M466Write5000) { + regs[(A >> 11) & 0x01] = A & 0xFF; + Sync(); +} + +static DECLFW(M466WriteLatch) { + regs[2] = V; + Sync(); +} + +static void M466Reset(void) { + regs[0] = regs[1] = 0; + Sync(); +} + + +static void M466Close(void) { +} + +static void M466Power(void) { + regs[0] = regs[1] = 0; + Sync(); + + SetReadHandler(0x8000, 0xFFFF, M466ReadLatch); + SetWriteHandler(0x5000, 0x5FFF, M466Write5000); + SetWriteHandler(0x8000, 0xFFFF, M466WriteLatch); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper466_Init(CartInfo *info) { + info->Power = M466Power; + info->Close = M466Close; + info->Reset = M466Reset; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper467.c b/src/mappers/mapper467.c new file mode 100644 index 000000000..e25135cb9 --- /dev/null +++ b/src/mappers/mapper467.c @@ -0,0 +1,102 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M467PW(uint16 A, uint16 V) { + if (reg & 0x20) { + uint8 mask = (reg & 0x40) ? 0x0F : 0x03; + uint8 base = reg << 1; + + setprg8(A, (base & ~mask) | (V & mask)); + } else { + setprg16(0x8000, reg & 0x1F); + setprg16(0xC000, reg & 0x1F); + } +} + +static void M467CHR(void) { + uint16 base = (reg << 2) & 0x100; + + if (reg & 0x40) { + setchr2(0x0000, base | (mmc3.reg[0] & ~0x01)); + setchr2(0x0800, base | (mmc3.reg[0] | 0x01)); + setchr2(0x1000, base | mmc3.reg[2]); + setchr2(0x1800, base | mmc3.reg[3]); + } else { + setchr2(0x0000, base | (mmc3.reg[0] & ~0x03) | 0); + setchr2(0x0800, base | (mmc3.reg[0] & ~0x03) | 1); + setchr2(0x1000, base | (mmc3.reg[2] & ~0x03) | 2); + setchr2(0x1800, base | (mmc3.reg[3] & ~0x03) | 3); + } +} + +static void M467MIR(void) { + setmirror(((reg >> 7) & 0x01) ^ 0x01); +} + +static DECLFW(M467Write) { + switch (A & 0xF000) { + case 0x9000: + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + default: + switch (A & 0xE001) { + case 0x8000: + mmc3.cmd = V & 0x3F; + break; + case 0x8001: + mmc3.reg[mmc3.cmd & 0x07] = V; + if (mmc3.cmd < 6) MMC3_FixCHR(); + else MMC3_FixPRG(); + break; + case 0xA000: + break; + } + } +} + + +static void M467Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void M467Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x8000, 0xBFFF, M467Write); +} + +void Mapper467_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_FixCHR = M467CHR; + MMC3_FixMIR = M467MIR; + MMC3_pwrap = M467PW; + info->Power = M467Power; + info->Reset = M467Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper471.c b/src/mappers/mapper471.c new file mode 100644 index 000000000..14ec8262d --- /dev/null +++ b/src/mappers/mapper471.c @@ -0,0 +1,52 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 471 denotes the Impact Soft IM1 circuit board, used for Haratyler (without HG or MP) and Haraforce. + * It is basically INES Mapper 201 with the addition of a scanline IRQ.*/ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, latch.addr); + setchr8(latch.addr); +} + +static DECLFW(M471Write) { + X6502_IRQEnd(FCEU_IQEXT); + Latch_Write(A, V); +} + +static void M471HBHook(void) { + X6502_IRQBegin(FCEU_IQEXT); +} + +static void M471Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M471Write); +} + +void Mapper471_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M471Power; + info->Reset = Latch_RegReset; + GameHBIRQHook = M471HBHook; +} diff --git a/src/mappers/mapper500.c b/src/mappers/mapper500.c new file mode 100644 index 000000000..da176c706 --- /dev/null +++ b/src/mappers/mapper500.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg4(0x7000, 0); + setprg16(0x8000, (reg[0] << 3) | (latch.data & 0x07)); + setprg16(0xC000, (reg[0] << 3) | 0x07); + setchr8(0); + setmirror(reg[1] & 0x01); +} + +static DECLFW(M500WriteReg) { + if (!(reg[1] & 0x80)) { + reg[A & 0x01] = V; + Sync(); + } +} + +static void M500Power(void) { + reg[0] = reg[1] = 0; + Latch_Power(); + SetReadHandler(0x7000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x6FFF, M500WriteReg); +} + +void Mapper500_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M500Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper501.c b/src/mappers/mapper501.c new file mode 100644 index 000000000..b0bad58c4 --- /dev/null +++ b/src/mappers/mapper501.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg4(0x7000, 0); + setprg32(0x8000, (reg[0] << 2) + (latch.data & 0x07)); + setchr8(0); + setmirror(MI_0 + ((latch.data >> 4) & 0x01)); +} + +static DECLFW(M501WriteReg) { + if (!(reg[1] & 0x80)) { + reg[A & 0x01] = V; + Sync(); + } +} + +static void M501Power(void) { + reg[0] = reg[1] = 0; + Latch_Power(); + SetReadHandler(0x7000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x6FFF, M501WriteReg); +} + +void Mapper501_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M501Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper502.c b/src/mappers/mapper502.c new file mode 100644 index 000000000..1df5fa74e --- /dev/null +++ b/src/mappers/mapper502.c @@ -0,0 +1,68 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 reg[2]; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { 0 } +}; + +static void Sync(void) { + uint8 mask = (8 << ((reg[1] >> 4) & 0x03)) - 1; + + setprg4(0x7000, 0); + if (reg[1] & 0x06) { + setprg32(0x8000, (reg[0] << 2) + (latch.data & (mask >> 1))); + } else { + setprg16(0x8000, (reg[0] << 3) + (latch.data & mask)); + setprg16(0xC000, (reg[0] << 3) + mask); + } + setchr8(0); + if (reg[1] & 0x02) { + setmirror(MI_0 + ((latch.data >> 4) & 0x01)); + } else { + setmirror(reg[1] & 0x01); + } +} + +static DECLFW(M502WriteReg) { + if (!(reg[1] & 0x80)) { + reg[A & 0x01] = V; + Sync(); + } +} + +static void M502Power(void) { + reg[0] = reg[1] = 0; + Latch_Power(); + SetReadHandler(0x7000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x6FFF, M502WriteReg); +} + +void Mapper502_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M502Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper512.c b/src/mappers/mapper512.c new file mode 100644 index 000000000..5ad27d824 --- /dev/null +++ b/src/mappers/mapper512.c @@ -0,0 +1,85 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * 8-in-1 Rockin' Kats, Snake, (PCB marked as "8 in 1"), similar to 12IN1, + * but with MMC3 on board, all games are hacked the same, Snake is buggy too! + * + * no reset-citcuit, so selected game can be reset, but to change it you must use power + * + */ + +/* NES 2.0 Mapper 512 is used for 中國大亨 (Zhōngguó Dàhēng) */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M512MIR(void) { + if (reg == 1) { + SetupCartMirroring(4, 0, &CHRRAM[4096]); + } else { + setmirror((mmc3.mirr & 0x01) ^ 0x01); + } +} + +static void M512CW(uint16 A, uint16 V) { + if (reg & 0x02) { + setchr1r(0x10, A, (V & 0x03)); + } else { + setchr1(A, V & 0xFF); + } +} + +static void M512PW(uint16 A, uint16 V) { + setprg8(A, (V & 0x3F)); +} + +static DECLFW(M512Write) { + if (A & 0x100) { + reg = V & 0x03; + MMC3_FixCHR(); + MMC3_FixMIR(); + } +} + +static void M512Close(void) { + MMC3_Close(); +} + +static void M512Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x4100, 0x4FFF, M512Write); +} + +void Mapper512_Init(CartInfo *info) { + MMC3_Init(info, 8, info->battery); + MMC3_cwrap = M512CW; + MMC3_pwrap = M512PW; + MMC3_FixMIR = M512MIR; + info->Power = M512Power; + info->Close = M512Close; + AddExState(®, 1, 0, "EXPR"); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); +} diff --git a/src/mappers/mapper513.c b/src/mappers/mapper513.c new file mode 100644 index 000000000..dffc90119 --- /dev/null +++ b/src/mappers/mapper513.c @@ -0,0 +1,85 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 513 - Sachen UNL-SA-9602B */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M513CW(uint16 A, uint16 V) { + setchr1(A, V & 0x3F); +} + +static void M513PW(uint16 A, uint16 V) { + if (!(A & 0x4000)) { + setprg8(A, (reg & 0xC0) | (V & 0x3F)); + } else { + setprg8(A, (V & 0x3F)); + } +} + +static DECLFW(M513Write) { + switch (A & 0xE001) { + case 0x8000: + mmc3.cmd = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + break; + case 0x8001: + mmc3.reg[mmc3.cmd & 0x07] = V; + switch (mmc3.cmd & 0x07) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + reg = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + break; + default: + MMC3_FixPRG(); + break; + } + default: + break; + } +} + +static void M513Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x8000, 0x9FFF, M513Write); +} + +void Mapper513_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_pwrap = M513PW; + MMC3_cwrap = M513CW; + mmc3.opts |= 2; + info->SaveGame[0] = CHR_ROM_DATA; + info->SaveGameLen[0] = info->CHRRamSaveSize; + info->Power = M513Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper514.c b/src/mappers/mapper514.c new file mode 100644 index 000000000..956cf66fe --- /dev/null +++ b/src/mappers/mapper514.c @@ -0,0 +1,95 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" + +static uint8 mode; +static uint32 lastnt; + +static SFORMAT StateRegs[] = { + { &mode, 1, "MODE" }, + { &lastnt, 4, "LSNT" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, mode & 0x3F); + setchr4(0x0000, lastnt); + setchr4(0x1000, 1); + setmirror(((mode >> 6) & 0x01) ^ 0x01); +} + +static DECLFW(M514Write8) { + if ((A & 0xFFF) == 0) { + mode = V; + Sync(); + } +} + +static void M514PPUHook(uint32 A) { + if ((A & 0x3000) == 0x2000) { + uint32 mask = (mode & 0x40) ? 0x02 : 0x01; + uint32 bank = A >> 10; + if ((mode & 0x80) && (bank & mask)) { + setchr4(0, 1); + lastnt = 1; + } else { + lastnt = 0; + setchr4(0, 0); + } + } +} + +static void M514Reset(void) { + lastnt = 0; + mode = 0; + Sync(); +} + +static void M514Power(void) { + lastnt = 0; + mode = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x8FFF, M514Write8); +} + +static void M514Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper514_Init(CartInfo *info) { + info->Power = M514Power; + info->Reset = M514Reset; + info->Close = M514Close; + PPU_hook = M514PPUHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper516.c b/src/mappers/mapper516.c new file mode 100644 index 000000000..05d7874f5 --- /dev/null +++ b/src/mappers/mapper516.c @@ -0,0 +1,61 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 516 - Brilliant Com Cocoma Pack */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void M516CW(uint16 A, uint16 V) { +/* FCEU_printf("CHR: A:%04x V:%02x R0:%02x\n", A, V, reg); */ + setchr1(A, ((reg << 5) & 0x180) | (V & 0x7F)); +} + +static void M516PW(uint16 A, uint16 V) { +/* FCEU_printf("PRG: A:%04x V:%02x R0:%02x\n", A, V, reg); */ + setprg8(A, ((reg << 4) & 0x30) | (V & 0x0F)); +} + +static DECLFW(M516Write) { +/* FCEU_printf("Wr: A:%04x V:%02x R0:%02x\n", A, V, reg); */ + if (A & 0x10) { + reg = A & 0x0F; + MMC3_FixPRG(); + MMC3_FixCHR(); + } + MMC3_Write(A, V); +} + +static void M516Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x8000, 0xFFFF, M516Write); +} + +void Mapper516_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M516CW; + MMC3_pwrap = M516PW; + info->Power = M516Power; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/mapper517.c b/src/mappers/mapper517.c new file mode 100644 index 000000000..c89756310 --- /dev/null +++ b/src/mappers/mapper517.c @@ -0,0 +1,101 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" +#include "latch.h" + +static int32 adc_data; +static int32 adc_high; +static int32 adc_low; +static uint8 adc_state; + +static SFORMAT StateRegs[] = { + { &adc_data, sizeof(adc_data), "DATA" }, + { &adc_high, sizeof(adc_high), "DTHI" }, + { &adc_low, sizeof(adc_low), "DTLO" }, + { &adc_state, sizeof(adc_state), "STAT" }, + { 0 }, +}; + +static void Sync(void) { + setprg16(0x8000, latch.data); + setprg16(0xC000, ~0); + setchr8(0); +} + +static DECLFR(M517Read) { + uint8 result = 0; + if (A == 0x6000) { + switch (adc_state) { + case 0: + adc_state = 1; + result = 0; + break; + case 1: + adc_state = 2; + result = 1; + break; + case 2: + if (adc_low > 0) { + adc_low--; + result = 1; + } else { + adc_state = 0; + result = 0; + } + break; + } + } else { + result = adc_high-- > 0 ? 0 : 1; + } + return result; +} + +static DECLFW(M517Write) { + /* TODO: implement mic input from frontend */ + /* adc_data = MIC * 63.0; */ + adc_data = 0.0 * 63.0; + adc_high = adc_data >> 2; + adc_low = 0x40 - adc_high - ((adc_data & 0x03) << 2); + adc_state = 0; + Latch_Write(A,V); +} + +static void M517Reset(void) { + adc_data = 0; + adc_state = 0; + Sync(); +} + +static void M517Power(void) { + adc_data = 0; + adc_state = 0; + Latch_Power(); + SetReadHandler(0x6000, 0x6FFF, M517Read); + SetWriteHandler(0x8000, 0x8FFF, M517Write); +} + +void Mapper517_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M517Power; + info->Reset = M517Reset; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper518.c b/src/mappers/mapper518.c new file mode 100644 index 000000000..cf1023e2b --- /dev/null +++ b/src/mappers/mapper518.c @@ -0,0 +1,109 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Dance 2000 12-in-1 + * + */ + +#include "mapinc.h" + +static uint8 prg, mode; +static uint32 lastnt = 0; + +static SFORMAT StateRegs[] = +{ + { &prg, 1, "REGS" }, + { &mode, 1, "MODE" }, + { &lastnt, 4, "LSNT" }, + { 0 } +}; + +static void Sync(void) { + setmirror((mode ^ 1) & 1); + setprg8r(0x10, 0x6000, 0); + setchr4(0x0000, lastnt); + setchr4(0x1000, 1); + if (mode & 4) { + setprg32(0x8000, prg & 7); + } else { + setprg16(0x8000, prg & 0x0f); + setprg16(0xC000, 0); + } +} + +static DECLFW(M518Write) { + switch (A) { + case 0x5000: prg = V; Sync(); break; + case 0x5200: mode = V; if (mode & 4) Sync(); break; + } +} + +static DECLFR(M518Read) { + if (prg & 0x40) + return CPU_OPENBUS; + else + return CartBR(A); +} + +static void M518Power(void) { + prg = mode = 0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, M518Read); + SetWriteHandler(0x5000, 0x5FFF, M518Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M518PPUHook(uint32 A) { + if (mode & 2) { + if ((A & 0x3000) == 0x2000) { + uint32 curnt = A & 0x800; + if (curnt != lastnt) { + setchr4(0x0000, curnt >> 11); + lastnt = curnt; + } + } + } else { + lastnt = 0; + setchr4(0x0000, 0); + } +} + +static void M518Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper518_Init(CartInfo *info) { + info->Power = M518Power; + info->Close = M518Close; + PPU_hook = M518PPUHook; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper519.c b/src/mappers/mapper519.c new file mode 100644 index 000000000..e756ada64 --- /dev/null +++ b/src/mappers/mapper519.c @@ -0,0 +1,86 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2015 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 519 + * UNIF board name UNL-EH8813A + */ + +#include "mapinc.h" +#include "latch.h" + +static uint8 lock, dipsw, chr, ram[4]; + +static SFORMAT StateRegs[] = { + { &dipsw, 1, "DPSW" }, + { &lock, 1, "LOCK" }, + { &chr, 1, "CREG" }, + { 0 } +}; + +static void Sync(void) { + if (lock == 0) { + if (latch.addr & 0x80) { + setprg16(0x8000, latch.addr); + setprg16(0xC000, latch.addr); + } else { + setprg32(0x8000, latch.addr >> 1); + } + setmirror(((latch.data >> 7) & 0x01) ^ 0x01); + lock = (latch.addr & 0x100) == 0x100; + chr = latch.data & 0x7C; + } + setchr8(chr | (latch.data & 0x03)); +} + +static DECLFR(M519ReadRAM) { + return ram[A & 0x03]; +} + +static DECLFW(M519WriteRAM) { + ram[A & 0x03] = V & 0x0F; +} + +static DECLFR(M519Read) { + if (latch.addr & 0x40) { + return CartBR((A & 0xFFF0) | (dipsw & 0x0F)); + } + return CartBR(A); +} + +static void M519Power(void) { + dipsw = lock = 0; + Latch_Power(); + SetReadHandler(0x5800, 0x5FFF, M519ReadRAM); + SetWriteHandler(0x5800, 0x5FFF, M519WriteRAM); +} + +static void M519Reset(void) { + lock = 0; + dipsw++; + Latch_RegReset(); +} + +void Mapper519_Init(CartInfo *info) { + Latch_Init(info, Sync, M519Read, FALSE, FALSE); + info->Reset = M519Reset; + info->Power = M519Power; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper520.c b/src/mappers/mapper520.c new file mode 100644 index 000000000..cad8d0e47 --- /dev/null +++ b/src/mappers/mapper520.c @@ -0,0 +1,57 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 520 - VRC4 clone + * Datach Dragon Ball Z/Datach Yu Yu Hakusho + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 PPUCHRBus; + +static SFORMAT StateRegs[] = { + { &PPUCHRBus, 1, "PPUC" }, + { 0 }, +}; + +static void M520PW(uint16 A, uint16 V) { + setprg8(A, ((vrc24.chr[PPUCHRBus] << 2) & 0x20) | (V & 0x1F)); +} + +static void M520CW(uint16 A, uint16 V) { + setchr1(A, V & 0x07); +} + +static void M520PPUHook(uint32 A) { + uint8 bank = (A & 0x1FFF) >> 10; + if ((PPUCHRBus != bank) && ((A & 0x3000) != 0x2000)) { + PPUCHRBus = bank; + VRC24_FixPRG(); + } +} + +void Mapper520_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x04, 0x08, 0, 1); + PPU_hook = M520PPUHook; + VRC24_pwrap = M520PW; + VRC24_cwrap = M520CW; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper521.c b/src/mappers/mapper521.c new file mode 100644 index 000000000..3212daf59 --- /dev/null +++ b/src/mappers/mapper521.c @@ -0,0 +1,52 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg; + +static void Sync(void) { + setprg16(0x8000, prg); + setprg16(0xC000, 0x08); + setchr8(0); +} + +static DECLFW(M521Write) { + prg = V; + Sync(); +} + +static void M521Power(void) { + prg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5020, 0x5020, M521Write); +} + +static void Restore(int version) { + Sync(); +} + +void Mapper521_Init(CartInfo *info) { + GameStateRestore = Restore; + info->Power = M521Power; + AddExState(&prg, 1, 0, "LATC"); +} diff --git a/src/mappers/mapper522.c b/src/mappers/mapper522.c new file mode 100644 index 000000000..c7302892e --- /dev/null +++ b/src/mappers/mapper522.c @@ -0,0 +1,83 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 522 - UNL-LH10 + * + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg[8], cmd; + +static SFORMAT StateRegs[] = +{ + { &cmd, 1, "CMD" }, + { reg, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, ~1); + setprg8(0x8000, reg[6]); + setprg8(0xA000, reg[7]); + setprg8r(0x10, 0xC000, 0); + setprg8(0xE000, ~0); + setchr8(0); + setmirror(0); +} + +static DECLFW(M522Write) { + if (A & 0x0001) { + reg[cmd & 0x07] = V; + Sync(); + } else { + cmd = V; + } +} + +static void M522Power(void) { + FDSSound_Power(); + reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = reg[6] = reg[7] = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x9FFF, M522Write); + SetWriteHandler(0xC000, 0xDFFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M522Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper522_Init(CartInfo *info) { + info->Power = M522Power; + info->Close = M522Close; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper524.c b/src/mappers/mapper524.c new file mode 100644 index 000000000..e0106b3bc --- /dev/null +++ b/src/mappers/mapper524.c @@ -0,0 +1,74 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 524 - BTL-900218 */ +/* http://wiki.nesdev.com/w/index.php/UNIF/900218 + * NES 2.0 Mapper 524 describes the PCB used for the pirate port Lord of King or Axe of Fight. + * UNIF board name is BTL-900218. + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint16 IRQCount; +static uint8 IRQa; + +static SFORMAT IRQStateRegs[] = { + { &IRQCount, 2, "IRQC" }, + { &IRQa, 1, "IRQA" }, + + { 0 } +}; + +static DECLFW(M524Write) { + switch (A & 0xF00C) { + case 0xF008: + IRQa = 1; + break; + case 0xF00C: + IRQa = 0; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +static void M524IRQHook(int a) { + if (!IRQa) + return; + + IRQCount += a; + if (IRQCount & 1024) + X6502_IRQBegin(FCEU_IQEXT); +} + +static void M524Power(void) { + IRQa = IRQCount = 0; + VRC24_Power(); + SetWriteHandler(0xF000, 0xFFFF, M524Write); +} + +void Mapper524_Init(CartInfo *info) { + VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); + info->Power = M524Power; + MapIRQHook = M524IRQHook; + AddExState(IRQStateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper525.c b/src/mappers/mapper525.c new file mode 100644 index 000000000..15c45c103 --- /dev/null +++ b/src/mappers/mapper525.c @@ -0,0 +1,87 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES Mapper 525 - UNL-M525 + * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_525 + * NES 2.0 Mapper 525 is used for a bootleg version of versions of Contra and 月風魔伝 (Getsu Fūma Den). + * Its similar to Mapper 23 Submapper 3) with non-nibblized CHR-ROM bank registers. + */ + +#include "mapinc.h" + +static uint8 prg; +static uint8 chr[8]; +static uint8 mirr; + +static SFORMAT StateRegs[] = { + { chr, 8, "CHRR" }, + { &prg, 1, "PRGR" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, prg >> 1); + setprg16(0xC000, ~0); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + setmirror((mirr & 0x01) ^ 0x01); +} + +static DECLFW(M525WritePRG) { + prg = V; + Sync(); +} + +static DECLFW(M525WriteMIR) { + prg = V; + Sync(); +} + +static DECLFW(M525WriteCHR) { + chr[A & 0x07] = V; + Sync(); +} + +static void M525Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x8FFF, M525WritePRG); + SetWriteHandler(0x9000, 0x9FFF, M525WriteMIR); + SetWriteHandler(0xB000, 0xBFFF, M525WriteCHR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper525_Init(CartInfo *info) { + info->Power = M525Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper526.c b/src/mappers/mapper526.c new file mode 100644 index 000000000..a15e8b0de --- /dev/null +++ b/src/mappers/mapper526.c @@ -0,0 +1,123 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 526 is used for a bootleg version of Namco's 三国志: 中原の覇者 (Sangokushi: Chūgen no Hasha). + * Its UNIF board name is UNL-BJ-56. + * Mirroring seems to be hard-wired (to vertical). + * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_526 + */ + +#include "mapinc.h" + +static uint8 prg[4], chr[8]; +static uint32 IRQCount; + +static SFORMAT StateRegs[] = { + { prg, 4, "PREG" }, + { chr, 8, "CREG" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, prg[3]); + + setchr1(0x0000, chr[0]); + setchr1(0x0400, chr[1]); + setchr1(0x0800, chr[2]); + setchr1(0x0C00, chr[3]); + setchr1(0x1000, chr[4]); + setchr1(0x1400, chr[5]); + setchr1(0x1800, chr[6]); + setchr1(0x1C00, chr[7]); + + setmirror(MI_V); +} + +static DECLFW(M526Write) { + /* FCEU_printf("Wr: A:%04x V:%02x\n", A, V); */ + switch (A & 0x0F) { + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + chr[A & 0x07] = V; + Sync(); + break; + case 0x08: case 0x09: case 0x0A: case 0x0B: + prg[A & 0x03] = V; + Sync(); + break; + case 0x0D: + case 0x0F: + /* One of these two acknowledges a pending IRQ, and the other + * resets to IRQ counter to zero. Because they are always written + * to one after the other, it's not clear which one does which. */ + X6502_IRQEnd(FCEU_IQEXT); + IRQCount = 0; + break; + } +} + +static void M526IRQHook(int a) { + IRQCount += a; + if (IRQCount & 0x1000) { + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void M526Close(void) { +} + +static void M526Power(void) { + prg[0] = ~3; + prg[1] = ~2; + prg[2] = ~1; + prg[3] = ~0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0x800F, M526Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper526_Init(CartInfo *info) { + info->Power = M526Power; + info->Close = M526Close; + MapIRQHook = M526IRQHook; + GameStateRestore = StateRestore; + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper527.c b/src/mappers/mapper527.c new file mode 100644 index 000000000..46b79012d --- /dev/null +++ b/src/mappers/mapper527.c @@ -0,0 +1,40 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 527 is used for a bootleg version of + * Taito's 不動明王伝 (Fudō Myōō Den). + * Its UNIF board name is UNL-AX-40G. The original INES Mapper 207 is + * replaced with a VRC2 clone (A0/A1, i.e. VRC2b) while retaining + * Mapper 207's extended mirroring. + */ + +#include "mapinc.h" +#include "vrc24.h" + +static void M527CW(uint16 A, uint16 V) { + setchr1(A, V); + setmirrorw((vrc24.chr[0] >> 7) & 1, (vrc24.chr[0] >> 7) & 1, (vrc24.chr[1] >> 7) & 1, (vrc24.chr[1] >> 7) & 1); +} + +void Mapper527_Init(CartInfo *info) { + VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); + VRC24_cwrap = M527CW; +} diff --git a/src/mappers/mapper528.c b/src/mappers/mapper528.c new file mode 100644 index 000000000..083f7c785 --- /dev/null +++ b/src/mappers/mapper528.c @@ -0,0 +1,98 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 528 + * UNIF BMC-831128C + */ + +#include "mapinc.h" +#include "fme7.h" +#include "vrcirq.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = { + { ®, 1, "REGS" }, + { 0 } +}; + +static void M528CW(uint16 A, uint16 V) { + uint16 mask = 0xFF; + uint16 base = reg << 4; + + setchr1(A, (base | (V & mask))); +} + +static void M528PW(uint16 A, uint16 V) { + uint16 base = reg; + uint16 mask = base | 0x0F; + + setprg8(A, base + (V & mask)); +} + +static void M528SyncWRAM(void) { + uint16 base = reg; + uint16 mask = base | 0x0F; + + if (fme7.prg[0] == 1) { + setprg8r(0x10, 0x6000, 0); + } else { + setprg8(0x6000, (base + (fme7.prg[0] & mask))); + } +} + +static DECLFW(M528Write) { + switch (A & 0x0F) { + case 0x0B: break; + case 0x0D: VRCIRQ_Control(V); break; + case 0x0E: VRCIRQ_Acknowledge(); break; + case 0x0F: VRCIRQ_Latch(V); break; + default: + FME7_WriteIndex(0x8000, A & 0x0F); + FME7_WriteReg(0xA000, V); + break; + } + reg = (A & 0x4000) >> 10; + FME7_FixPRG(); + FME7_FixCHR(); + FME7_FixWRAM(); +} + +static void M528Power(void) { + reg = 0; + FME7_Power(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0xA000, 0xAFFF, M528Write); + SetWriteHandler(0xC000, 0xCFFF, M528Write); +} + +void Mapper528_Init(CartInfo *info) { + FME7_Init(info, TRUE, info->battery); + FME7_FixWRAM = M528SyncWRAM; + FME7_pwrap = M528PW; + FME7_cwrap = M528CW; + info->Power = M528Power; + AddExState(StateRegs, ~0, 0, NULL); + + VRCIRQ_Init(TRUE); + MapIRQHook = VRCIRQ_CPUHook; + AddExState(&VRCIRQ_StateRegs, ~0, 0, 0); +} diff --git a/src/mappers/mapper529.c b/src/mappers/mapper529.c new file mode 100644 index 000000000..5647f3941 --- /dev/null +++ b/src/mappers/mapper529.c @@ -0,0 +1,72 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 529 - YY0807/J-2148/T-230 + * UNIF UNL-T-230 + */ + +#include "mapinc.h" +#include "vrc24.h" +#include "eeprom_93Cx6.h" + +static uint8 haveEEPROM; +static uint8 eeprom_data[256]; + +static void M529PW(uint16 A, uint16 V) { + setprg16(0x8000, vrc24.prg[1]); + setprg16(0xC000, ~0); +} + +static DECLFR(M529EEPROMRead) { + if (haveEEPROM) { + return eeprom_93Cx6_read() ? 0x01 : 0x00; + } + return 0x01; +} + +static DECLFW(M529Write) { + if (A & 0x800) { + if (haveEEPROM) { + eeprom_93Cx6_write(!!(A & 0x04), !!(A & 0x02), !!(A & 0x01)); + } + } else { + VRC24_Write(A, V); + } +} + +static void M529Power(void) { + VRC24_Power(); + SetReadHandler(0x5000, 0x5FFF, M529EEPROMRead); + SetWriteHandler(0x8000, 0xFFFF, M529Write); +} + +void Mapper529_Init(CartInfo *info) { + haveEEPROM = (info->PRGRamSaveSize & 0x100) != 0; + VRC24_Init(info, VRC4, 0x04, 0x08, !haveEEPROM, 1); + info->Power = M529Power; + VRC24_pwrap = M529PW; + if (haveEEPROM) { + eeprom_93Cx6_init(eeprom_data, 256, 16); + info->battery = 1; + info->SaveGame[0] = eeprom_data; + info->SaveGameLen[0] = 256; + } +} diff --git a/src/mappers/mapper530.c b/src/mappers/mapper530.c new file mode 100644 index 000000000..ef7b24915 --- /dev/null +++ b/src/mappers/mapper530.c @@ -0,0 +1,55 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 530 - UNL-AX5705 + * Super Bros. Pocker Mali (VRC4 mapper) + */ + +#include "mapinc.h" +#include "vrc24.h" + +static DECLFW(UNLAX5705Write) { + A |= (A & 0x0008) ? 0x1000 : 0x0000; + switch (A & 0xF000) { + case 0x8000: + case 0xA000: + V = ((V & 0x02) << 2) | ((V & 0x08) >> 2) | (V & 0x05); + break; + case 0xB000: + case 0xC000: + case 0xD000: + case 0xE000: + if (A & 0x0001) { + V = ((V & 0x04) >> 1) | ((V & 0x02) << 1) | (V & 0x09); + } + break; + } + VRC24_Write(A, V); +} + +static void M530Power(void) { + VRC24_Power(); + SetWriteHandler(0x8000, 0xFFFF, UNLAX5705Write); +} + +void Mapper530_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x01, 0x02, 0, 1); + info->Power = M530Power; +} diff --git a/src/mappers/mapper533.c b/src/mappers/mapper533.c new file mode 100644 index 000000000..14e478fc6 --- /dev/null +++ b/src/mappers/mapper533.c @@ -0,0 +1,48 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 533 is used for the Sachen 3014 board, used for the game + * 動動腦 II: 國中英文(一) (Dòngdòngnǎo II: Guózhōng Yīngwén (I), + * also known as Middle School English II, SA-003). + * It's a CNROM-like board with the added ability to read back + * the latch content for protection purposes. + */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8((latch.data >> 4) & 0x01); +} + +static DECLFR(M533Read) { + switch (A & 0xF000) { + case 0xE000: + return ((PRGptr[0][0x6000 | (A & 0xFFFF)] & 0xF0) | (latch.data >> 4)); + default: + break; + } + return CartBROB(A); +} + +void Mapper533_Init(CartInfo *info) { + Latch_Init(info, Sync, M533Read, FALSE, TRUE); +} diff --git a/src/mappers/mapper535.c b/src/mappers/mapper535.c new file mode 100644 index 000000000..3d31f637e --- /dev/null +++ b/src/mappers/mapper535.c @@ -0,0 +1,99 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NES 2.0 Mapper 535 - UNL-M535 + * FDS Conversion - Nazo no Murasamejō + * + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg, IRQa; +static int32 IRQCount; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg8(0x6000, reg); + setprg32(0x8000, 0x03); + setprg8r(0x10, 0xB800, 0); +} + +static DECLFW(M535RamWrite) { + WRAM[(A - 0xB800) & 0x1FFF] = V; +} + +static DECLFW(M535Write) { + reg = V; + Sync(); +} + +static DECLFW(M535IRQaWrite) { + IRQa = V & 0x02; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); +} + +static void M535IRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount > 7560) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M535Power(void) { + FDSSound_Power(); + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0xB800, 0xD7FF, M535RamWrite); + SetWriteHandler(0xE000, 0xEFFF, M535IRQaWrite); + SetWriteHandler(0xF000, 0xFFFF, M535Write); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M535Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper535_Init(CartInfo *info) { + info->Power = M535Power; + info->Close = M535Close; + MapIRQHook = M535IRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper538.c b/src/mappers/mapper538.c new file mode 100644 index 000000000..de337cf2f --- /dev/null +++ b/src/mappers/mapper538.c @@ -0,0 +1,80 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 538 denotes the 60-1064-16L PCB, used for a + * bootleg cartridge conversion named Super Soccer Champion + * of the Konami FDS game Exciting Soccer. + */ + +#include "mapinc.h" +#include "latch.h" +#include "fdssound.h" + +/* this code emulates rom dump with wrong bank order */ +static uint8 M538Banks[16] = { + 0, 1, 2, 1, 3, 1, 4, 1, + 5, 5, 1, 1, 6, 6, 7, 7 +}; + +static void Sync_alt(void) { + setprg8(0x6000, (latch.data >> 1) | 8); + setprg8(0x8000, M538Banks[latch.data & 0x0F]); + setprg8(0xA000, 14); + setprg8(0xC000, 7); + setprg8(0xE000, 15); + setchr8(0); + setmirror(1); +} + +static void Sync(void) { + setprg8(0x6000, latch.data | 1); + setprg8(0x8000, (latch.data & 1) && (~latch.data & 8) ? 10 : (latch.data & ~1)); + setprg8(0xA000, 13); + setprg8(0xC000, 14); + setprg8(0xE000, 15); + setchr8(0); + setmirror(MI_V); +} + +static DECLFW(M538Write) { + switch (A & 0xF000) { + case 0xC000: + case 0xD000: + latch.data = V; + Sync(); + break; + } +} + +static void M538Power(void) { + FDSSound_Power(); + Latch_RegReset(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M538Write); +} + +void Mapper538_Init(CartInfo *info) { + if (info->CRC32 == 0xA8C6D77D) { + Latch_Init(info, Sync_alt, NULL, 0, 0); + } + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M538Power; +} diff --git a/src/mappers/mapper539.c b/src/mappers/mapper539.c new file mode 100644 index 000000000..5a31b3372 --- /dev/null +++ b/src/mappers/mapper539.c @@ -0,0 +1,115 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* FDS Conversion - Kid Icarus (パルテナの鏡) (Parthena) */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 prg; +static uint8 mirr; + +static SFORMAT StateRegs[] = { + { &prg, 1, "PREG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, 0x0D); + setprg8(0x8000, 0x0C); + setprg8(0xA000, prg & 0x0F); + setprg8(0xC000, 0x0E); + setprg8(0xE000, 0x0F); + setchr8(0); + setmirror(((mirr & 8) >> 3) ^ 1); +} + +static DECLFR(M539ReadWRAM) { + A = (((A) & 0x1FFF) | (((A) < 0xC000) ? 0x1000 : 0x0000) | (((A) < 0x8000) ? 0x800 : 0x000)); + return WRAM[A]; +} + +static DECLFW(M539WriteWRAM) { + A = (((A) & 0x1FFF) | (((A) < 0xC000) ? 0x1000 : 0x0000) | (((A) < 0x8000) ? 0x800 : 0x000)); + WRAM[A] = V; +} + +static DECLFW(M539WritePRG) { + prg = V; + Sync(); +} + +static DECLFW(M539WriteMirroring) { + if ((A & 0x25) == 0x25) { + mirr = V; + Sync(); + } +} + +static void M539Power(void) { + FDSSound_Power(); + prg = 0; + mirr = 0; + Sync(); + + SetReadHandler(0x6000, 0xFFFF, CartBR); + + SetWriteHandler(0xA000, 0xAFFF, M539WritePRG); + SetWriteHandler(0xF000, 0xFFFF, M539WriteMirroring); + + /* Certain ranges in the CPU address space are overlaid with portions of 8 KiB of PRG-RAM as follows: + * CPU $6000-$60FF + * CPU $6200-$62FF + * CPU $6400-$65FF + * CPU $8200-$82FF + * CPU $C000-$D1FF + * CPU $DF00-$DFFF + */ + + SetReadHandler(0x6000, 0x60FF, M539ReadWRAM); + SetReadHandler(0x6200, 0x62FF, M539ReadWRAM); + SetReadHandler(0x6400, 0x65FF, M539ReadWRAM); + SetReadHandler(0x8200, 0x82FF, M539ReadWRAM); + SetReadHandler(0xC000, 0xD1FF, M539ReadWRAM); + SetReadHandler(0xDF00, 0xDFFF, M539ReadWRAM); + + SetWriteHandler(0x6000, 0x60FF, M539WriteWRAM); + SetWriteHandler(0x6200, 0x62FF, M539WriteWRAM); + SetWriteHandler(0x6400, 0x65FF, M539WriteWRAM); + SetWriteHandler(0x8200, 0x82FF, M539WriteWRAM); + SetWriteHandler(0xC000, 0xD1FF, M539WriteWRAM); + SetWriteHandler(0xDF00, 0xDFFF, M539WriteWRAM); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper539_Init(CartInfo *info) { + info->Power = M539Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper541.c b/src/mappers/mapper541.c new file mode 100644 index 000000000..38193fe77 --- /dev/null +++ b/src/mappers/mapper541.c @@ -0,0 +1,54 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* LittleCom 160-in-1 multicart */ + +#include "mapinc.h" +#include "latch.h" + +static void Sync(void) { + if (latch.addr & 2) { /* NROM-128 */ + setprg16(0x8000, latch.addr >> 2); + setprg16(0xC000, latch.addr >> 2); + } else { /* NROM=256 */ + setprg32(0x8000, latch.addr >> 3); + } + setchr8(0); + setmirror(latch.addr & 0x01); +} + +static DECLFW(M541Write) { + if (A >= 0xC000) { + latch.addr = A; + Sync(); + } +} + +static void M541Power(void) { + Latch_Power(); + SetWriteHandler(0x8000, 0xFFFF, M541Write); +} + +void Mapper541_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, FALSE); + info->Power = M541Power; + info->Reset = Latch_RegReset; +} diff --git a/src/mappers/mapper543.c b/src/mappers/mapper543.c new file mode 100644 index 000000000..b3b9562e2 --- /dev/null +++ b/src/mappers/mapper543.c @@ -0,0 +1,90 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 543 - 1996 無敵智カ卡 5-in-1 (CH-501) */ +/* NOTE: needs RAM to be initialized to all 0x00 */ + +#include "mapinc.h" +#include "mmc1.h" + +static uint8 reg; +static uint8 bits; +static uint8 shift; + +static SFORMAT StateRegs[] = { + { &bits, 1, "BITS" }, + { &shift, 1, "SHFT" }, + { ®, 1, "REG0" }, + { 0 } +}; + +static void M543PW(uint16 A, uint16 V) { + setprg16(A, (reg << 4) | (V & 0x0F)); +} + +static void M543CW(uint16 A, uint16 V) { + setchr4(A, (V & 0x07)); +} + +static void M543WW(void) { + uint32 wramBank; + + if (reg & 0x02) { + wramBank = 0x04 | ((reg >> 1) & 0x02) | (reg & 0x01) ; + } else { + wramBank = ((reg << 1) & 0x02) | ((MMC1_GetCHRBank(0) >> 3) & 0x01); + } + setprg8r(0x10, 0x6000, wramBank); +} + +static DECLFW(M543Write) { + bits |= ((V >> 3) & 0x01) << shift++; + if (shift == 4) { + reg = bits; + bits = shift = 0; + MMC1_FixPRG(); + MMC1_FixCHR(); + } +} + +static void M543Reset(void) { + bits = 0; + shift = 0; + reg = 0; + MMC1_Reset(); +} + +static void M543Power(void) { + bits = 0; + shift = 0; + reg = 0; + MMC1_Power(); + SetWriteHandler(0x5000, 0x5FFF, M543Write); +} + +void Mapper543_Init(CartInfo *info) { + MMC1_Init(info, 64, info->battery ? 64 : 0); + info->Power = M543Power; + info->Reset = M543Reset; + MMC1_cwrap = M543CW; + MMC1_pwrap = M543PW; + MMC1_wwrap = M543WW; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper544.c b/src/mappers/mapper544.c new file mode 100644 index 000000000..5e1c68651 --- /dev/null +++ b/src/mappers/mapper544.c @@ -0,0 +1,119 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 544 - Waixing FS306 */ +#include "mapinc.h" +#include "vrc24.h" + +static uint8 nt[4]; +static uint8 cpuC; + +static uint8 chrRamMask; +static uint8 chrRamCompare; + +static writefunc writePPU; +extern uint32 RefreshAddr; + +static SFORMAT StateRegs[] = { + { nt, 4, "NTBL" }, + { &cpuC, 1, "CPUC" }, + { &chrRamMask, 1, "CHRM" }, + { &chrRamCompare, 1, "CHRB" }, + { 0 }, +}; + +static void M544PW(uint16 A, uint16 V) { + V &= 0x1F; + if (A == 0xC000) { + V = cpuC; + } + setprg8(A, V); +} + +static void M544CW(uint16 A, uint16 V) { + if ((V & chrRamMask) == chrRamCompare) { + setchr1r(0x10, A, V); + } else { + setchr1(A, V); + } +} + +static void M544WriteExtra(uint16 A, uint8 V) { + if (A & 0x04) { + nt[A & 0x03] = V & 0x01; + setmirrorw(nt[0], nt[1], nt[2], nt[3]); + } else { + cpuC = V; + VRC24_FixPRG(); + } +} + +static const uint8 compareMasks[8] = { + 0x28, 0x00, 0x4C, 0x64, 0x46, 0x7C, 0x04, 0xFF +}; + +static DECLFW(M544PPUWrite) { + if (RefreshAddr < 0x2000) { + uint8 reg = RefreshAddr >> 10; + uint8 chrBank = vrc24.chr[reg]; + if (chrBank & 0x80) { + if (chrBank & 0x10) { + chrRamMask = 0x00; + chrRamCompare = 0xFF; + } else { + chrRamMask = (chrBank & 0x40) ? 0xFE : 0xFC; + chrRamCompare = compareMasks[((chrBank >> 1) & 0x01) | ((chrBank >> 2) & 0x02) | ((chrBank >> 4) & 0x04)]; + } + VRC24_FixCHR(); + } + } + writePPU(A, V); +} + +static void M544Power(void) { + chrRamMask = 0xFC; + chrRamCompare = 0x28; + nt[0] = 0; + nt[1] = 0; + nt[2] = 1; + nt[3] = 1; + cpuC = ~1; + VRC24_Power(); + writePPU = GetWriteHandler(0x2007); + SetWriteHandler(0x2007, 0x2007, M544PPUWrite); +} + +static void M544Close(void) { +} + +void Mapper544_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x400, 0x800, 1, 1); + info->Power = M544Power; + info->Close = M544Close; + VRC24_pwrap = M544PW; + VRC24_cwrap = M544CW; + VRC24_miscWrite = M544WriteExtra; + AddExState(StateRegs, ~0, 0, NULL); + + CHRRAMSIZE = 2048; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper547.c b/src/mappers/mapper547.c new file mode 100644 index 000000000..fc15dc0b6 --- /dev/null +++ b/src/mappers/mapper547.c @@ -0,0 +1,220 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005-2019 CaH4e3 (FCEUX) + * Copyright (C) 2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-V (CAI Shogakko no Sansu) + * + */ + +#include "mapinc.h" + +static uint8 reg[16]; +static uint8 IRQa; +static uint8 IRQr; +static uint32 IRQLatch; +static uint32 IRQCount; + +static SFORMAT StateRegs[] = { + { QTAINTRAM, 0x800, "IRAM" }, + { reg, 6, "REGS" }, + { &IRQCount, 4, "IRQC" }, + { &IRQLatch, 4, "IRQL" }, + { &IRQa, 1, "IRQA" }, + { &IRQr, 1, "IRQR" }, + { &qtaintramreg, 1, "IREG" }, + { 0 } +}; + +static void SyncWRAM(void) { +/* +D~7654 3210 + --------- + .... C..B + | +- PRG A12 + +---- Chip select + 0: External cartridge's 8 KiB (battery-backed) + 1: Internal 8 KiB (not battery-backed) */ + setprg4r(0x10, 0x6000, ((reg[0] & 0x08) >> 2) | (reg[0] & 0x01)); + setprg4r(0x10, 0x7000, ((reg[1] & 0x08) >> 2) | (reg[1] & 0x01)); +} + +static void SyncPRG(void) { +/* +D~7654 3210 + --------- + .CBB BBBB + |++-++++- PRG A13-A18 + +-------- Chip select + 0: Internal PRG-ROM (128 KiB) + 1: External PRG-ROM (512 KiB) */ + setprg8(0x8000, (reg[2] & 0x40) ? (0x10 + (reg[2] & 0x3F)) : (reg[2] & 0x0F)); + setprg8(0xA000, (reg[3] & 0x40) ? (0x10 + (reg[3] & 0x3F)) : (reg[3] & 0x0F)); + setprg8(0xC000, (reg[4] & 0x40) ? (0x10 + (reg[4] & 0x3F)) : (reg[4] & 0x0F)); + setprg8(0xE000, 0x10 + 0x3F); +} + +static void SyncCHR(void) { + setchr4r(0x10, 0x0000, reg[5] & 0x01); + setchr4r(0x10, 0x1000, 0x01); +} + +static void SyncMir(void) { + setmirror(((reg[10] >> 1) & 1) ^ 1); +} + +static void Sync(void) { + SyncPRG(); + SyncWRAM(); + SyncCHR(); + SyncMir(); +} + +static DECLFW(M547Write) { + int index = (A & 0x0F00) >> 8; + + reg[index] = V; + switch (A) { + case 0xD000: + case 0xD100: + SyncWRAM(); + break; + case 0xD200: + case 0xD300: + case 0xD400: + SyncPRG(); + break; + case 0xD500: + SyncCHR(); + break; + case 0xD600: + IRQLatch &= 0xFF00; + IRQLatch |= V; + break; + case 0xD700: + IRQLatch &= 0x00FF; + IRQLatch |= V << 8; + break; + case 0xD800: + IRQa = IRQr; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xD900: + IRQr = V & 0x01; + IRQa = V & 0x02; + if (IRQa) { + IRQCount = IRQLatch; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xDA00: + SyncMir(); + /* register shadow to share it with ppu */ + qtaintramreg = reg[10] & 0x03; + break; + } +} + +static const uint8 pageTable[0x24] = { + /* JIS X 0208 rows $20-$4F. $20 is not a valid row number. */ + 0x0, 0x0, 0x2, 0x2, 0x1, 0x1, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, + /* JIS X 0208 rows $50-$7F. $7F is not a valid row number. */ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0xD, 0xD +}; + +static DECLFR(M547Read) { + uint8 row = reg[13] - 0x20; + uint8 col = reg[12] - 0x20; + + if ((row < 0x60) && (col < 0x60)) { + /* "row" and "col" are the first and second 7-bit JIS X 0208 code byte, respectively, each minus the $21 offset. */ + uint16 code = (col % 32) + /* First, go through 32 columns of a column-third. */ + (row % 16) * 32 + /* Then, through 16 rows of a row-third. */ + (col / 32) * 32 * 16 + /* Then, through three column-thirds. */ + (row / 16) * 32 * 16 * 3; /* Finally, through three row-thirds. */ + uint16 glyph = (code & 0xFF) | (pageTable[code >> 8] << 8); + uint32 tile = glyph * 4; /* four tiles per glyph */ + + if (A == 0xDC00) { + /* tile number */ + return ((tile & 0xFF) | (reg[11] & 0x03)); + } else { + /* bank byte */ + return (0x40 | ((reg[11] & 0x04) << 5) | (tile >> 8)); + } + } + return 0; +} + +static void M547CPUIRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount & 0x10000) { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount = IRQLatch; + } + } +} + +static void M547Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0xD000, 0xDFFF, M547Write); + SetReadHandler(0xDC00, 0xDC00, M547Read); + SetReadHandler(0xDD00, 0xDD00, M547Read); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M547Close(void) { + QTAIHack = FALSE; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper547_Init(CartInfo *info) { + QTAIHack = TRUE; + + info->Power = M547Power; + info->Close = M547Close; + MapIRQHook = M547CPUIRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, 0); + + if (iNESCart.iNES2) { + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; + } + + if (!CHRRAMSIZE) CHRRAMSIZE = 8192; + if (!WRAMSIZE) WRAMSIZE = 8192 + 8192; /* 8K external + 8K internal RAM */ + + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + info->battery = TRUE; + iNESCart.SaveGame[0] = WRAM; + iNESCart.SaveGameLen[0] = 8192; /* only bank 0, the external cartridge RAM is battery-backed */ +} diff --git a/src/mappers/mapper548.c b/src/mappers/mapper548.c new file mode 100644 index 000000000..6b9edb8fc --- /dev/null +++ b/src/mappers/mapper548.c @@ -0,0 +1,107 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion - Almana no Kiseki - (Co Tung Co.)'s CTC-15 circuit board + * + */ + +#include "mapinc.h" +#include "fdssound.h" + +static uint8 reg, latch, IRQa; +static int32 IRQCount; + +static SFORMAT StateRegs[] = { + { ®, 1, "REG" }, + { &latch, 1, "LATC" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, reg); + setprg16(0xC000, 0x03); +} + +static DECLFW(M548Write4800) { + latch = ((A >> 3) & 0x04) | ((A >> 2) & 0x03); + IRQa = (A & 0x04) != 0x04; + if (!IRQa) { + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + } +} + +static DECLFW(M548Write5000) { + reg = latch ^ 0x05; + Sync(); +} + + +static void M548IRQ(int a) { + int count = a; + if (IRQa) { + while (count > 0) { + if (IRQCount == 23680) { + X6502_IRQBegin(FCEU_IQEXT); + } else if (IRQCount == 24320) { + X6502_IRQEnd(FCEU_IQEXT); + } + count--; + IRQCount++; + } + } +} + +static void M548Power(void) { + latch = 7; + reg = latch ^ 0x05; + IRQa = 0; + IRQCount = 0; + FDSSound_Power(); + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4800, 0x4FFF, M548Write4800); + SetWriteHandler(0x5000, 0x57FF, M548Write5000); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void M548Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper548_Init(CartInfo *info) { + info->Power = M548Power; + info->Close = M548Close; + MapIRQHook = M548IRQ; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/mappers/mapper549.c b/src/mappers/mapper549.c new file mode 100644 index 000000000..1e7881574 --- /dev/null +++ b/src/mappers/mapper549.c @@ -0,0 +1,52 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* NES 2.0 Mapper 549 + * Used for the Kaiser port of Meikyuu Jiin Dababa from the Famicom Disk System. + */ + +#include "mapinc.h" +#include "latch.h" +#include "fdssound.h" + +static void Sync(void) { + setprg8(0x6000, ((latch.addr >> 3) & 0x04) | (latch.addr >> 2)); + setprg32(0x8000, 0x02); + setchr8(0); +} + +static void M549Power(void) { + Latch_Power(); + FDSSound_Power(); + SetReadHandler(0x6000, 0x7FFF, CartBR); +} + +static void M549Reset(void) { + Sync(); + FDSSoundRegReset(); + FDSSound_SC(); +} + +void Mapper549_Init(CartInfo *info) { + Latch_Init(info, Sync, NULL, FALSE, TRUE); + info->Power = M549Power; + info->Reset = M549Reset; +} diff --git a/src/mappers/mapper550.c b/src/mappers/mapper550.c new file mode 100644 index 000000000..76336f018 --- /dev/null +++ b/src/mappers/mapper550.c @@ -0,0 +1,89 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 550 - 7-in-1 1993 Chess Series (JY-015) */ + +#include "mapinc.h" +#include "mmc1.h" + +static uint8 latch; +static uint8 reg; + +static SFORMAT StateRegs[] = { + { &latch, 1, "LATC" }, + { ®, 1, "REGS" }, + { 0 } +}; + +static void M550PW(uint16 A, uint16 V) { + if ((reg & 0x06) == 0x06) { + setprg16(A, (reg << 2) | (V & 0x07)); + } else { + setprg32(0x8000, (reg << 1) | ((latch >> 4) & 0x01)); + } +} + +static void M550CW(uint16 A, uint16 V) { + if ((reg & 0x06) == 0x06) { + setchr4(A, ((reg << 2) & 0x18) | (V & 0x07)); + } else { + setchr8(((reg << 1) & 0x0C) | (latch & 0x03)); + } +} + +static DECLFW(M550Write7) { + if (!(reg & 0x08)) { + reg = A & 0x0F; + MMC1_FixPRG(); + MMC1_FixCHR(); + } +} + +static DECLFW(M550Write8) { + latch = V; + if ((reg & 0x06) == 0x06) { + MMC1_Write(A, V); + } + MMC1_FixPRG(); + MMC1_FixCHR(); +} + +static void M550Reset(void) { + latch = 0; + reg = 0; + MMC1_Reset(); +} + +static void M550Power(void) { + latch = 0; + reg = 0; + MMC1_Power(); + SetWriteHandler(0x7000, 0x7FFF, M550Write7); + SetWriteHandler(0x8000, 0xFFFF, M550Write8); +} + +void Mapper550_Init(CartInfo *info) { + MMC1_Init(info, 8, 0); + info->Power = M550Power; + info->Reset = M550Reset; + MMC1_cwrap = M550CW; + MMC1_pwrap = M550PW; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper553.c b/src/mappers/mapper553.c new file mode 100644 index 000000000..695524eb2 --- /dev/null +++ b/src/mappers/mapper553.c @@ -0,0 +1,38 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static DECLFR(M553Read) { + if (A < 0xC000) { + return 0x3A; + } + return CartBR(A); +} + +static void M553Power(void) { + setprg16(0xC000, 0); + setchr8(0); + SetReadHandler(0x8000, 0xFFFF, M553Read); +} + +void Mapper553_Init(CartInfo *info) { + info->Power = M553Power; +} diff --git a/src/mappers/mapper554.c b/src/mappers/mapper554.c new file mode 100644 index 000000000..adf338d9a --- /dev/null +++ b/src/mappers/mapper554.c @@ -0,0 +1,85 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Mapper 554 - Kaiser KS-7010 + * used for one of several cartridge conversions of the FDS version of + * 悪魔城 Dracula, the Japanese version of Castlevania + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, reg); + setprg8(0x8000, 0x0A); + setprg8(0xA000, 0x0B); + setprg8(0xC000, 0x06); + setprg8(0xE000, 0x07); + setchr8(reg); +} + +static DECLFR(M544Read) { + uint16 adr = A & 0xFFFE; + + switch (A & 0xF000) { + case 0xC000: + if ((adr >= 0xCAB6) && (adr <= 0xCAD7)) { + reg = (adr >> 2) & 0x0F; + Sync(); + } + break; + case 0xE000: + if ((adr == 0xEBE2) || (adr == 0xEE32)) { + reg = (A >> 2) & 0x0F; + Sync(); + } + break; + case 0xF000: + if (adr == 0xFFFC) { + reg = (A >> 2) & 0x0F; + Sync(); + } + break; + } + + return CartBR(A); +} + +static void M554Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, M544Read); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper554_Init(CartInfo *info) { + info->Power = M554Power; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper555.c b/src/mappers/mapper555.c new file mode 100644 index 000000000..24da40c75 --- /dev/null +++ b/src/mappers/mapper555.c @@ -0,0 +1,133 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 516 - Brilliant Com Cocoma Pack */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg[2]; +static uint8 count_expired; +static uint32 count; +static uint32 count_target = 0x20000000; + +static SFORMAT StateRegs[] = { + { reg, 2, "REGS" }, + { &count, 2, "CNTR" }, + { &count_expired, 2, "CNTE" }, + { 0 } +}; + +static void M555CW(uint16 A, uint16 V) { + uint16 base = (reg[0] << 5) & 0x80; + + if ((reg[0] & 0x06) == 0x02) { + if (V & 0x40) { + setchr1r(0x10, A, base | (V & 0x07)); + } else { + setchr1(A, base | (V & 0xFF)); + } + } else { + setchr1(A, base | (V & 0x7F)); + } +} + +static void M555PW(uint16 A, uint16 V) { + uint16 mask = ((reg[0] << 3) & 0x18) | 0x07; + uint16 base = ((reg[0] << 3) & 0x20); + + setprg8(A, base | (V & mask)); +} + +static DECLFR(M555Read5) { + if (A & 0x800) { + return (0x5C | (count_expired ? 0x80 : 0)); + } + return WRAM[0x2000 | (A & 0xFFF)]; +} + +static DECLFW(M555Write5) { + if (A & 0x800) { + reg[(A >> 10) & 0x01] = V; + MMC3_FixPRG(); + MMC3_FixCHR(); + } else { + WRAM[0x2000 | (A & 0xFFF)] = V; + } +} + +static void M555Reset(void) { + count_target = 0x20000000 | ((uint32)GameInfo->cspecial << 25); + count = 0; + memset(reg, 0, sizeof(reg)); + MMC3_Reset(); +} + +static void M555Power(void) { + count_target = 0x20000000 | ((uint32)GameInfo->cspecial << 25); + count = 0; + memset(reg, 0, sizeof(reg)); + MMC3_Power(); + + SetReadHandler(0x5000, 0x5FFF, M555Read5); + SetWriteHandler(0x5000, 0x5FFF, M555Write5); + + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); +} + +static void M555CPUIRQHook(int a) { + while (a--) { + if (!(reg[0] & 0x08)) { + count = 0; + count_expired = false; + } else { + if (++count == count_target) { + count_expired = TRUE; + } + if ((count % 1789773) == 0) { + uint32 seconds = (count_target - count) / 1789773; + FCEU_DispMessage(RETRO_LOG_INFO, 1000, "Time left: %02i:%02i\n", seconds / 60, seconds % 60); + } + } + } +} + +void Mapper555_Init(CartInfo *info) { + MMC3_Init(info, 0, 0); + MMC3_cwrap = M555CW; + MMC3_pwrap = M555PW; + info->Power = M555Power; + info->Reset = M555Reset; + MapIRQHook = M555CPUIRQHook; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = 16 * 1024; + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + CHRRAMSIZE = 8 * 1024; + CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, TRUE); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/mapper556.c b/src/mappers/mapper556.c new file mode 100644 index 000000000..6e40e9153 --- /dev/null +++ b/src/mappers/mapper556.c @@ -0,0 +1,180 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 556 + * Used for the for the 超强小新2+瑪莉家族 7-in-1 (JY-215) multicart. + */ + +#include "mapinc.h" +#include "mmc3.h" +#include "vrc24.h" + +static uint8 cmd; +static uint8 reg[4]; + +static SFORMAT StateRegs[] = { + { reg, 5, "REGS" }, + { &cmd, 1, "CMD0" }, + { 0 }, +}; + +static uint32 M556PRGMask(void) { + return (~reg[3] & 0x3F); +} + +static uint32 M556PRGBase(void) { + return (((reg[3] & 0x40) << 2) | reg[1]); +} + +static uint32 M556CHRMask(void) { + return (0xFF >> (~reg[2] & 0x0F)); +} + +static uint32 M556CHRBase(void) { + return (((reg[3] & 0x40) << 6) | ((reg[2] & 0xF0) << 4) | reg[0]); +} + +static void M556MMC3PW(uint16 A, uint16 V) { + uint32 mask = M556PRGMask(); + uint32 base = M556PRGBase(); + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M556MMC3CW(uint16 A, uint16 V) { + uint32 mask = M556CHRMask(); + uint32 base = M556CHRBase(); + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M556VRC4PW(uint16 A, uint16 V) { + uint32 mask = M556PRGMask(); + uint32 base = M556PRGBase(); + + setprg8(A, (base & ~mask) | (V & mask)); +} + +static void M556VRC4CW(uint16 A, uint16 V) { + uint32 mask = M556CHRMask(); + uint32 base = M556CHRBase(); + + setchr1(A, (base & ~mask) | (V & mask)); +} + +static void M556Sync(void) { + if (reg[2] & 0x80) { + VRC24_FixPRG(); + VRC24_FixCHR(); + VRC24_FixMIR(); + } else { + MMC3_FixPRG(); + MMC3_FixCHR(); + MMC3_FixMIR(); + } +} + +static DECLFW(M556WriteREG) { + if (!(reg[3] & 0x80)) { + reg[cmd] = V; + cmd = (cmd + 1) & 0x03; + M556Sync(); + } +} + +static DECLFW(M556WriteASIC) { + if (reg[2] & 0x80) { + VRC24_Write(A, V); + } else { + MMC3_Write(A, V); + } +} + +static void M556CPUIRQHook(int a) { + if (reg[2] & 0x80) { + VRC24_IRQCPUHook(a); + } +} + +static void M556HBIRQHook(void) { + if (!(reg[2] & 0x80)) { + MMC3_IRQHBHook(); + } +} + +static void M556Reset(void) { + memset(reg, 0, sizeof(reg)); + reg[2] = 0x0F; + M556Sync(); +} + +static void M556Power(void) { + memset(reg, 0, sizeof(reg)); + reg[2] = 0x0F; + + MMC3_Reset(); + VRC24_Reset(); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, M556WriteREG); + SetWriteHandler(0x8000, 0xFFFF, M556WriteASIC); + + if (WRAM) { + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + } +} + +static void M556Close(void) { +} + +static void StateRestore(int version) { + M556Sync(); +} + +void Mapper556_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x05, 0x0A, 0, TRUE); + VRC24_pwrap = M556VRC4PW; + VRC24_cwrap = M556VRC4CW; + + MMC3_Init(info, 0, 0); + MMC3_pwrap = M556MMC3PW; + MMC3_cwrap = M556MMC3CW; + + info->Reset = M556Reset; + info->Power = M556Power; + info->Close = M556Close; + MapIRQHook = M556CPUIRQHook; + GameHBIRQHook = M556HBIRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + } +} diff --git a/src/mappers/mapper557.c b/src/mappers/mapper557.c new file mode 100644 index 000000000..679c41f42 --- /dev/null +++ b/src/mappers/mapper557.c @@ -0,0 +1,43 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 557 is used for Kaiser's cartridge conversion of the Famicom Disk System game Moero TwinBee: Cinnamon-hakase o Sukue!. */ + +#include "mapinc.h" +#include "n118.h" + +static void M557FixPRG(void) { + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, n118.reg[6] & 0x0F); + setprg8(0xA000, n118.reg[7] & 0x0F); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); +} + +static void M557FixCHR(void) { + setchr8(0); + setmirror(((n118.reg[5] >> 5) & 0x01) ^ 0x01); +} + +void Mapper557_Init(CartInfo *info) { + N118_Init(info, 8, 0); + N118_FixPRG = M557FixPRG; + N118_FixCHR = M557FixCHR; +} diff --git a/src/mappers/mapper558.c b/src/mappers/mapper558.c new file mode 100644 index 000000000..761ea7181 --- /dev/null +++ b/src/mappers/mapper558.c @@ -0,0 +1,144 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2019 Libretro Team + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Yancheng YC-03-09/Waixing FS??? PCB */ + +#include "mapinc.h" + +#include "eeprom_93Cx6.h" + +static uint8 reg[4]; + +static uint8 haveEEPROM; +static uint8 eeprom_data[512]; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg[1] << 4) | (reg[0] & 0xF) | ((reg[3] & 0x04) ? 0x00 : 0x03)); + setprg8r(0x10, 0x6000, 0); + if (!(reg[0] & 0x80)) { + setchr8(0); + } +} + +static void M558HBIRQHook(void) { + if ((reg[0] & 0x80) && + (scanline < 239)) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on + PA13 rises. This does not seem possible with the current PPU emulation however. */ + setchr4(0x0000, (scanline >= 127) ? 1 : 0); + setchr4(0x1000, (scanline >= 127) ? 1 : 0); + } else { + setchr8(0); + } +} + +static DECLFR(readReg) { + if (haveEEPROM) { + return eeprom_93Cx6_read() ? 0x04 : 0x00; + } + return reg[2] & 0x04; +} + +static DECLFW(writeReg) { + switch (A & 0xFF00) { + case 0x5000: + if (!(reg[3] & 0x02)) { + V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); + } + reg[0] = V; + Sync(); + break; + case 0x5100: + if (!(reg[3] & 0x02)) { + V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); + } + reg[1] = V; + Sync(); + break; + case 0x5200: + if ((PRG_ROM_SIZE_16K != (1024 * 1024)) && !(reg[3] & 0x02)) { + V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); + } + reg[2] = V; + if (haveEEPROM) { + eeprom_93Cx6_write((reg[2] & 0x04), (reg[2] & 0x02), (reg[2] & 0x01)); + } + break; + case 0x5300: + reg[3] = V; + Sync(); + break; + } +} + +static void M558Power(void) { + memset(reg, 0, sizeof(reg)); + Sync(); + SetReadHandler(0x5000, 0x57FF, readReg); + SetWriteHandler(0x5000, 0x57FF, writeReg); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); +} + +static void M558Reset(void) { + memset(reg, 0, sizeof(reg)); + Sync(); +} + +static void M558Close(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper558_Init(CartInfo *info) { + info->Power = M558Power; + info->Reset = M558Reset; + info->Close = M558Close; + GameHBIRQHook = M558HBIRQHook; + + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = info->PRGRamSize + (info->PRGRamSaveSize & ~0x7FF); + WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + + haveEEPROM = !!(info->PRGRamSaveSize & 0x200); + if (haveEEPROM) { + eeprom_93Cx6_init(eeprom_data, 512, 8); + info->battery = 1; + info->SaveGame[0] = eeprom_data; + info->SaveGameLen[0] = 512; + } else if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = (info->PRGRamSaveSize & ~0x7FF); + } +} diff --git a/src/mappers/mapper559.c b/src/mappers/mapper559.c new file mode 100644 index 000000000..70fa45845 --- /dev/null +++ b/src/mappers/mapper559.c @@ -0,0 +1,91 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NES 2.0 Mapper 559 - VRC4 clone + * Subor 0102 + */ + +#include "mapinc.h" +#include "vrc24.h" + +static uint8 nt[4]; +static uint8 cpuC; + +static SFORMAT StateRegs[] = { + { &cpuC, 1, "CPUC" }, + { nt, 4, "NTBL" }, + { 0 }, +}; + +static void M559PW(uint16 A, uint16 V) { + V &= 0x1F; + if (A == 0xC000) { + V = cpuC; + } + setprg8(A, V); +} + +static void M559CW(uint16 A, uint16 V) { + setchr1(A, V & 0x1FF); +} + +static void M559MIRR(void) { + setmirrorw(nt[0], nt[1], nt[2], nt[3]); +} + +static void M559WriteMisc(uint16 A, uint8 V) { + if (A & 0x04) { + nt[A & 0x03] = V & 0x01; + VRC24_FixMIR(); + } else { + cpuC = V; + VRC24_FixPRG(); + } +} + +static DECLFW(M559WriteNibble) { + /* nibblize address */ + if (A & 0x400) { + V >>= 4; + } + VRC24_Write(A, V); +} + +static void M559Power(void) { + nt[0] = 0; + nt[1] = 0; + nt[2] = 1; + nt[3] = 1; + cpuC = ~1; + VRC24_Power(); + setprg8(0xC000, cpuC); + setmirrorw(nt[0], nt[1], nt[2], nt[3]); + SetWriteHandler(0xB000, 0xFFFF, M559WriteNibble); +} + +void Mapper559_Init(CartInfo *info) { + VRC24_Init(info, VRC4, 0x400, 0x800, 1, 1); + info->Power = M559Power; + VRC24_FixMIR = M559MIRR; + VRC24_pwrap = M559PW; + VRC24_cwrap = M559CW; + VRC24_miscWrite = M559WriteMisc; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/mapper561.c b/src/mappers/mapper561.c new file mode 100644 index 000000000..91d6de993 --- /dev/null +++ b/src/mappers/mapper561.c @@ -0,0 +1,294 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prg[4]; +static uint8 chr; +static uint8 latch; +static uint8 reg1M; +static uint8 reg4M; + +static uint8 IRQa_fds; +static int16 IRQCount_fds; +static int16 IRQCount_sgd; + +static SFORMAT StateRegs[] = { + { ®1M, 1, "REG1" }, + { ®4M, 1, "REG4" }, + { &latch, 1, "LATC" }, + { &chr, 1, "CREG" }, + { prg, 4, "PREG" }, + + { &IRQa_fds, 1, "IRQA" }, + { &IRQCount_fds, 2, "FDSC" }, + + { &IRQCount_sgd, 2, "SGDC" }, + + { 0 }, +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + /* PRG memory can be writable */ + SetupCartPRGMapping(0, PRGptr[0], PRGsize[0], !(reg1M & 0x02)); + if (!(reg4M & 0x01)) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, prg[3]); + } else { + switch (reg1M >> 5) { + case 0: + setprg16(0x8000, latch & 0x07); + setprg16(0xC000, 0x07); + break; + case 1: + setprg16(0x8000, (latch >> 2) & 0x0F); + setprg16(0xC000, 0x07); + break; + case 2: + setprg16(0x8000, latch & 0x0F); + setprg16(0xC000, 0x0F); + break; + case 3: + setprg16(0x8000, 0x0F); + setprg16(0xC000, latch & 0x0F); + break; + case 4: + setprg32(0x8000, (latch >> 4) & 0x03); + break; + case 5: + setprg32(0x8000, 0x03); + break; + case 6: + setprg8(0x8000, latch & 0x0F); + setprg8(0xA000, latch >> 4); + setprg16(0xC000, 0x07); + break; + case 7: + setprg8(0x8000, latch & 0x0E); + setprg8(0xA000, (latch >> 4) | 0x01); + setprg16(0xC000, 0x07); + break; + } + } + + /* CHR RAN can be write-protected */ + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !((reg1M & 0xE0) & 0x80)); + setchr8(chr); + + switch (reg1M & 0x11) { + case 0x00: setmirror(MI_0); break; + case 0x01: setmirror(MI_V); break; + case 0x10: setmirror(MI_1); break; + case 0x11: setmirror(MI_H); break; + } +} + +static DECLFW(M561WriteReg) { + switch (A) { + case 0x4024: + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x4025: + X6502_IRQEnd(FCEU_IQEXT); + IRQa_fds = V; + if (IRQa_fds & 0x42) { + IRQCount_fds = 0; + } + break; + case 0x4100: + X6502_IRQEnd(FCEU_IQEXT); + IRQCount_sgd = (int16)((IRQCount_sgd & 0xFF00) | V); + if (!V) { + IRQCount_sgd = V; + } + break; + case 0x4101: + X6502_IRQEnd(FCEU_IQEXT); + IRQCount_sgd = (int16)((IRQCount_sgd & 0x00FF) | (V << 8)); + break; + case 0x42FC: + case 0x42FD: + case 0x42FE: + case 0x42FF: + reg1M = (V & 0xF0) | (A & 0x03); + Sync(); + break; + case 0x43FC: + case 0x43FD: + case 0x43FE: + case 0x43FF: + reg4M = (V & 0xF0) | (A & 0x03); + chr = V & 0x03; + Sync(); + break; + } +} + +static DECLFW(M561Write) { + if (reg1M & 0x02) { + latch = V; + switch (reg1M >> 5) { + case 0: + case 2: + chr = 0; + break; + case 1: + case 4: + case 5: + chr = latch & 0x03; + break; + case 3: + chr = (latch >> 4) & 0x03; + break; + default: + /* keep chr bank from last mode */ + break; + } + prg[(A >> 13) & 0x03] = V >> 2; + Sync(); + } else { + CartBW(A, V); + } +} + +static void M561Reset(void) { + IRQa_fds = IRQCount_fds = IRQCount_sgd = 0; + Sync(); +} + +static void M561Power(void) { + reg1M = (iNESCart.submapper << 5) | ((iNESCart.mirror == MI_V) ? 0x01 : 0x11) | 0x02; + reg4M = 0x03; + prg[0] = 0x1C; + prg[1] = 0x1D; + prg[2] = 0x1E; + prg[3] = 0x1F; + chr = 0; + + SetWriteHandler(0x4020, 0x4FFF, M561WriteReg); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M561Write); + + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + + Sync(); + + if (MISC_ROM_SIZE && (MISC_ROM_SIZE >= 4)) { + uint16 trainerLoadAddr = 0x7000; + uint16 trainerInitAddr = 0x7003; + uint32 trainerSize = 512; + uint8 *trainerData = MISC_ROM_DATA; + int i; + + if (MISC_ROM_SIZE != 512) { + trainerLoadAddr = (MISC_ROM_DATA[1] << 8) | MISC_ROM_DATA[0]; + trainerInitAddr = (MISC_ROM_DATA[3] << 8) | MISC_ROM_DATA[2]; + trainerSize = MISC_ROM_SIZE - 4; + trainerData = MISC_ROM_DATA + 4; + } + + for (i = 0; i < MISC_ROM_SIZE; i++) { + WRAM[(trainerLoadAddr & 0x1FFF) + i] = trainerData[i]; + } + + if (trainerInitAddr) { + /* JSR init */ + (GetWriteHandler(0x0700))(0x0700, 0x20); + (GetWriteHandler(0x0701))(0x0701, trainerInitAddr & 0xFF); + (GetWriteHandler(0x0702))(0x0702, trainerInitAddr >> 8); + + /* JMP ($FFFC) */ + (GetWriteHandler(0x0703))(0x0703, 0x6C); + (GetWriteHandler(0x0704))(0x0704, 0xFC); + (GetWriteHandler(0x0705))(0x0705, 0xFF); + + X6502_SetNewPC(0x700); + } + } + (GetWriteHandler(0x4017))(0x4017, 0x40); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M561CPUIRQHook(int a) { + IRQCount_fds += 3 * a; + while ((IRQCount_fds >= 448) && (IRQa_fds & 0x80)) { + IRQCount_fds -= 448; + X6502_IRQBegin(FCEU_IQEXT); + } + if (IRQCount_sgd < 0) { + IRQCount_sgd += a; + if (IRQCount_sgd >= 0) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +void Mapper561_Init(CartInfo *info) { + uint32 wramsize = info->PRGRamSize + info->PRGRamSaveSize; + + info->Power = M561Power; + info->Reset = M561Reset; + MapIRQHook = M561CPUIRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = wramsize ? wramsize : 8192; + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + + if ((info->submapper == 3) && (PRG_ROM_SIZE_16K < (256 * 1024))) { + uint8 *tmp = (uint8 *)FCEU_malloc(PRG_ROM_SIZE_16K); + int i; + + for (i = 0; i < PRG_ROM_SIZE_16K; i++) { + tmp[i] = PRG_ROM_DATA[i]; + } + FCEU_free(PRG_ROM_DATA); + PRG_ROM_SIZE_16K = (256 * 1024); + PRG_ROM_DATA = (uint8 *)FCEU_malloc(PRG_ROM_SIZE_16K); + for (i = 0; i < PRG_ROM_SIZE_16K; i++) { + PRG_ROM_DATA[i] = tmp[i]; + } + FCEU_free(tmp); + SetupCartPRGMapping(0, PRG_ROM_DATA, PRG_ROM_SIZE_16K, FALSE); + } + + if (CHR_ROM_SIZE_8K) { + /* Game Doctor only used CHR RAM, but some .nes files has CHR ROM instead. */ + /* Remap CHR as writable. */ + SetupCartCHRMapping(0, CHR_ROM_DATA, CHR_ROM_SIZE_8K, TRUE); + AddExState(CHR_ROM_DATA, CHR_ROM_SIZE_8K, 0, "CHRM"); + } + + /* PRG memory can be writable, so add to states */ + AddExState(PRG_ROM_DATA, PRG_ROM_SIZE_16K, 0, "PRGM"); +} diff --git a/src/mappers/mapper562.c b/src/mappers/mapper562.c new file mode 100644 index 000000000..dcd044b3c --- /dev/null +++ b/src/mappers/mapper562.c @@ -0,0 +1,590 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static const uint8 tgd4800[2048] = { + 0xf6, 0x60, 0x20, 0xd3, 0xe7, 0xf0, 0x06, 0x20, 0xd3, 0xe7, 0x20, + 0xf5, 0xe7, 0xa2, 0x01, 0xb5, 0xf5, 0xa8, 0x55, 0xf7, 0x35, 0xf5, + 0x95, 0xf5, 0x94, 0xf7, 0xca, 0x10, 0xf2, 0x60, 0xa9, 0x08, 0x08, + 0xa0, 0x00, 0x18, 0x65, 0x00, 0x85, 0x00, 0xa9, 0x00, 0x65, 0x01, + 0x85, 0x01, 0x28, 0xc6, 0x02, 0x60, 0xa2, 0x08, 0xb0, 0x0a, 0xb1, + 0x00, 0x8d, 0x07, 0x20, 0xc8, 0xca, 0xd0, 0xf5, 0x60, 0xad, 0x07, + 0x20, 0x91, 0x00, 0xb0, 0xf4, 0xa5, 0x03, 0xa2, 0x08, 0xb0, 0x07, + 0x8d, 0x07, 0x20, 0xca, 0xd0, 0xf8, 0x60, 0xad, 0x07, 0x20, 0xb0, + 0xf7, 0xa2, 0x08, 0xa5, 0x03, 0x51, 0x00, 0x8d, 0x07, 0x20, 0xc8, + 0xca, 0xd0, 0xf5, 0x60, 0x85, 0x04, 0x86, 0x02, 0x84, 0x03, 0x20, + 0xfc, 0xe3, 0xad, 0x02, 0x20, 0xa5, 0xff, 0x29, 0xfb, 0x85, 0xff, + 0x8d, 0x00, 0x20, 0xa4, 0x03, 0x8c, 0x06, 0x20, 0xa5, 0x04, 0x29, + 0xf0, 0x8d, 0x06, 0x20, 0xa9, 0x00, 0x85, 0x03, 0xa5, 0x04, 0x29, + 0x0f, 0x4a, 0x90, 0x02, 0xc6, 0x03, 0x4a, 0x90, 0x03, 0xae, 0x07, + 0x20, 0xa8, 0xf0, 0x15, 0x88, 0xf0, 0x20, 0x88, 0xf0, 0x29, 0x88, + 0x20, 0x59, 0xe8, 0xa0, 0x00, 0x20, 0x32, 0xe8, 0x20, 0x1e, 0xe8, + 0xd0, 0xf3, 0x60, 0x20, 0x32, 0xe8, 0x20, 0x32, 0xe8, 0xa9, 0x10, + 0x20, 0x20, 0xe8, 0xd0, 0xf3, 0x60, 0x20, 0x32, 0xe8, 0x20, 0x47, + 0xe8, 0x20, 0x1e, 0xe8, 0xd0, 0xf5, 0x60, 0x20, 0x47, 0xe8, 0x20, + 0x32, 0xe8, 0x20, 0x1e, 0xe8, 0xd0, 0xf5, 0x60, 0xae, 0x00, 0x78, + 0x9a, 0xad, 0x11, 0x44, 0x29, 0xfc, 0x09, 0x06, 0x8d, 0x11, 0x44, + 0xa2, 0x00, 0xbd, 0x00, 0x70, 0x95, 0x00, 0xbd, 0x00, 0x71, 0x9d, + 0x00, 0x01, 0xe8, 0xd0, 0xf2, 0xad, 0x13, 0x44, 0x8d, 0x11, 0x44, + 0xad, 0x10, 0x44, 0x29, 0xfc, 0x8d, 0x10, 0x44, 0xad, 0x02, 0x20, + 0x10, 0xfb, 0xad, 0x02, 0x20, 0x10, 0xfb, 0x68, 0xa8, 0x68, 0xaa, + 0x68, 0x28, 0x6c, 0xfa, 0xff, 0x08, 0x48, 0xad, 0x10, 0x44, 0x29, + 0x03, 0xd0, 0x33, 0xad, 0x10, 0x44, 0x09, 0x02, 0x8d, 0x10, 0x44, + 0xad, 0x11, 0x44, 0x8d, 0x13, 0x44, 0x09, 0x04, 0x29, 0xfc, 0x8d, + 0x11, 0x44, 0xad, 0x06, 0x60, 0x10, 0x0b, 0x8a, 0x48, 0x98, 0x48, + 0xba, 0x8e, 0x00, 0x78, 0x4c, 0x03, 0x60, 0xad, 0x13, 0x44, 0x8d, + 0x11, 0x44, 0xad, 0x10, 0x44, 0x29, 0xfc, 0x8d, 0x10, 0x44, 0xad, + 0x10, 0x44, 0x29, 0xbf, 0x8d, 0x10, 0x44, 0x29, 0x03, 0xc9, 0x02, + 0xf0, 0x05, 0x68, 0x28, 0x6c, 0xfa, 0xff, 0x68, 0x28, 0x4c, 0x64, + 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xa9, 0x00, 0x85, 0xfc, 0x85, 0xfd, 0x20, 0x3a, 0xe1, 0x20, + 0x73, 0xe3, 0xba, 0xee, 0x20, 0x22, 0xe4, 0x20, 0x73, 0xe3, 0xf6, + 0xee, 0x20, 0xa3, 0xee, 0x20, 0x3a, 0xe1, 0x20, 0x4e, 0xec, 0x20, + 0x22, 0xe4, 0x20, 0x73, 0xe3, 0xce, 0xee, 0x20, 0x73, 0xe3, 0x07, + 0xef, 0x20, 0xa3, 0xee, 0x20, 0x3a, 0xe1, 0x20, 0x67, 0xec, 0x20, + 0x7b, 0xec, 0x20, 0x22, 0xe4, 0x20, 0x73, 0xe3, 0xe2, 0xee, 0x20, + 0x73, 0xe3, 0x18, 0xef, 0x20, 0x99, 0xee, 0x20, 0x5c, 0xe3, 0x4c, + 0x00, 0xec, 0x20, 0xd4, 0xed, 0x20, 0x8c, 0xec, 0xea, 0xea, 0xea, + 0x20, 0x42, 0xe0, 0xa5, 0x06, 0x85, 0x94, 0x85, 0x95, 0x20, 0x01, + 0xed, 0x20, 0xa7, 0xe2, 0x60, 0x20, 0xd4, 0xed, 0x20, 0xad, 0xee, + 0x20, 0xa0, 0xec, 0xa5, 0x95, 0x85, 0x06, 0x20, 0x6e, 0xed, 0x20, + 0xa7, 0xe2, 0x60, 0x20, 0xd4, 0xed, 0x20, 0xdc, 0xec, 0xa5, 0x95, + 0x85, 0x06, 0x20, 0xa1, 0xed, 0x20, 0xa7, 0xe2, 0x60, 0x20, 0xe2, + 0xed, 0xa0, 0x00, 0x20, 0x12, 0xe3, 0x99, 0x00, 0x07, 0xc8, 0xc0, + 0x37, 0xd0, 0xf5, 0x20, 0xcd, 0xe1, 0x60, 0x20, 0xb4, 0xe2, 0xa5, + 0xfa, 0x29, 0x2b, 0x8d, 0x25, 0x40, 0xa9, 0x00, 0x8d, 0x24, 0x40, + 0xa0, 0xc5, 0x20, 0x2c, 0xe1, 0xa0, 0x56, 0x20, 0x2c, 0xe1, 0xa9, + 0x01, 0x20, 0x37, 0xe3, 0xa0, 0x00, 0xb9, 0x00, 0x07, 0x20, 0x12, + 0xe3, 0xc8, 0xc0, 0x37, 0xd0, 0xf5, 0x20, 0xf0, 0xe1, 0xa9, 0x02, + 0x20, 0x37, 0xe3, 0xa5, 0x94, 0x20, 0x12, 0xe3, 0x20, 0xf0, 0xe1, + 0x60, 0x20, 0xe2, 0xed, 0xa0, 0x00, 0x20, 0x12, 0xe3, 0xa2, 0x22, + 0xd9, 0x00, 0x07, 0x20, 0x2b, 0xe2, 0xc8, 0xc0, 0x37, 0xd0, 0xf0, + 0x20, 0xcd, 0xe1, 0x20, 0x42, 0xe0, 0xa5, 0x06, 0xa2, 0x23, 0xc5, + 0x94, 0x20, 0x2b, 0xe2, 0x60, 0xa9, 0x03, 0x20, 0x16, 0xe3, 0xa0, + 0x00, 0x20, 0x12, 0xe3, 0x99, 0xa0, 0x00, 0x20, 0x61, 0xee, 0xc8, + 0xc0, 0x0f, 0xd0, 0xf2, 0x20, 0xcd, 0xe1, 0xa9, 0x04, 0x20, 0x16, + 0xe3, 0x20, 0x89, 0xee, 0x90, 0x09, 0x20, 0x12, 0xe3, 0x20, 0x61, + 0xee, 0x4c, 0x1e, 0xed, 0x20, 0xcd, 0xe1, 0xc6, 0x06, 0xd0, 0xce, + 0x60, 0x20, 0x10, 0xee, 0xc9, 0x03, 0xd0, 0x32, 0xa0, 0x00, 0x20, + 0x12, 0xe3, 0x99, 0xa0, 0x00, 0x20, 0x61, 0xee, 0xc8, 0xc0, 0x0f, + 0xd0, 0xf2, 0x20, 0x22, 0xee, 0x20, 0x10, 0xee, 0xc9, 0x04, 0xd0, + 0x18, 0x20, 0x89, 0xee, 0x90, 0x09, 0x20, 0x12, 0xe3, 0x20, 0x61, + 0xee, 0x4c, 0x55, 0xed, 0x20, 0x22, 0xee, 0xd0, 0x05, 0xe6, 0x95, + 0x4c, 0x34, 0xed, 0x60, 0xa9, 0x03, 0x20, 0x37, 0xe3, 0xa0, 0x00, + 0x20, 0x68, 0xee, 0x99, 0xa0, 0x00, 0x20, 0x12, 0xe3, 0xc8, 0xc0, + 0x0f, 0xd0, 0xf2, 0x20, 0xf0, 0xe1, 0xa9, 0x04, 0x20, 0x37, 0xe3, + 0x20, 0x89, 0xee, 0x90, 0x09, 0x20, 0x68, 0xee, 0x20, 0x12, 0xe3, + 0x4c, 0x8b, 0xed, 0x20, 0xf0, 0xe1, 0xc6, 0x06, 0xd0, 0xce, 0x60, + 0xa9, 0x03, 0x20, 0x16, 0xe3, 0xa0, 0x00, 0x20, 0x12, 0xe3, 0x99, + 0xa0, 0x00, 0x20, 0x56, 0xee, 0xc8, 0xc0, 0x0f, 0xd0, 0xf2, 0x20, + 0xcd, 0xe1, 0xa9, 0x04, 0x20, 0x16, 0xe3, 0x20, 0x89, 0xee, 0x90, + 0x09, 0x20, 0x12, 0xe3, 0x20, 0x56, 0xee, 0x4c, 0xbe, 0xed, 0x20, + 0xcd, 0xe1, 0xc6, 0x06, 0xd0, 0xce, 0x60, 0xa9, 0x00, 0x85, 0x90, + 0x8d, 0xff, 0x43, 0x85, 0x88, 0xa9, 0x60, 0x85, 0x89, 0x60, 0x20, + 0xb4, 0xe2, 0xa0, 0xc5, 0x20, 0x2c, 0xe1, 0xa0, 0x46, 0x20, 0x2c, + 0xe1, 0xa9, 0x01, 0x20, 0x16, 0xe3, 0x60, 0xa0, 0x0f, 0xb9, 0x00, + 0x07, 0xc9, 0xb0, 0xd0, 0x11, 0xc8, 0xc0, 0x12, 0xd0, 0xf4, 0xb9, + 0x00, 0x07, 0xc9, 0xb1, 0xb0, 0x05, 0xa2, 0x06, 0x4c, 0x2d, 0xe2, + 0x60, 0xa0, 0x05, 0x20, 0x2c, 0xe1, 0xa5, 0xfa, 0x09, 0x40, 0x85, + 0xfa, 0x8d, 0x25, 0x40, 0x20, 0x03, 0xe3, 0x60, 0x20, 0x12, 0xe3, + 0xad, 0x30, 0x40, 0x29, 0x40, 0xd0, 0x29, 0xa5, 0xfa, 0x09, 0x10, + 0x85, 0xfa, 0x8d, 0x25, 0x40, 0x20, 0x12, 0xe3, 0xad, 0x30, 0x40, + 0x29, 0x10, 0xd0, 0x16, 0xa5, 0xfa, 0x29, 0x2f, 0x09, 0x04, 0x85, + 0xfa, 0x8d, 0x25, 0x40, 0xa2, 0x01, 0xad, 0x32, 0x40, 0x4a, 0x20, + 0x28, 0xe2, 0xa9, 0x00, 0x60, 0xa2, 0x00, 0xc1, 0x88, 0xf0, 0x10, + 0xa2, 0x26, 0x4c, 0x2d, 0xe2, 0xa2, 0x00, 0x81, 0x88, 0x4c, 0x6c, + 0xee, 0xa2, 0x00, 0xa1, 0x88, 0xe6, 0x88, 0xd0, 0x18, 0xe6, 0x89, + 0xa6, 0x89, 0xe0, 0xe0, 0x90, 0x10, 0xa2, 0x60, 0x86, 0x89, 0x48, + 0x18, 0xa5, 0x90, 0x69, 0x10, 0x85, 0x90, 0x8d, 0xff, 0x43, 0x68, + 0x60, 0xa5, 0xac, 0x38, 0xe9, 0x01, 0x85, 0xac, 0xb0, 0x06, 0xa5, + 0xad, 0xe9, 0x00, 0x85, 0xad, 0x60, 0x20, 0x76, 0xe4, 0x20, 0x8c, + 0xe1, 0x20, 0x5e, 0xe1, 0x60, 0x20, 0x99, 0xee, 0x20, 0x5c, 0xe3, + 0x20, 0x64, 0xe3, 0x60, 0xad, 0x32, 0x40, 0x29, 0x04, 0xd0, 0x01, + 0x60, 0xa2, 0x07, 0x4c, 0x2d, 0xe2, 0x3f, 0x00, 0x10, 0x0f, 0x2a, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0xff, 0x3f, 0x00, 0x10, 0x0f, 0x26, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0xff, 0x3f, 0x00, 0x10, 0x0f, 0x22, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, + 0x21, 0xe8, 0x0d, 0x12, 0x17, 0x1c, 0x0e, 0x1b, 0x1d, 0x24, 0x1c, + 0x18, 0x1e, 0x1b, 0x0c, 0x0e, 0xff, 0x21, 0xe8, 0x0d, 0x12, 0x17, + 0x1c, 0x0e, 0x1b, 0x1d, 0x24, 0x1d, 0x0a, 0x1b, 0x10, 0x0e, 0x1d, + 0xff, 0x21, 0xec, 0x07, 0x0c, 0x18, 0x19, 0x22, 0x24, 0x18, 0x14, + 0xff, 0xa9, 0x00, 0x8d, 0xff, 0x43, 0x8d, 0x0c, 0x44, 0x8d, 0x02, + 0x01, 0xa9, 0x80, 0x8d, 0xff, 0x42, 0xa9, 0x03, 0x8d, 0x11, 0x44, + 0xa9, 0x83, 0x8d, 0x10, 0x44, 0xd0, 0x2c, 0x78, 0xa9, 0x00, 0x8d, + 0x00, 0x20, 0x8d, 0x01, 0x20, 0x8d, 0x0c, 0x44, 0xa2, 0x03, 0xad, + 0x02, 0x20, 0x10, 0xfb, 0xca, 0xd0, 0xf8, 0x2c, 0x10, 0x44, 0x30, + 0x09, 0x70, 0x07, 0xad, 0x10, 0x44, 0x29, 0x1f, 0x10, 0x18, 0xad, + 0x10, 0x44, 0x29, 0x1f, 0x8d, 0x12, 0x44, 0xad, 0x10, 0x44, 0x29, + 0xfc, 0x09, 0x02, 0x8d, 0x10, 0x44, 0x6c, 0xf6, 0xff, 0xad, 0x12, + 0x44, 0x8d, 0x10, 0x44, 0x8d, 0x10, 0x44, 0x29, 0x03, 0xc9, 0x02, + 0xf0, 0x09, 0xa2, 0xff, 0x9a, 0xe8, 0x8a, 0xa8, 0x6c, 0xfc, 0xff, + 0x20, 0xbe, 0xe6, 0x4c, 0x3f, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4c, 0xd9, + 0x48, 0x4c, 0x18, 0x49, 0x4c, 0x23, 0x4f, 0x4c, 0x3f, 0x4f, 0x4c, + 0x78, 0x4f +}; + +static uint8 prg[4]; +static uint8 chr1K[8]; +static uint8 chr; +static uint8 latch; + +static uint8 reg1M; +static uint8 reg2M; +static uint8 regtgd; + +static uint8 lockCHR; +static uint8 lastCHRBank; + +static uint8 IRQa_fds; +static int16 IRQCount_fds; +static uint16 IRQCount_tgd; +static uint16 count_target_tgd; + +static uint32 lastAddr; + +static writefunc writePPU; + +static SFORMAT StateRegs[] = { + { ®1M, 1, "REG1" }, + { ®2M, 1, "REG2" }, + { ®tgd, 1, "REGT" }, + { &latch, 1, "LATC" }, + { &chr, 1, "CREG" }, + { &lockCHR, 1, "CHRL" }, + { chr1K, 8, "CHR1" }, + { prg, 4, "PREG" }, + + { &IRQa_fds, 1, "IRQa" }, + { &IRQCount_fds, 2, "FDSC" }, + + { &IRQCount_tgd, 2, "TGDC" }, + { &count_target_tgd, 2, "TGDT" }, + + { &lastAddr, 1, "LADR" }, + + { 0 }, +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + /* PRG memory can be writable */ + SetupCartPRGMapping(0, PRGptr[0], PRGsize[0], !(reg1M & 0x02)); + if (regtgd & 0x80) { + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, prg[3]); + } else if (!(reg2M & 0x01)) { + setprg8(0x8000, (prg[0] & 0x0F) | ((reg2M >> 2) & 0x10)); + setprg8(0xA000, (prg[1] & 0x0F) | ((reg2M >> 2) & 0x10)); + setprg8(0xC000, (prg[2] & 0x0F)); + setprg8(0xE000, (prg[3] & 0x0F)); + } else { + switch (reg1M >> 5) { + case 0: + setprg16(0x8000, latch & 0x07); + setprg16(0xC000, 0x07); + break; + case 1: + setprg16(0x8000, (latch >> 2) & 0x0F); + setprg16(0xC000, 0x07); + break; + case 2: + setprg16(0x8000, latch & 0x0F); + setprg16(0xC000, 0x0F); + break; + case 3: + setprg16(0x8000, 0x0F); + setprg16(0xC000, latch & 0x0F); + break; + case 4: + setprg32(0x8000, (latch >> 4) & 0x03); + break; + case 5: + setprg32(0x8000, 0x03); + break; + case 6: + setprg8(0x8000, latch & 0x0F); + setprg8(0xA000, latch >> 4); + setprg16(0xC000, 0x07); + break; + case 7: + setprg8(0x8000, latch & 0x0E); + setprg8(0xA000, (latch >> 4) | 0x01); + setprg16(0xC000, 0x07); + break; + } + } + + /* CHR RAN can be write-protected */ + SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !(((reg1M & 0xE0) & 0x80) || lockCHR)); + + if (regtgd & 0x40) { + setchr1(0x0000, chr1K[0]); + setchr1(0x0400, chr1K[1]); + setchr1(0x0800, chr1K[2]); + setchr1(0x0C00, chr1K[3]); + setchr1(0x1000, chr1K[4]); + setchr1(0x1400, chr1K[5]); + setchr1(0x1800, chr1K[6]); + setchr1(0x1C00, chr1K[7]); + } else { + setchr8(chr); + } + + switch (reg1M & 0x11) { + case 0x00: setmirror(MI_0); break; + case 0x01: setmirror(MI_V); break; + case 0x10: setmirror(MI_1); break; + case 0x11: setmirror(MI_H); break; + } +} + +static DECLFR(M562ReadReg) { + switch (A) { + case 0x4400: + case 0x4401: + case 0x4402: + case 0x4403: + case 0x4404: + case 0x4405: + case 0x4406: + case 0x4407: + return chr1K[A & 0x07]; + case 0x4408: + case 0x4409: + case 0x440A: + case 0x440B: + return (prg[A & 0x03] << 2) | (latch & 0x03); + case 0x440C: + return (IRQCount_tgd >> 8); + case 0x440D: + return (IRQCount_tgd & 0xFF); + case 0x4411: + return regtgd; + case 0x4415: + return reg1M; + case 0x4420: + return chr1K[lastCHRBank]; + default: + if (A & 0x800) { + return tgd4800[A & 0x7FF]; + } + return CartBR(A); + } +} + +static DECLFW(M562WriteReg) { + switch (A) { + case 0x4024: + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0x4025: + X6502_IRQEnd(FCEU_IQEXT); + IRQa_fds = V; + if (IRQa_fds & 0x42) { + IRQCount_fds = 0; + } + break; + case 0x42FC: + case 0x42FD: + case 0x42FE: + case 0x42FF: + reg1M = (V & 0xF0) | (A & 0x03); + lockCHR = !((reg1M & 0xE0) & 0x80); + Sync(); + break; + case 0x43FC: + case 0x43FD: + case 0x43FE: + case 0x43FF: + reg2M = (V & 0xF0) | (A & 0x03); + chr = V & 0x03; + Sync(); + break; + case 0x4400: + case 0x4401: + case 0x4402: + case 0x4403: + case 0x4404: + case 0x4405: + case 0x4406: + case 0x4407: + chr1K[A & 7] = V; + Sync(); + break; + case 0x440C: + X6502_IRQEnd(FCEU_IQEXT); + if (!(V & 0x80)) { + IRQCount_tgd = 0x8000; + } + count_target_tgd = (count_target_tgd & 0x00FF) | (V << 8); + break; + case 0x440D: + X6502_IRQEnd(FCEU_IQEXT); + count_target_tgd = (count_target_tgd & 0xFF00) | V; + break; + case 0x4411: + regtgd = V; + Sync(); + break; + } +} + +static DECLFW(M562Write) { + if (reg1M & 0x02) { + latch = V; + switch (reg1M >> 5) { + case 1: + case 4: + case 5: + chr = latch & 0x03; + break; + case 3: + chr = (latch >> 4) & 0x03; + break; + } + prg[(A >> 13) & 0x03] = V >> 2; + Sync(); + } else { + CartBW(A, V); + } +} + +static DECLFW(M562CHRWrite) { + if (((reg1M >> 5) >= 5) && (~(reg1M & 0x11) & 0x01)) { + lockCHR = !!(reg1M & 0x10); + } + writePPU(A, V); +} + +static void M562Reset(void) { + IRQa_fds = 0; + IRQCount_fds = 0; + IRQCount_tgd = 0xFFFF; + count_target_tgd = 0; + Sync(); +} + +static void M562Power(void) { + reg1M = (iNESCart.submapper << 5) | ((iNESCart.mirror == MI_V) ? 0x01 : 0x11) | 0x04 | 0x02; + reg2M = 0x03; + regtgd = 0x03; + + latch = 0; + chr = 0; + lockCHR = FALSE; + + prg[0] = 0x1C; + prg[1] = 0x1D; + prg[2] = 0x1E; + prg[3] = 0x1F; + chr1K[0] = 0; + chr1K[1] = 1; + chr1K[2] = 2; + chr1K[3] = 3; + chr1K[4] = 4; + chr1K[5] = 5; + chr1K[6] = 6; + chr1K[7] = 7; + IRQa_fds = 0; + IRQCount_fds = 0; + IRQCount_tgd = 0xFFFF; + count_target_tgd = 0; + + writePPU = GetWriteHandler(0x2007); + SetWriteHandler(0x2007, 0x2007, M562CHRWrite); + + SetReadHandler(0x4020, 0x4FFF, M562ReadReg); + SetWriteHandler(0x4020, 0x4FFF, M562WriteReg); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M562Write); + + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + + Sync(); + + if (MISC_ROM_SIZE && (MISC_ROM_SIZE >= 4)) { + uint16 trainerLoadAddr = 0x7000; + uint16 trainerInitAddr = 0x7003; + uint32 trainerSize = 512; + uint8 *trainerData = MISC_ROM_DATA; + int i; + + if (MISC_ROM_SIZE != 512) { + trainerLoadAddr = (MISC_ROM_DATA[1] << 8) | MISC_ROM_DATA[0]; + trainerInitAddr = (MISC_ROM_DATA[3] << 8) | MISC_ROM_DATA[2]; + trainerSize = MISC_ROM_SIZE - 4; + trainerData = MISC_ROM_DATA + 4; + + FCEU_printf(" load addr : %04x\n", trainerLoadAddr); + FCEU_printf(" init addr : %04x\n", trainerInitAddr); + FCEU_printf(" data size : %d\n", trainerSize); + } + + for (i = 0; i < MISC_ROM_SIZE; i++) { + (GetWriteHandler(trainerLoadAddr))(trainerLoadAddr + i, trainerData[i]); + } + + if (trainerInitAddr) { + /* JSR init */ + (GetWriteHandler(0x0700))(0x0700, 0x20); + (GetWriteHandler(0x0701))(0x0701, trainerInitAddr & 0xFF); + (GetWriteHandler(0x0702))(0x0702, trainerInitAddr >> 8); + + /* JMP ($FFFC) */ + (GetWriteHandler(0x0703))(0x0703, 0x6C); + (GetWriteHandler(0x0704))(0x0704, 0xFC); + (GetWriteHandler(0x0705))(0x0705, 0xFF); + + X6502_SetNewPC(0x700); + } + } + (GetWriteHandler(0x4017))(0x4017, 0x40); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M562CPUIRQHook(int a) { + while (a--) { + IRQCount_fds += 3; + while ((IRQCount_fds >= 448) && (IRQa_fds & 0x80)) { + IRQCount_fds -= 448; + X6502_IRQBegin(FCEU_IQEXT); + } + if (count_target_tgd & 0x8000) { + if (IRQCount_tgd == count_target_tgd && (IRQCount_tgd != 0xFFFF)) { + X6502_IRQBegin(FCEU_IQEXT); + } else { + IRQCount_tgd++; + } + } + } +} + +static void M562PPUHook(uint32 A) { + if ((lastAddr != A) && ((A & 0x3000) != 0x2000)) { + lastCHRBank = (A >> 13) & 0x07; + } + lastAddr = A; +} + +void Mapper562_Init(CartInfo *info) { + uint32 wramsize = info->PRGRamSize + info->PRGRamSaveSize; + + info->Power = M562Power; + info->Reset = M562Reset; + MapIRQHook = M562CPUIRQHook; + PPU_hook = M562PPUHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); + + WRAMSIZE = wramsize ? wramsize : 8192; + if (WRAMSIZE) { + WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + + if (CHR_ROM_SIZE_8K) { + /* Game Doctor only used CHR RAM, but some .nes files has CHR ROM instead. */ + /* Remap CHR as writable. */ + SetupCartCHRMapping(0, CHR_ROM_DATA, CHR_ROM_SIZE_8K, TRUE); + AddExState(CHR_ROM_DATA, CHR_ROM_SIZE_8K, 0, "CHRM"); + } + + /* PRG memory can be writable, so add to states */ + AddExState(PRG_ROM_DATA, PRG_ROM_SIZE_16K, 0, "PRGM"); +} diff --git a/src/mappers/nsf.c b/src/mappers/nsf.c new file mode 100644 index 000000000..8533a1a2b --- /dev/null +++ b/src/mappers/nsf.c @@ -0,0 +1,858 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include + +#include "../fceu-types.h" +#include "../x6502.h" +#include "../fceu.h" +#include "../video.h" +#include "../sound.h" +#include "../general.h" +#include "../fceu-memory.h" +#include "../file.h" +#include "../fds.h" +#include "../cart.h" +#include "../input.h" +#include "../state.h" + +#include "mappers/sound/vrc6sound.h" +#include "mappers/sound/vrc7sound.h" +#include "mappers/sound/fdssound.h" +#include "mappers/sound/mmc5sound.h" +#include "mappers/sound/n163sound.h" +#include "mappers/sound/s5bsound.h" + +#include "nsf.h" +#include "nsfe.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define FIXED_EXWRAM_SIZE (32768 + 8192) + +static DECLFW(NSF_write); +static DECLFR(NSF_read); + +static int vismode = 1; + +static uint8 NSFROM[0x30 + 6] = +{ +/* 0x00 - NMI */ + 0x8D, 0xF4, 0x3F, /* Stop play routine NMIs. */ + 0xA2, 0xFF, 0x9A, /* Initialize the stack pointer. */ + 0xAD, 0xF0, 0x3F, /* See if we need to init. */ + 0xF0, 0x09, /* If 0, go to play routine playing. */ + + 0xAD, 0xF1, 0x3F, /* Confirm and load A */ + 0xAE, 0xF3, 0x3F, /* Load X with PAL/NTSC byte */ + + 0x20, 0x00, 0x00, /* JSR to init routine */ + + 0xA9, 0x00, + 0xAA, + 0xA8, + 0x20, 0x00, 0x00, /* JSR to play routine */ + 0x8D, 0xF5, 0x3F, /* Start play routine NMIs. */ + 0x90, 0xFE, /* Loopie time. */ + +/* 0x20 */ + 0x8D, 0xF3, 0x3F, /* Init init NMIs */ + 0x18, + 0x90, 0xFE /* Loopie time. */ +}; + +static DECLFR(NSFROMRead) { + return (NSFROM - 0x3800)[A]; +} + +static int lastJoy; +static int doreset = 0; +static int NSFNMIFlags; + +static uint8 BSon; +static int special = 0; +static uint8 *ExWRAM = 0; + +static uint8 SongReload; + +static uint8 *mmc5_exram; +static uint8 mmc5_mul[2]; + +NSFINFO *NSFInfo; + +extern uint8 FCEU_GetJoyJoy(void); + +static SFORMAT StateRegs[] = { + { &lastJoy, 1, "JOY" }, + { &SongReload, 1, "SREL" }, + { &doreset, 1, "DORE" }, + { &NSFNMIFlags, 1, "NMIF" }, + { 0 } +}; + +static void FreeNSF(void) { + if (mmc5_exram) { + free(mmc5_exram); + mmc5_exram = NULL; + } + + if (ExWRAM) { + free(ExWRAM); + ExWRAM = 0; + } + + if (NSFInfo) { + if (NSFInfo->NSFDATA) { + free(NSFInfo->NSFDATA); + NSFInfo->NSFDATA = NULL; + } + + free(NSFInfo); + NSFInfo = NULL; + } +} + +static void NSFGI(int h) { + switch (h) { + case GI_CLOSE: + FreeNSF(); + break; + case GI_RESETM2: + case GI_POWER: + NSF_init(); + break; + } +} + +/* First 32KB is reserved for sound chip emulation in the iNES mapper code. */ + +static INLINE void BANKSET(uint32 A, uint32 bank) { + bank &= NSFInfo->NSFMaxBank; + if (NSFInfo->SoundChip & NSFSOUND_FDS) { + memcpy(ExWRAM + (A - 0x6000), NSFInfo->NSFDATA + (bank << 12), 4096); + } else { + setprg4(A, bank); + } +} + +static int LoadNSF(FCEUFILE *fp) { + size_t tmp_size = FCEU_fgetsize(fp) - 0x80; + NSF_HEADER NSFHeader; + + FCEU_fread(&NSFHeader, 1, 0x80, fp); + + /* NULL-terminate strings just in case. */ + NSFHeader.GameName[31] = NSFHeader.Artist[31] = NSFHeader.Copyright[31] = 0; + + sprintf((char *)NSFInfo->SongName, "%s", (const char *)NSFHeader.GameName); + sprintf((char *)NSFInfo->Artist, "%s", (const char *)NSFHeader.Artist); + sprintf((char *)NSFInfo->Copyright, "%s", (const char *)NSFHeader.Copyright); + + NSFInfo->LoadAddr = NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh << 8); + NSFInfo->InitAddr = NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh << 8); + NSFInfo->PlayAddr = NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh << 8); + + if (tmp_size > 16 * 1024 * 1024) { + FCEU_PrintError("NSF is too large.\n"); + return FALSE; + } + + NSFInfo->NSFSize = tmp_size; + + NSFInfo->NSFMaxBank = ((NSFInfo->NSFSize + (NSFInfo->LoadAddr & 0xfff) + 4095) / 4096); + NSFInfo->NSFMaxBank = PRGsize[0] = uppow2(NSFInfo->NSFMaxBank); + + if (!(NSFInfo->NSFDATA = (uint8 *)FCEU_malloc(NSFInfo->NSFMaxBank * 4096))) { + return FALSE; + } + + FCEU_fseek(fp, 0x80, SEEK_SET); + memset(NSFInfo->NSFDATA, 0x00, NSFInfo->NSFMaxBank * 4096); + FCEU_fread(NSFInfo->NSFDATA + (NSFInfo->LoadAddr & 0xfff), 1, NSFInfo->NSFSize, fp); + + NSFInfo->NSFMaxBank--; + + NSFInfo->VideoSystem = NSFHeader.VideoSystem; + NSFInfo->SoundChip = NSFHeader.SoundChip; + NSFInfo->TotalSongs = NSFHeader.TotalSongs; + + if (NSFHeader.StartingSong == 0) { + NSFHeader.StartingSong = 1; + } + + NSFInfo->StartingSong = NSFHeader.StartingSong - 1; + memcpy(NSFInfo->BankSwitch, NSFHeader.BankSwitch, 8); + + return TRUE; +} + +int NSFLoad(FCEUFILE *fp) { + char magic[5]; + int x; + + NSFInfo = (NSFINFO *)FCEU_malloc(sizeof(NSFINFO)); + + FCEU_fseek(fp, 0, SEEK_SET); + FCEU_fread(&magic, 1, 5, fp); + + if (!memcmp(magic, "NESM\x1a", 5)) { + FCEU_fseek(fp, 0, SEEK_SET); + if (!LoadNSF(fp)) { + FreeNSF(); + return FALSE; + } + } else if (!memcmp(magic, "NSFE", 4)) { + FCEU_fseek(fp, 0, SEEK_SET); + if (!LoadNSFE(fp)) { + FreeNSF(); + return FALSE; + } + } else { + return FALSE; + } + + if (NSFInfo->LoadAddr < 0x6000) { + FCEU_PrintError("Invalid load address!"); + FreeNSF(); + return FALSE; + } + + if (NSFInfo->TotalSongs < 1) { + FCEU_PrintError("Total number of songs is less than 1\n"); + FreeNSF(); + return FALSE; + } + + BSon = 0; + for (x = 0; x < 8; x++) { + BSon |= NSFInfo->BankSwitch[x]; + } + + if (BSon == 0) { + uint8 BankCounter = 0x00; + + if (((NSFInfo->LoadAddr >> 8) & 0x70) >= 0x70) { + BSon = 0xFF; /* Ice Climber, and other F000 base address tunes need this */ + } else { + for (x = ((NSFInfo->LoadAddr >> 8) & 0x70) / 0x10; x < 8; x++) { + NSFInfo->BankSwitch[x] = BankCounter; + BankCounter += 0x01; + } + BSon = 0; + } + } + + for (x = 0; x < 8; x++) { + BSon |= NSFInfo->BankSwitch[x]; + } + + GameInfo->type = GIT_NSF; + GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD; + GameInfo->cspecial = SIS_NSF; + + for (x = 0;; x++) { + if (NSFROM[x] == 0x20) { + NSFROM[x + 1] = NSFInfo->InitAddr & 0xFF; + NSFROM[x + 2] = NSFInfo->InitAddr >> 8; + NSFROM[x + 8] = NSFInfo->PlayAddr & 0xFF; + NSFROM[x + 9] = NSFInfo->PlayAddr >> 8; + break; + } + } + + if (NSFInfo->VideoSystem == 0) { + GameInfo->vidsys = GIV_NTSC; + } else if (NSFInfo->VideoSystem == 1) { + GameInfo->vidsys = GIV_PAL; + } + + GameInterface = NSFGI; + + FCEU_printf("\n"); + FCEU_printf("NSF Loaded.\n"); + FCEU_printf("File information:\n"); + FCEU_printf(" Name: %s\n", NSFInfo->SongName); + FCEU_printf(" Artist: %s\n", NSFInfo->Artist); + FCEU_printf(" Copyright: %s\n", NSFInfo->Copyright); + if (NSFInfo->Dumper[0]) { + FCEU_printf(" Dumper: %s\n", NSFInfo->Dumper); + } + FCEU_printf("\n"); + if (NSFInfo->SoundChip) { + static char *tab[6] = { + "Konami VRC6", + "Konami VRC7", + "Nintendo FDS", + "Nintendo MMC5", + "Namco 163", + "Sunsoft 5B", + }; + + for (x = 0; x < 6; x++) { + if (NSFInfo->SoundChip & (1 << x)) { + FCEU_printf(" Expansion hardware: %s\n", tab[x]); + #if 0 + NSFInfo->SoundChip = 1 << x; /* Prevent confusing weirdness if more than one bit is set. */ + break; + #endif + } + } + } + if (BSon) { + FCEU_printf(" Bank-switched.\n"); + } + FCEU_printf(" Load address: $%04x\n", NSFInfo->LoadAddr); + FCEU_printf(" Init address: $%04x\n", NSFInfo->InitAddr); + FCEU_printf(" Play address: $%04x\n", NSFInfo->PlayAddr); + FCEU_printf(" %s\n", (NSFInfo->VideoSystem & 1) ? "PAL" : "NTSC"); + FCEU_printf(" Starting song: %d / %d\n\n", NSFInfo->StartingSong + 1, NSFInfo->TotalSongs); + + ExWRAM = (uint8 *)FCEU_gmalloc(FIXED_EXWRAM_SIZE); + + FCEUI_SetVidSystem(NSFInfo->VideoSystem != 0); + lastJoy = 0; + + /* TODO: hard-clip strings for now because of DrawNSF limtis */ + NSFInfo->SongName[31] = 0; + NSFInfo->Artist[31] = 0; + NSFInfo->Copyright[31] = 0; + NSFInfo->Dumper[31] = 0; + for (x = 0; x < (int)(sizeof(NSFInfo->SongNames) / sizeof(NSFInfo->SongNames[0])); x++) { + NSFInfo->SongNames[x][31] = 0; + } + + NSFInfo->CurrentSong = NSFInfo->StartingSong; + + return TRUE; +} + +static DECLFR(NSFVectorRead) { + if (((NSFNMIFlags & 1) && SongReload) || (NSFNMIFlags & 2) || doreset) { + if (A == 0xFFFA) { + return (0x00); + } else if (A == 0xFFFB) { + return (0x38); + } else if (A == 0xFFFC) { + return (0x20); + } else if (A == 0xFFFD) { + doreset = 0; + return (0x38); + } + return (X.DB); + } else { + return (CartBR(A)); + } +} + +void NSF_init(void) { + doreset = 1; + +/* NSFInfo->CurrentSong = NSFInfo->StartingSong; */ + SongReload = 0xFF; + NSFNMIFlags = 0; + + ResetExState(0, 0); + ResetCartMapping(); + + SetWriteHandler(0x6000, 0x7FFF, CartBW); + if (NSFInfo->SoundChip & NSFSOUND_FDS) { + SetupCartPRGMapping(0, ExWRAM, FIXED_EXWRAM_SIZE, 1); + setprg32(0x6000, 0); + setprg8(0xE000, 4); + memset(ExWRAM, 0x00, FIXED_EXWRAM_SIZE); + /* SetWriteHandler(0x6000, 0xDFFF, CartBW); */ + SetReadHandler(0x6000, 0xFFFF, CartBR); + } else { + memset(ExWRAM, 0x00, 8192); + SetReadHandler(0x6000, 0x7FFF, CartBR); + /* SetWriteHandler(0x6000, 0x7FFF, CartBW); */ + SetupCartPRGMapping(0, NSFInfo->NSFDATA, ((NSFInfo->NSFMaxBank + 1) * 4096), 0); + SetupCartPRGMapping(1, ExWRAM, 8192, 1); + setprg8r(1, 0x6000, 0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + } + + if (BSon) { + int x; + for (x = 0; x < 8; x++) { + if (NSFInfo->SoundChip & NSFSOUND_FDS && x >= 6) { + BANKSET(0x6000 + (x - 6) * 4096, NSFInfo->BankSwitch[x]); + } + BANKSET(0x8000 + x * 4096, NSFInfo->BankSwitch[x]); + } + } else { + int x; + for (x = (NSFInfo->LoadAddr & 0xF000); x < 0x10000; x += 0x1000) { + BANKSET(x, ((x - (NSFInfo->LoadAddr & 0xF000)) >> 12)); + } + } + + SetReadHandler(0xFFFA, 0xFFFD, NSFVectorRead); + + SetWriteHandler(0x2000, 0x3fef, 0); + SetReadHandler(0x2000, 0x37ff, 0); + SetReadHandler(0x3836, 0x3FFF, 0); + SetReadHandler(0x3800, 0x3835, NSFROMRead); + + SetWriteHandler(0x5ff6, 0x5fff, NSF_write); + + SetWriteHandler(0x3ff0, 0x3fff, NSF_write); + SetReadHandler(0x3ff0, 0x3fff, NSF_read); + + AddExState(StateRegs, ~0, 0, NULL); + AddExState(ExWRAM, FIXED_EXWRAM_SIZE, 0, "ERAM"); + AddExState(&NSFInfo->CurrentSong, 4 | FCEUSTATE_RLSB, 0, "CURS"); + + /* init sound chips */ + + if (NSFInfo->SoundChip & NSFSOUND_VRC6) { + VRC6Sound_ESI(); + SetWriteHandler(0x9000, 0x9003, NSF_write); + SetWriteHandler(0xA000, 0xA002, NSF_write); + SetWriteHandler(0xB000, 0xB002, NSF_write); + } + if (NSFInfo->SoundChip & NSFSOUND_VRC7) { + VRC7Sound_ESI(); + SetWriteHandler(0x9010, 0x9010, NSF_write); + SetWriteHandler(0x9030, 0x9030, NSF_write); + } + if (NSFInfo->SoundChip & NSFSOUND_FDS) { + FDSSoundRegReset(); + FDSSound_SC(); + SetReadHandler(0x4040, 0x407F, NSF_read); + SetReadHandler(0x4090, 0x4090, NSF_read); + SetReadHandler(0x4092, 0x4092, NSF_read); + SetWriteHandler(0x4040, 0x408A, NSF_write); + } + if (NSFInfo->SoundChip & NSFSOUND_MMC5) { + MMC5Sound_ESI(); + SetReadHandler(0x5C00, 0x5fef, NSF_read); + SetReadHandler(0x5205, 0x5206, NSF_read); + SetWriteHandler(0x5000, 0x5015, NSF_write); + SetWriteHandler(0x5205, 0x5206, NSF_write); + SetWriteHandler(0x5C00, 0x5FF5, NSF_write); + if (mmc5_exram) { + FCEU_free(mmc5_exram); + } + mmc5_exram = (uint8 *)FCEU_malloc(1024); + } + if (NSFInfo->SoundChip & NSFSOUND_N163) { + N163Sound_ESI(); + SetReadHandler(0x4800, 0x4FFF, NSF_read); + SetWriteHandler(0x4800, 0x4FFF, NSF_write); + SetWriteHandler(0xF800, 0xFFFF, NSF_write); + } + if (NSFInfo->SoundChip & NSFSOUND_S5B) { + S5BSound_ESI(); + SetWriteHandler(0xC000, 0xCFFF, NSF_write); + SetWriteHandler(0xE000, 0xEFFF, NSF_write); + } + + /* sound chips states */ + + if (NSFInfo->SoundChip & NSFSOUND_VRC6) { + VRC6Sound_AddStateInfo(); + } + if (NSFInfo->SoundChip & NSFSOUND_VRC7) { + VRC7Sound_AddStateInfo(); + } + if (NSFInfo->SoundChip & NSFSOUND_FDS) { + FDSSound_AddStateInfo(); + } + if (NSFInfo->SoundChip & NSFSOUND_MMC5) { + MMC5Sound_AddStateInfo(); + AddExState(mmc5_exram, 1024, 0, "ExRM"); + AddExState(mmc5_mul, 2, 0, "MUL0"); + } + if (NSFInfo->SoundChip & NSFSOUND_N163) { + N163Sound_AddStateInfo(); + } + if (NSFInfo->SoundChip & NSFSOUND_S5B) { + S5BSound_AddStateInfo(); + } +} + +static DECLFW(NSF_write) { + if (NSFInfo->SoundChip & NSFSOUND_VRC6) { + switch (A) { + case 0x9000: + case 0x9001: + case 0x9002: + case 0x9003: + case 0xA000: + case 0xA001: + case 0xA002: + case 0xB000: + case 0xB001: + case 0xB002: + VRC6Sound_Write(A, V); + break; + } + } + + if (NSFInfo->SoundChip & NSFSOUND_VRC7) { + switch (A) { + case 0x9010: + case 0x9030: + VRC7Sound_Write(A, V); + break; + } + } + + if (NSFInfo->SoundChip & NSFSOUND_FDS) { + if ((A >= 0x6000) && (A <= 0xDFFF)){ + /* FIXME: Conflicts in multi chip modes */ + if (!(NSFInfo->SoundChip & (NSFSOUND_VRC6)) && !(A >= 0xA000 && A <= 0xA002)) { + CartBW(A, V); + } + } else if (A >= 0x4040 && A <= 0x407F) { + FDSWaveWrite(A, V); + } else { + switch (A) { + case 0x4080: FDSSReg0Write(A, V); break; + case 0x4082: FDSSReg1Write(A, V); break; + case 0x4083: FDSSReg2Write(A, V); break; + case 0x4084: FDSSReg3Write(A, V); break; + case 0x4085: FDSSReg4Write(A, V); break; + case 0x4086: FDSSReg5Write(A, V); break; + case 0x4087: FDSSReg6Write(A, V); break; + case 0x4088: FDSSReg7Write(A, V); break; + case 0x4089: FDSSReg8Write(A, V); break; + case 0x408A: FDSSReg9Write(A, V); break; + } + } + } + + if (NSFInfo->SoundChip & NSFSOUND_MMC5) { + if ((A >= 0x5000) && (A <= 0x5015)) { + MMC5Sound_Write(A, V); + } else if (A == 0x5205) { + mmc5_mul[0] = V; + } else if (A == 0x5206) { + mmc5_mul[1] = V; + } else if ((A >= 0x5c00) && (A <= 0x5FF5)) { + mmc5_exram[A & 0x3FF] = V; + } + } + + if (NSFInfo->SoundChip & NSFSOUND_N163) { + switch (A & 0xF800) { + case 0xF800: + N163Sound_Write(A, V); + break; + case 0x4800: + N163Sound_Write(A, V); + break; + } + } + + if (NSFInfo->SoundChip & NSFSOUND_S5B) { + switch (A & 0xF000) { + case 0xC000: + case 0xE000: + S5BSound_Write(A, V); + break; + } + } + + switch (A & 0xF000) { + case 0x6000: + case 0x7000: + /* always mapped to ExWRAM */ + CartBW(A, V); + break; + } + + switch (A) { + case 0x3FF3: + NSFNMIFlags |= 1; + break; + case 0x3FF4: + NSFNMIFlags &= ~2; + break; + case 0x3FF5: + NSFNMIFlags |= 2; + break; + + case 0x5FF6: + case 0x5FF7: + if (!(NSFInfo->SoundChip & NSFSOUND_FDS)) { + return; + } + /* fallthrough */ + case 0x5FF8: + case 0x5FF9: + case 0x5FFA: + case 0x5FFB: + case 0x5FFC: + case 0x5FFD: + case 0x5FFE: + case 0x5FFF: + if (!BSon) { + return; + } + A &= 0xF; + BANKSET((A * 4096), V); + break; + } +} + +static DECLFR(NSF_read) { + int x; + + if (NSFInfo->SoundChip & NSFSOUND_FDS) { + if ((A >= 0x4040) && (A <= 0x407F)) { + return FDSWaveRead(A); + } + if (A == 0x4090) { + return FDSEnvVolumeRead(A); + } + if (A == 0x4092) { + return FDSEnvModRead(A); + } + } + + if (NSFInfo->SoundChip & NSFSOUND_MMC5) { + if ((A >= 0x5C00) && (A <= 0x5FEF)) { + return mmc5_exram[A & 0x3FF]; + } + if (A == 0x5205) { + return (uint8)(uint32)(mmc5_mul[0] * mmc5_mul[1]); + } + if (A == 0x5206) { + return (uint8)((uint32)(mmc5_mul[0] * mmc5_mul[1]) >> 8); + } + } + + if (NSFInfo->SoundChip & NSFSOUND_N163) { + if ((A >= 0x4800) && (A <= 0x4FFF)) { + return N163Sound_Read(A); + } + } + + switch (A) { + case 0x3ff0: + x = SongReload; +#ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) +#endif + SongReload = 0; + return x; + case 0x3ff1: +#ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) +#endif + { + for (x = 0; x < 0x800; x++) { + BWrite[x](x, 0); + } + + BWrite[0x4015](0x4015, 0x0); + for (x = 0; x < 0x14; x++) { + BWrite[0x4000 + x](0x4000 + x, 0); + } + BWrite[0x4015](0x4015, 0xF); + + if (NSFInfo->SoundChip & NSFSOUND_FDS) { + BWrite[0x4017](0x4017, 0xC0); /* FDS BIOS writes $C0 */ + BWrite[0x4089](0x4089, 0x80); + BWrite[0x408A](0x408A, 0xE8); + } else { + memset(ExWRAM, 0x00, 8192); + BWrite[0x4017](0x4017, 0xC0); + BWrite[0x4017](0x4017, 0xC0); + BWrite[0x4017](0x4017, 0x40); + } + + if (BSon) { + for (x = 0; x < 8; x++) { + BANKSET(0x8000 + x * 4096, NSFInfo->BankSwitch[x]); + } + } + return (NSFInfo->CurrentSong); + } + case 0x3FF3: + return PAL; + } + return X.DB; +} + +void DrawNSF(uint8 *target) { + char snbuf[16]; + int32 *Bufpl; + int32 mul = 0; + int len = GetSoundBuffer(&Bufpl); + int x; + uint8 bgFill = 0; + uint8 textColor = 0x06; + uint8 waveFormColor = 0x03; + + if (vismode == 0) { + return; + } + + memset(target, bgFill, 256 * 240); + memset(XDBuf, 0, 256 * 240); + + if (special == 0) { + if (FSettings.SoundVolume) { + mul = 8192 * 240 / (16384 * FSettings.SoundVolume / 50); + } + for (x = 0; x < 256; x++) { + uint32 y = 142 + ((((int32)(int16)Bufpl[(x * len) >> 8]) * mul) >> 14); + if (y < 240) { + target[x + y * 256] = waveFormColor; + } + } + } else if (special == 1) { + if (FSettings.SoundVolume) { + mul = 8192 * 240 / (8192 * FSettings.SoundVolume / 50); + } + for (x = 0; x < 256; x++) { + double r = (((int32)(int16)Bufpl[(x * len) >> 8]) * mul) >> 14; + uint32 xp = 128 + r * cos(x * M_PI * 2 / 256); + uint32 yp = 120 + r * sin(x * M_PI * 2 / 256); + + xp &= 255; + yp %= 240; + target[xp + yp * 256] = waveFormColor; + } + } else if (special == 2) { + static double theta = 0; + + if (FSettings.SoundVolume) { + mul = 8192 * 240 / (16384 * FSettings.SoundVolume / 50); + } + for (x = 0; x < 128; x++) { + double xc = (double)128 - x; + double yc = 0.0 - ((double)((((int32)(int16)Bufpl[(x * len) >> 8]) * mul) >> 14)); + double t = (M_PI + atan(yc / xc)) + theta; + double r = sqrt(xc * xc + yc * yc); + uint32 m = 128 + r * cos(t); + uint32 n = 120 + r * sin(t); + + if (m < 256 && n < 240) { + target[m + n * 256] = waveFormColor; + } + } + for (x = 128; x < 256; x++) { + double xc = (double)x - 128; + double yc = (double)((((int32)(int16)Bufpl[(x * len) >> 8]) * mul) >> 14); + double t = (atan(yc / xc)) + theta; + double r = sqrt(xc * xc + yc * yc); + uint32 m = 128 + r * cos(t); + uint32 n = 120 + r * sin(t); + + if (m < 256 && n < 240) { + target[m + n * 256] = waveFormColor; + } + } + theta += (double)M_PI / 256; + } + + DrawTextTrans(target + 10 * 256 + 4 + (((31 - strlen((char *)NSFInfo->SongName)) << 2)), 256, (uint8*)NSFInfo->SongName, textColor); + DrawTextTrans(target + 26 * 256 + 4 + (((31 - strlen((char *)NSFInfo->Artist)) << 2)), 256, (uint8*)NSFInfo->Artist, textColor); + DrawTextTrans( target + 42 * 256 + 4 + (((31 - strlen((char *)NSFInfo->Copyright)) << 2)), 256, (uint8*)NSFInfo->Copyright, textColor); + + if (NSFInfo->SongNames[0][0]) { + DrawTextTrans(target + 70 * 256 + 4 + (((31 - strlen((char *)NSFInfo->SongNames[NSFInfo->CurrentSong])) << 2)), 256, (uint8 *)NSFInfo->SongNames[NSFInfo->CurrentSong], textColor); + } else { + DrawTextTrans(target + 70 * 256 + 4 + (((31 - strlen("Song:")) << 2)), 256, (uint8 *)"Song:", textColor); + } + sprintf(snbuf, "<%d/%d>", NSFInfo->CurrentSong + 1, NSFInfo->TotalSongs); + DrawTextTrans(target + 82 * 256 + 4 + (((31 - strlen(snbuf)) << 2)), 256, (uint8 *)snbuf, textColor); +} + +void DoNSFFrame(void) { + uint8 tmp = FCEU_GetJoyJoy(); + + if (((NSFNMIFlags & 1) && SongReload) || (NSFNMIFlags & 2)) { + TriggerNMI(); + } + + if ((tmp & JOY_RIGHT) && !(lastJoy & JOY_RIGHT)) { + if (NSFInfo->CurrentSong < NSFInfo->TotalSongs - 1) { + NSFInfo->CurrentSong++; + } else { + NSFInfo->CurrentSong = NSFInfo->StartingSong; + } + SongReload = 0xFF; + } else if ((tmp & JOY_LEFT) && !(lastJoy & JOY_LEFT)) { + if (NSFInfo->CurrentSong > 0) { + NSFInfo->CurrentSong--; + } else { + NSFInfo->CurrentSong = NSFInfo->TotalSongs - 1; + } + SongReload = 0xFF; + } else if ((tmp & JOY_UP) && !(lastJoy & JOY_UP)) { + uint32 ns = NSFInfo->CurrentSong + (uint32)MIN(NSFInfo->TotalSongs - 1 - NSFInfo->CurrentSong, 10); + if (NSFInfo->CurrentSong != ns) { + NSFInfo->CurrentSong = ns; + SongReload = 0xFF; + } + } else if ((tmp & JOY_DOWN) && !(lastJoy & JOY_DOWN)) { + unsigned ns = NSFInfo->CurrentSong - (uint32)MIN(NSFInfo->CurrentSong, (uint32)10); + + if (NSFInfo->CurrentSong != ns) { + NSFInfo->CurrentSong = ns; + SongReload = 0xFF; + } + } else if ((tmp & JOY_SELECT) && !(lastJoy & JOY_SELECT)) { + NSFInfo->CurrentSong = NSFInfo->StartingSong; + SongReload = 0xFF; + } else if ((tmp & JOY_START) && !(lastJoy & JOY_START)) { + SongReload = 0xFF; + } else if ((tmp & JOY_A) && !(lastJoy & JOY_A)) { + special = (special + 1) % 3; + } + lastJoy = tmp; +} + +void FCEUI_NSFSetVis(int mode) { + vismode = mode; +} + +int FCEUI_NSFChange(int amount) { + NSFInfo->CurrentSong += amount; + if (NSFInfo->CurrentSong < 1) { + NSFInfo->CurrentSong = 1; + } else if (NSFInfo->CurrentSong > NSFInfo->TotalSongs) { + NSFInfo->CurrentSong = NSFInfo->TotalSongs; + } + SongReload = 0xFF; + + return (NSFInfo->CurrentSong); +} + +/* Returns total songs */ +int FCEUI_NSFGetInfo(uint8 *name, uint8 *artist, uint8 *copyright, int maxlen) { + strncpy((char *)name, (const char *)NSFInfo->SongName, (size_t)maxlen); + strncpy((char *)artist, (const char *)NSFInfo->Artist, (size_t)maxlen); + strncpy((char *)copyright, (const char *)NSFInfo->Copyright, (size_t)maxlen); + return (NSFInfo->TotalSongs); +} diff --git a/src/mappers/nsf.h b/src/mappers/nsf.h new file mode 100644 index 000000000..66f60f6e9 --- /dev/null +++ b/src/mappers/nsf.h @@ -0,0 +1,84 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FCEU_NSF_H +#define _FCEU_NSF_H + +#define NSFSOUND_VRC6 0x01 +#define NSFSOUND_VRC7 0x02 +#define NSFSOUND_FDS 0x04 +#define NSFSOUND_MMC5 0x08 +#define NSFSOUND_N163 0x10 +#define NSFSOUND_S5B 0x20 + +typedef struct NSF_HEADER { + char ID[5]; /* NESM^Z */ + uint8 Version; + uint8 TotalSongs; + uint8 StartingSong; + uint8 LoadAddressLow; + uint8 LoadAddressHigh; + uint8 InitAddressLow; + uint8 InitAddressHigh; + uint8 PlayAddressLow; + uint8 PlayAddressHigh; + uint8 GameName[32]; + uint8 Artist[32]; + uint8 Copyright[32]; + uint8 NTSCspeed[2]; /* Unused */ + uint8 BankSwitch[8]; + uint8 PALspeed[2]; /* Unused */ + uint8 VideoSystem; + uint8 SoundChip; + uint8 Expansion[4]; + uint8 reserve[8]; +} NSF_HEADER; + +typedef struct NSFINFO { + char SongName[256]; + char Artist[256]; + char Copyright[256]; + char Dumper[256]; + char SongNames[100][256]; + + uint8 TotalSongs; + uint8 StartingSong; + uint8 CurrentSong; + uint8 VideoSystem; + + uint16 PlayAddr, InitAddr, LoadAddr; + uint8 BankSwitch[8]; + uint8 SoundChip; + + uint8 *NSFDATA; + size_t NSFMaxBank; + size_t NSFSize; +} NSFINFO; + +extern NSFINFO *NSFInfo; + +void NSF_init(void); +void DrawNSF(uint8 *target); +void DoNSFFrame(void); + +/* NSF Expansion Chip Set Write Handler for mappers */ +void NFSSetWriteHandler(int chip, int32 start, int32 end, writefunc func); + +#endif diff --git a/src/mappers/nsfe.c b/src/mappers/nsfe.c new file mode 100644 index 000000000..922a193db --- /dev/null +++ b/src/mappers/nsfe.c @@ -0,0 +1,283 @@ +/* FCEUmm - Multi-system Emulator + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + +#include +#include + +#include "../fceu.h" +#include "../x6502.h" +#include "../sound.h" +#include "../cart.h" +#include "../fceu-endian.h" +#include "../file.h" +#include "../general.h" + +#include "nsf.h" +#include "nsfe.h" + +typedef struct { + uint8 LoadAddressLow; + uint8 LoadAddressHigh; + uint8 InitAddressLow; + uint8 InitAddressHigh; + uint8 PlayAddressLow; + uint8 PlayAddressHigh; + uint8 VideoSystem; + uint8 SoundChip; + uint8 TotalSongs; + uint8 StartingSong; +} NSFE_INFO; + +typedef struct { + uint32 info; + char ID[4]; +} NSFE_HEADER; + +static NSFE_HEADER nchead; + +static void GetString(FCEUFILE *fp, uint32 *chunk_size, uint8 *str) { + unsigned count = 0; + + while (*chunk_size) { + uint8 c = FCEU_fgetc(fp); + + (*chunk_size)--; + if (!c) { + break; + } + if (c < 0x20) { + c = 0x20; + } + *str++ = c; + count++; + } +} + +static void FreeNFSE(void) { + if (NSFInfo->NSFDATA) { + free(NSFInfo->NSFDATA); + NSFInfo->NSFDATA = NULL; + } +} + +static uint8 nsfe_INFO(FCEUFILE *fp) { + NSFE_INFO nsfe_info; + + if (NSFInfo->TotalSongs) { + FCEU_PrintError("NSFE chunk \"%.4s\" is duplicate.\n", (char *)nchead.ID); + return FALSE; + } + + if (nchead.info < 8) { + FCEU_PrintError("NSFE chunk \"%.4s\" size(%u) is invalid.\n", (char *)nchead.ID, nchead.info); + return FALSE; + } + + if (!FCEU_fread(&nsfe_info, 1, 10, fp)) { + return FALSE; + } + + NSFInfo->TotalSongs = 1; + NSFInfo->StartingSong = 0; + + NSFInfo->LoadAddr = nsfe_info.LoadAddressLow | nsfe_info.LoadAddressHigh << 8; + NSFInfo->InitAddr = nsfe_info.InitAddressLow | nsfe_info.InitAddressHigh << 8; + NSFInfo->PlayAddr = nsfe_info.PlayAddressLow | nsfe_info.PlayAddressHigh << 8; + NSFInfo->VideoSystem = nsfe_info.VideoSystem; + NSFInfo->SoundChip = nsfe_info.SoundChip; + + nchead.info -= 8; + + if (nchead.info) { + NSFInfo->TotalSongs = nsfe_info.TotalSongs; + if (!NSFInfo->TotalSongs) { + NSFInfo->TotalSongs = 255; + } + nchead.info--; + } + + if (nchead.info) { + NSFInfo->StartingSong = nsfe_info.StartingSong; + nchead.info--; + } + + return TRUE; +} + +static uint8 nsfe_DATA(FCEUFILE *fp) { + if (!NSFInfo->TotalSongs) { + FCEU_PrintError("NSFE chunk \"%.4s\" is out of order.\n", (char *)nchead.ID); + return FALSE; + } + + if (NSFInfo->NSFDATA) { + FCEU_PrintError("NSFE chunk \"%.4s\" is duplicate.\n", (char *)nchead.ID); + return FALSE; + } + + NSFInfo->NSFSize = nchead.info; + NSFInfo->NSFMaxBank = uppow2((NSFInfo->NSFSize + (NSFInfo->LoadAddr & 0xfff) + 0xfff) / 0x1000) - 1; + + NSFInfo->NSFDATA = (uint8 *)FCEU_malloc((NSFInfo->NSFMaxBank + 1) * 4096); + if (!NSFInfo->NSFDATA) { + return FALSE; + } + memset(NSFInfo->NSFDATA, 0, (NSFInfo->NSFMaxBank + 1) * 4096); + + if (!FCEU_fread(NSFInfo->NSFDATA + (NSFInfo->LoadAddr & 0xfff), 1, NSFInfo->NSFSize, fp)) { + return FALSE; + } + + nchead.info -= NSFInfo->NSFSize; + + return TRUE; +} + +static uint8 nsfe_BANK(FCEUFILE *fp) { + uint64 tr = (uint64)MIN((uint64)nchead.info, (uint64)8); + + if (!FCEU_fread(NSFInfo->BankSwitch, 1, tr, fp) != 0) { + return FALSE; + } + nchead.info -= 8; + + return TRUE; +} + +static uint8 nsfe_NEND(FCEUFILE *fp) { + if (nchead.info != 0) { + /* chunk size here can be anything */ + } else if (!NSFInfo->NSFDATA) { + FCEU_PrintError("NEND reached without preceding DATA chunk.\n"); + return FALSE; + } + + return TRUE; +} + +static uint8 nsfe_tlbl(FCEUFILE *fp) { + unsigned ws; + + if (!NSFInfo->TotalSongs) { + FCEU_PrintError("NSFE chunk \"%.4s\" is out of order.\n", (char *)nchead.ID); + return FALSE; + } + + for (ws = 0; ws < NSFInfo->TotalSongs && nchead.info > 0; ws++) { + GetString(fp, &nchead.info, (uint8 *)NSFInfo->SongNames[ws]); + } + + return TRUE; +} + +static uint8 nsfe_auth(FCEUFILE *fp) { + unsigned count; + + for (count = 0; count < 4 && nchead.info > 0; count++) { + switch (count) { + case 0: + GetString(fp, &nchead.info, (uint8 *)&NSFInfo->SongName); + break; + case 1: + GetString(fp, &nchead.info, (uint8 *)&NSFInfo->Artist); + break; + case 2: + GetString(fp, &nchead.info, (uint8 *)&NSFInfo->Copyright); + break; + case 3: + GetString(fp, &nchead.info, (uint8 *)&NSFInfo->Dumper); + break; + } + } + return TRUE; +} + +static uint8 nsfe_UNUSED(FCEUFILE *fp) { + /* unused chunk, just move our rom pointer at the end of chunk */ + if (nchead.info) { + if (FCEU_fseek(fp, nchead.info, SEEK_CUR) != 0) { + return FALSE; + } + } + nchead.info = 0; + return TRUE; +} + +int LoadNSFE(FCEUFILE *fp) { + if (FCEU_fseek(fp, 4, SEEK_CUR) != 0) { + return FALSE; + } + + for (;;) { + if (!FCEU_fread(&nchead, 1, 8, fp)) { + FreeNFSE(); + return FALSE; + } + /* FCEU_printf(" Chunk: \"%.4s\" %d\n", nchead.ID, nchead.info); */ + if (!memcmp(nchead.ID, "INFO", 4)) { + if (!nsfe_INFO(fp)) { + FreeNFSE(); + return FALSE; + } + } else if (!memcmp(nchead.ID, "BANK", 4)) { + if (!nsfe_BANK(fp)) { + FreeNFSE(); + return FALSE; + } + } else if (!memcmp(nchead.ID, "auth", 4)) { + if (!nsfe_auth(fp)) { + FreeNFSE(); + return FALSE; + } + } else if (!memcmp(nchead.ID, "tlbl", 4)) { + if (!nsfe_tlbl(fp)) { + FreeNFSE(); + return FALSE; + } + } else if (!memcmp(nchead.ID, "DATA", 4)) { + if (!nsfe_DATA(fp)) { + FreeNFSE(); + return FALSE; + } + } else if (!memcmp(nchead.ID, "NEND", 4)) { + if (!nsfe_NEND(fp)) { + FreeNFSE(); + return FALSE; + } + /* ignore remaining data from this point */ + return TRUE; + } else { + if (!nsfe_UNUSED(fp)) { + FreeNFSE(); + return FALSE; + } + } + if (nchead.info) { + /* this should not happen */ + if (FCEU_fseek(fp, nchead.info, SEEK_CUR) != 0) { + FreeNFSE(); + return FALSE; + } + nchead.info = 0; + } + } + FreeNFSE(); + return FALSE; +} diff --git a/src/mappers/nsfe.h b/src/mappers/nsfe.h new file mode 100644 index 000000000..739d9f420 --- /dev/null +++ b/src/mappers/nsfe.h @@ -0,0 +1,6 @@ +#ifndef __FCEU_NES_NSFE_H +#define __FCEU_NES_NSFE_H + +int LoadNSFE(FCEUFILE *fp); + +#endif /* __FCEU_NES_NSFE_H */ diff --git a/src/mappers/sound/dripsound.c b/src/mappers/sound/dripsound.c new file mode 100644 index 000000000..72b315e2d --- /dev/null +++ b/src/mappers/sound/dripsound.c @@ -0,0 +1,250 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +#define TIMER_SHIFT ((FSettings.soundq >= 1) ? 0 : 17) + +typedef struct DRIPSOUND { + uint8 buffer[256], readPos, writePos; + uint8 bufferFull, bufferEmpty; + uint8 volume; + uint16 freq; + int32 timer; + int16 out; +} DRIPSOUND; + +static DRIPSOUND channel[2]; +static int32 cvbc = 0; + +static void SetOutput(DRIPSOUND *ds, int32 output) { + ds->out = output; +} + +static void ChannelReset(DRIPSOUND *ds) { + memset(ds->buffer, 0, 256); + ds->readPos = 0; + ds->writePos = 0; + ds->bufferFull = FALSE; + ds->bufferEmpty = TRUE; +} + +static uint8 ChannelRead(DRIPSOUND *ds, uint16 A) { + uint8 result = 0; + + if (ds->bufferFull) { + result |= 0x80; + } + + if (ds->bufferEmpty) { + result |= 0x40; + } + + return result; +} + +static void ChannelWrite(DRIPSOUND *ds, uint16 A, uint8 V) { + switch (A & 0x03) { + case 0: + ChannelReset(ds); + SetOutput(ds, 0); + ds->timer = ds->freq << TIMER_SHIFT; + break; + + case 1: + if (ds->readPos == ds->writePos) { + ds->bufferEmpty = FALSE; + SetOutput(ds, V * ds->volume); + ds->timer = ds->freq << TIMER_SHIFT; + } + + ds->buffer[ds->writePos++] = V; + if (ds->readPos == ds->writePos) { + ds->bufferFull = TRUE; + } + break; + + case 2: + ds->freq = (ds->freq & 0xF00) | V; + break; + + case 3: + ds->freq = (ds->freq & 0xFF) | ((V & 0xF) << 8); + ds->volume = (V & 0xF0) >> 4; + if (!ds->bufferEmpty) { + SetOutput(ds, ds->buffer[ds->readPos] * ds->volume); + } + break; + } +} + +static int32 GetSample(void) { + int32 out = 0; + int P; + + for (P = 0; P < 2; P++) { + DRIPSOUND *ds = &channel[P]; + + if (!ds->bufferEmpty) { + ds->timer -= nesincsize; + while (ds->timer <= 0) { + ds->timer += ds->freq << TIMER_SHIFT; + if (ds->readPos == ds->writePos) { + ds->bufferFull = FALSE; + } + + ds->readPos++; + SetOutput(ds, ds->buffer[ds->readPos] * ds->volume); + + if (ds->readPos == ds->writePos) { + ds->bufferEmpty = TRUE; + } + } + } + out += ds->out; + } + return out; +} + +static void DRIPSound(void) { + int P, V; + int start = cvbc; + int end = ((int)SOUNDTS << 16) / soundtsinc; + + if (end <= start) { + return; + } + cvbc = end; + + for (V = start; V < end; V++) { + Wave[V >> 4] += GetSample() >> 4; + } +} + +static int32 GetSampleHQ(void) { + int32 out = 0; + int P; + + for (P = 0; P < 2; P++) { + DRIPSOUND *ds = &channel[P]; + + if (!ds->bufferEmpty) { + ds->timer--; + if (ds->timer <= 0) { + ds->timer = ds->freq << TIMER_SHIFT; + if (ds->readPos == ds->writePos) { + ds->bufferFull = FALSE; + } + + ds->readPos++; + SetOutput(ds, ds->buffer[ds->readPos] * ds->volume); + + if (ds->readPos == ds->writePos) { + ds->bufferEmpty = TRUE; + } + } + } + out += ds->out; + } + return out; +} + +static void DoDRIPSoundHQ(void) { + int P, V; + + for (V = cvbc; V < (int)SOUNDTS; V++) { + WaveHi[V] += GetSampleHQ(); + } + cvbc = SOUNDTS; +} + +static void DoDripSound(int32 Count) { + DRIPSound(); + cvbc = Count; +} + +static void SyncHQ(int32 ts) { + cvbc = ts; +} + +DECLFR(DRIPSound_Read) { + if (A & 0x800) { + return (ChannelRead(&channel[1], A)); + } + return (ChannelRead(&channel[0], A)); +} + +DECLFW(DRIPSound_Write) { + if (FSettings.SndRate > 0) { + if (FSettings.soundq >= 1) { + DoDRIPSoundHQ(); + } else { + DRIPSound(); + } + } + if (A & 0x04) { + ChannelWrite(&channel[1], A, V); + } else { + ChannelWrite(&channel[0], A, V); + } +} + +static void DRIPSound_SC(void) { + GameExpSound.Fill = DoDripSound; + GameExpSound.HiSync = SyncHQ; + GameExpSound.HiFill = DoDRIPSoundHQ; + GameExpSound.RChange = DRIPSound_SC; + channel[0].timer = 0; + channel[1].timer = 0; + cvbc = 0; +} + +void DRIPSound_ESI(void) { + GameExpSound.RChange = DRIPSound_SC; + + ChannelReset(&channel[0]); + ChannelReset(&channel[1]); + + DRIPSound_SC(); +} + +void DRIPSound_AddStateInfo(void) { + AddExState(channel[0].buffer, 256, 0, "FF00"); + AddExState(&channel[0].readPos, 1, 0, "RDP0"); + AddExState(&channel[0].writePos, 1, 0, "WRP0"); + AddExState(&channel[0].bufferFull, 1, 0, "FUL0"); + AddExState(&channel[0].bufferEmpty, 1, 0, "EMT0"); + AddExState(&channel[0].freq, 2, 0, "FRQ0"); + AddExState(&channel[0].volume, 1, 0, "VOL0"); + AddExState(&channel[0].timer, 4, 0, "TIM0"); + AddExState(&channel[0].out, 2, 0, "POS0"); + + AddExState(channel[1].buffer, 256, 0, "FF01"); + AddExState(&channel[1].readPos, 1, 0, "RDP1"); + AddExState(&channel[1].writePos, 1, 0, "WRP1"); + AddExState(&channel[1].bufferFull, 1, 0, "FUL1"); + AddExState(&channel[1].bufferEmpty, 1, 0, "EMT1"); + AddExState(&channel[1].freq, 2, 0, "FRQ1"); + AddExState(&channel[1].volume, 1, 0, "VOL1"); + AddExState(&channel[1].timer, 4, 0, "TIM1"); + AddExState(&channel[1].out, 2, 0, "POS1"); + + AddExState(&cvbc, 4, 0, "CVBC"); +} diff --git a/src/mappers/sound/dripsound.h b/src/mappers/sound/dripsound.h new file mode 100644 index 000000000..f5e190a17 --- /dev/null +++ b/src/mappers/sound/dripsound.h @@ -0,0 +1,29 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _DRIPSOUND_H +#define _DRIPSOUND_H + +void DRIPSound_ESI(void); +DECLFR(DRIPSound_Read); +DECLFW(DRIPSound_Write); +void DRIPSound_AddStateInfo(void); + +#endif /* _DRIPSOUND_H */ \ No newline at end of file diff --git a/src/mappers/sound/emu2149.c b/src/mappers/sound/emu2149.c new file mode 100644 index 000000000..0594b7050 --- /dev/null +++ b/src/mappers/sound/emu2149.c @@ -0,0 +1,431 @@ +/** + * emu2149 v1.41 + * https://github.com/digital-sound-antiques/emu2149 + * Copyright (C) 2001-2022 Mitsutaka Okazaki + * + * This source refers to the following documents. The author would like to thank all the authors who have + * contributed to the writing of them. + * - psg.vhd -- 2000 written by Kazuhiro Tsujikawa. + * - s_fme7.c -- 1999,2000 written by Mamiya (NEZplug). + * - ay8910.c -- 1998-2001 Author unknown (MAME). + * - MSX-Datapack -- 1991 ASCII Corp. + * - AY-3-8910 data sheet + */ +#include +#include +#include "emu2149.h" + +#ifndef INLINE +#if defined(_MSC_VER) +#define INLINE __inline +#elif defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE INLINE +#endif +#endif + +static uint32_t voltbl[2][32] = { + /* YM2149 - 32 steps */ + {0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, + 0x0B, 0x0D, 0x0F, 0x12, + 0x16, 0x1A, 0x1F, 0x25, 0x2D, 0x35, 0x3F, 0x4C, 0x5A, 0x6A, 0x7F, 0x97, + 0xB4, 0xD6, 0xFF, 0xFF}, + /* AY-3-8910 - 16 steps */ + {0x00, 0x00, 0x03, 0x03, 0x04, 0x04, 0x06, 0x06, 0x09, 0x09, 0x0D, 0x0D, + 0x12, 0x12, 0x1D, 0x1D, + 0x22, 0x22, 0x37, 0x37, 0x4D, 0x4D, 0x62, 0x62, 0x82, 0x82, 0xA6, 0xA6, + 0xD0, 0xD0, 0xFF, 0xFF} +}; + +static const uint8_t regmsk[16] = { + 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x1f, 0x3f, + 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0x0f, 0xff, 0xff +}; + +#define GETA_BITS 24 + +static void +internal_refresh (PSG * psg) +{ + uint32_t f_master = psg->clk; + + if (psg->clk_div) + f_master /= 2; + + if (psg->quality) + { + psg->base_incr = 1 << GETA_BITS; + psg->realstep = f_master; + psg->psgstep = psg->rate * 8; + psg->psgtime = 0; + psg->freq_limit = (uint32_t)(f_master / 16 / (psg->rate / 2)); + } + else + { + psg->base_incr = (uint32_t)((double)f_master * (1 << GETA_BITS) / 8 / psg->rate); + psg->freq_limit = 0; + } +} + +void +PSG_setClock(PSG *psg, uint32_t clock) +{ + if (psg->clk != clock) { + psg->clk = clock; + internal_refresh(psg); + } +} + +void +PSG_setClockDivider(PSG *psg, uint8_t enable) +{ + if (psg->clk_div != enable) { + psg->clk_div = enable; + internal_refresh (psg); + } +} + +void +PSG_setRate (PSG * psg, uint32_t rate) +{ + uint32_t r = rate ? rate : 44100; + if (psg->rate != r) { + psg->rate = r; + internal_refresh(psg); + } +} + +void +PSG_setQuality (PSG * psg, uint8_t q) +{ + if (psg->quality != q) { + psg->quality = q; + internal_refresh(psg); + } +} + +PSG * +PSG_new (uint32_t clock, uint32_t rate) +{ + PSG *psg; + + psg = (PSG *) calloc (1, sizeof (PSG)); + if (psg == NULL) + return NULL; + + PSG_setVolumeMode(psg, 0); + psg->clk = clock; + psg->clk_div = 0; + psg->rate = rate ? rate : 44100; + psg->quality = 0; + internal_refresh(psg); + PSG_setMask(psg, 0x00); + return psg; +} + +void +PSG_setVolumeMode (PSG * psg, int type) +{ + switch (type) + { + case 1: + psg->voltbl = voltbl[0]; /* YM2149 */ + break; + case 2: + psg->voltbl = voltbl[1]; /* AY-3-8910 */ + break; + default: + psg->voltbl = voltbl[0]; /* fallback: YM2149 */ + break; + } +} + +uint32_t +PSG_setMask (PSG *psg, uint32_t mask) +{ + uint32_t ret = 0; + if(psg) + { + ret = psg->mask; + psg->mask = mask; + } + return ret; +} + +uint32_t +PSG_toggleMask (PSG *psg, uint32_t mask) +{ + uint32_t ret = 0; + if(psg) + { + ret = psg->mask; + psg->mask ^= mask; + } + return ret; +} + +void +PSG_reset (PSG * psg) +{ + int i; + + psg->base_count = 0; + + for (i = 0; i < 3; i++) + { + psg->count[i] = 0; + psg->freq[i] = 0; + psg->edge[i] = 0; + psg->volume[i] = 0; + psg->ch_out[i] = 0; + } + + psg->mask = 0; + + for (i = 0; i < 16; i++) + psg->reg[i] = 0; + psg->adr = 0; + + psg->noise_seed = 0xffff; + psg->noise_scaler = 0; + psg->noise_count = 0; + psg->noise_freq = 0; + + psg->env_ptr = 0; + psg->env_freq = 0; + psg->env_count = 0; + psg->env_pause = 1; + + psg->out = 0; + +} + +void +PSG_delete (PSG * psg) +{ + free (psg); +} + +uint8_t +PSG_readIO (PSG * psg) +{ + return (uint8_t) (psg->reg[psg->adr]); +} + +uint8_t +PSG_readReg (PSG * psg, uint32_t reg) +{ + return (uint8_t) (psg->reg[reg & 0x1f]); +} + +void +PSG_writeIO (PSG * psg, uint32_t adr, uint32_t val) +{ + if (adr & 1) + PSG_writeReg (psg, psg->adr, val); + else + psg->adr = val & 0x1f; +} + +static INLINE void +update_output (PSG * psg) +{ + + int i, noise; + uint8_t incr; + + psg->base_count += psg->base_incr; + incr = (psg->base_count >> GETA_BITS); + psg->base_count &= (1 << GETA_BITS) - 1; + + /* Envelope */ + psg->env_count += incr; + + if (psg->env_count >= psg->env_freq) + { + if (!psg->env_pause) + { + if(psg->env_face) + psg->env_ptr = (psg->env_ptr + 1) & 0x3f ; + else + psg->env_ptr = (psg->env_ptr + 0x3f) & 0x3f; + } + + if (psg->env_ptr & 0x20) /* if carry or borrow */ + { + if (psg->env_continue) + { + if (psg->env_alternate^psg->env_hold) psg->env_face ^= 1; + if (psg->env_hold) psg->env_pause = 1; + psg->env_ptr = psg->env_face ? 0 : 0x1f; + } + else + { + psg->env_pause = 1; + psg->env_ptr = 0; + } + } + + if (psg->env_freq >= incr) + psg->env_count -= psg->env_freq; + else + psg->env_count = 0; + } + + /* Noise */ + psg->noise_count += incr; + if (psg->noise_count >= psg->noise_freq) + { + psg->noise_scaler ^= 1; + if (psg->noise_scaler) + { + if (psg->noise_seed & 1) + psg->noise_seed ^= 0x24000; + psg->noise_seed >>= 1; + } + + if (psg->noise_freq >= incr) + psg->noise_count -= psg->noise_freq; + else + psg->noise_count = 0; + } + noise = psg->noise_seed & 1; + + /* Tone */ + for (i = 0; i < 3; i++) + { + psg->count[i] += incr; + if (psg->count[i] >= psg->freq[i]) + { + psg->edge[i] = !psg->edge[i]; + + if (psg->freq[i] >= incr) + psg->count[i] -= psg->freq[i]; + else + psg->count[i] = 0; + } + + if (0 < psg->freq_limit && psg->freq[i] <= psg->freq_limit) + { + /* Mute the channel if the pitch is higher than the Nyquist frequency at the current sample rate, + * to prevent aliased or broken tones from being generated. Of course, this logic doesn't exist + * on the actual chip, but practically all tones higher than the Nyquist frequency are usually + * removed by a low-pass circuit somewhere, so we here halt the output. */ + continue; + } + + if (psg->mask & PSG_MASK_CH(i)) + { + psg->ch_out[i] = 0; + continue; + } + + if ((psg->tmask[i]||psg->edge[i]) && (psg->nmask[i]||noise)) + { + if (!(psg->volume[i] & 32)) + psg->ch_out[i] = (psg->voltbl[psg->volume[i] & 31] << 4); + else + psg->ch_out[i] = (psg->voltbl[psg->env_ptr] << 4); + } + else + { + psg->ch_out[i] = 0; + } + } +} + +static INLINE int16_t +mix_output(PSG *psg) +{ + return (int16_t)(psg->ch_out[0] + psg->ch_out[1] + psg->ch_out[2]); +} + +int16_t +PSG_calc (PSG * psg) +{ + if (!psg->quality) + { + update_output(psg); + psg->out = mix_output(psg); + } + else + { + /* Simple rate converter (See README for detail). */ + while (psg->realstep > psg->psgtime) + { + psg->psgtime += psg->psgstep; + update_output(psg); + psg->out += mix_output(psg); + psg->out >>= 1; + } + psg->psgtime -= psg->realstep; + } + return psg->out; +} + +void +PSG_writeReg (PSG * psg, uint32_t reg, uint32_t val) +{ + int c; + + if (reg > 15) return; + + val &= regmsk[reg]; + + psg->reg[reg] = (uint8_t) val; + + switch (reg) + { + case 0: + case 2: + case 4: + case 1: + case 3: + case 5: + c = reg >> 1; + psg->freq[c] = ((psg->reg[c * 2 + 1] & 15) << 8) + psg->reg[c * 2]; + break; + + case 6: + psg->noise_freq = val & 31; + break; + + case 7: + psg->tmask[0] = (val & 1); + psg->tmask[1] = (val & 2); + psg->tmask[2] = (val & 4); + psg->nmask[0] = (val & 8); + psg->nmask[1] = (val & 16); + psg->nmask[2] = (val & 32); + break; + + case 8: + case 9: + case 10: + psg->volume[reg - 8] = val << 1; + break; + + case 11: + case 12: + psg->env_freq = (psg->reg[12] << 8) + psg->reg[11]; + break; + + case 13: + psg->env_continue = (val >> 3) & 1; + psg->env_attack = (val >> 2) & 1; + psg->env_alternate = (val >> 1) & 1; + psg->env_hold = val & 1; + psg->env_face = psg->env_attack; + psg->env_pause = 0; + psg->env_ptr = psg->env_face ? 0 : 0x1f; + break; + + case 14: + case 15: + default: + break; + } + + return; +} \ No newline at end of file diff --git a/src/mappers/sound/emu2149.h b/src/mappers/sound/emu2149.h new file mode 100644 index 000000000..96daeeb92 --- /dev/null +++ b/src/mappers/sound/emu2149.h @@ -0,0 +1,94 @@ +/* emu2149.h */ +#ifndef _EMU2149_H_ +#define _EMU2149_H_ + +#include + +#define PSG_MASK_CH(x) (1<<(x)) + +#ifdef __cplusplus +extern "C" +{ +#endif + + typedef struct __PSG + { + + /* Volume Table */ + uint32_t *voltbl; + + uint8_t reg[0x20]; + int32_t out; + + uint32_t clk, rate, base_incr; + uint8_t quality; + uint8_t clk_div; + + uint16_t count[3]; + uint8_t volume[3]; + uint16_t freq[3]; + uint8_t edge[3]; + uint8_t tmask[3]; + uint8_t nmask[3]; + uint32_t mask; + + uint32_t base_count; + + uint8_t env_ptr; + uint8_t env_face; + + uint8_t env_continue; + uint8_t env_attack; + uint8_t env_alternate; + uint8_t env_hold; + uint8_t env_pause; + + uint16_t env_freq; + uint32_t env_count; + + uint32_t noise_seed; + uint8_t noise_scaler; + uint8_t noise_count; + uint8_t noise_freq; + + /* rate converter */ + uint32_t realstep; + uint32_t psgtime; + uint32_t psgstep; + + uint32_t freq_limit; + + /* I/O Ctrl */ + uint8_t adr; + + /* output of channels */ + int16_t ch_out[3]; + + } PSG; + + void PSG_setQuality (PSG * psg, uint8_t q); + void PSG_setClock(PSG *psg, uint32_t clk); + void PSG_setClockDivider(PSG *psg, uint8_t enable); + void PSG_setRate (PSG * psg, uint32_t rate); + PSG *PSG_new (uint32_t clk, uint32_t rate); + void PSG_reset (PSG *); + void PSG_delete (PSG *); + void PSG_writeReg (PSG *, uint32_t reg, uint32_t val); + void PSG_writeIO (PSG * psg, uint32_t adr, uint32_t val); + uint8_t PSG_readReg (PSG * psg, uint32_t reg); + uint8_t PSG_readIO (PSG * psg); + int16_t PSG_calc (PSG *); + void PSG_setVolumeMode (PSG * psg, int type); + uint32_t PSG_setMask (PSG *, uint32_t mask); + uint32_t PSG_toggleMask (PSG *, uint32_t mask); + +#ifdef __cplusplus +} +#endif + +/* deprecated interfaces */ +#define PSG_set_quality PSG_setQuality +#define PSG_set_rate PSG_setRate +#define PSG_set_clock PSG_setClock + +#endif diff --git a/src/mappers/sound/emu2413.c b/src/mappers/sound/emu2413.c new file mode 100644 index 000000000..447e27d5d --- /dev/null +++ b/src/mappers/sound/emu2413.c @@ -0,0 +1,1507 @@ +/** + * emu2413 v1.5.9 + * https://github.com/digital-sound-antiques/emu2413 + * Copyright (C) 2020 Mitsutaka Okazaki + * + * This source refers to the following documents. The author would like to thank all the authors who have + * contributed to the writing of them. + * - [YM2413 notes](http://www.smspower.org/Development/YM2413) by andete + * - ymf262.c by Jarek Burczynski + * - [VRC7 presets](https://siliconpr0n.org/archive/doku.php?id=vendor:yamaha:opl2#opll_vrc7_patch_format) by Nuke.YKT + * - YMF281B presets by Chabin + */ +#include "emu2413.h" +#include +#include +#include +#include + +#ifndef INLINE +#if defined(_MSC_VER) +#define INLINE __inline +#elif defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE inline +#endif +#endif + +#define _PI_ 3.14159265358979323846264338327950288 + +#define OPLL_TONE_NUM 3 +/* clang-format off */ +static uint8_t default_inst[OPLL_TONE_NUM][(16 + 3) * 8] = {{ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0: User */ +0x71,0x61,0x1e,0x17,0xd0,0x78,0x00,0x17, /* 1: Violin */ +0x13,0x41,0x1a,0x0d,0xd8,0xf7,0x23,0x13, /* 2: Guitar */ +0x13,0x01,0x99,0x00,0xf2,0xc4,0x21,0x23, /* 3: Piano */ +0x11,0x61,0x0e,0x07,0x8d,0x64,0x70,0x27, /* 4: Flute */ +0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28, /* 5: Clarinet */ +0x31,0x22,0x16,0x05,0xe0,0x71,0x00,0x18, /* 6: Oboe */ +0x21,0x61,0x1d,0x07,0x82,0x81,0x11,0x07, /* 7: Trumpet */ +0x33,0x21,0x2d,0x13,0xb0,0x70,0x00,0x07, /* 8: Organ */ +0x61,0x61,0x1b,0x06,0x64,0x65,0x10,0x17, /* 9: Horn */ +0x41,0x61,0x0b,0x18,0x85,0xf0,0x81,0x07, /* A: Synthesizer */ +0x33,0x01,0x83,0x11,0xea,0xef,0x10,0x04, /* B: Harpsichord */ +0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, /* C: Vibraphone */ +0x61,0x50,0x0c,0x05,0xd2,0xf5,0x40,0x42, /* D: Synthsizer Bass */ +0x01,0x01,0x55,0x03,0xe9,0x90,0x03,0x02, /* E: Acoustic Bass */ +0x41,0x41,0x89,0x03,0xf1,0xe4,0xc0,0x13, /* F: Electric Guitar */ +0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, /* R: Bass Drum (from VRC7) */ +0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68, /* R: High-Hat(M) / Snare Drum(C) (from VRC7) */ +0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, /* R: Tom-tom(M) / Top Cymbal(C) (from VRC7) */ +},{ +/* VRC7 presets from Nuke.YKT */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x03,0x21,0x05,0x06,0xe8,0x81,0x42,0x27, +0x13,0x41,0x14,0x0d,0xd8,0xf6,0x23,0x12, +0x11,0x11,0x08,0x08,0xfa,0xb2,0x20,0x12, +0x31,0x61,0x0c,0x07,0xa8,0x64,0x61,0x27, +0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28, +0x02,0x01,0x06,0x00,0xa3,0xe2,0xf4,0xf4, +0x21,0x61,0x1d,0x07,0x82,0x81,0x11,0x07, +0x23,0x21,0x22,0x17,0xa2,0x72,0x01,0x17, +0x35,0x11,0x25,0x00,0x40,0x73,0x72,0x01, +0xb5,0x01,0x0f,0x0F,0xa8,0xa5,0x51,0x02, +0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, +0x71,0x23,0x11,0x06,0x65,0x74,0x18,0x16, +0x01,0x02,0xd3,0x05,0xc9,0x95,0x03,0x02, +0x61,0x63,0x0c,0x00,0x94,0xC0,0x33,0xf6, +0x21,0x72,0x0d,0x00,0xc1,0xd5,0x56,0x06, +0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, +0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68, +0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, +},{ +/* YMF281B presets */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0: User */ +0x62,0x21,0x1a,0x07,0xf0,0x6f,0x00,0x16, /* 1: Electric Strings (form Chabin's patch) */ +0x40,0x10,0x45,0x00,0xf6,0x83,0x73,0x63, /* 2: Bow Wow (based on plgDavid's patch, KSL fixed) */ +0x13,0x01,0x99,0x00,0xf2,0xc3,0x21,0x23, /* 3: Electric Guitar (similar to YM2413 but different DR(C)) */ +0x01,0x61,0x0b,0x0f,0xf9,0x64,0x70,0x17, /* 4: Organ (based on Chabin, TL/DR fixed) */ +0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28, /* 5: Clarinet (identical to YM2413) */ +0x60,0x01,0x82,0x0e,0xf9,0x61,0x20,0x27, /* 6: Saxophone (based on plgDavid, PM/EG fixed) */ +0x21,0x61,0x1c,0x07,0x84,0x81,0x11,0x07, /* 7: Trumpet (similar to YM2413 but different TL/DR(M)) */ +0x37,0x32,0xc9,0x01,0x66,0x64,0x40,0x28, /* 8: Street Organ (from Chabin) */ +0x01,0x21,0x07,0x03,0xa5,0x71,0x51,0x07, /* 9: Synth Brass (based on Chabin, TL fixed) */ +0x06,0x01,0x5e,0x07,0xf3,0xf3,0xf6,0x13, /* A: Electric Piano (based on Chabin, DR/RR/KR fixed) */ +0x00,0x00,0x18,0x06,0xf5,0xf3,0x20,0x23, /* B: Bass (based on Chabin, EG fixed) */ +0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, /* C: Vibraphone (identical to YM2413) */ +0x35,0x64,0x00,0x00,0xff,0xf3,0x77,0xf5, /* D: Chimes (from plgDavid) */ +0x11,0x31,0x00,0x07,0xdd,0xf3,0xff,0xfb, /* E: Tom Tom II (from plgDavid) */ +0x3a,0x21,0x00,0x07,0x80,0x84,0x0f,0xf5, /* F: Noise (based on plgDavid, AR fixed) */ +0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, /* R: Bass Drum (identical to YM2413) */ +0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68, /* R: High-Hat(M) / Snare Drum(C) (identical to YM2413) */ +0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, /* R: Tom-tom(M) / Top Cymbal(C) (identical to YM2413) */ +}}; +/* clang-format on */ + +/* phase increment counter */ +#define DP_BITS 19 +#define DP_WIDTH (1 << DP_BITS) +#define DP_BASE_BITS (DP_BITS - PG_BITS) + +/* dynamic range of envelope output */ +#define EG_STEP 0.375 +#define EG_BITS 7 +#define EG_MUTE ((1 << EG_BITS) - 1) +#define EG_MAX (EG_MUTE - 4) + +/* dynamic range of total level */ +#define TL_STEP 0.75 +#define TL_BITS 6 + +/* dynamic range of sustine level */ +#define SL_STEP 3.0 +#define SL_BITS 4 + +/* damper speed before key-on. key-scale affects. */ +#define DAMPER_RATE 12 + +#define TL2EG(d) ((d) << 1) + +/* sine table */ +#define PG_BITS 10 /* 2^10 = 1024 length sine table */ +#define PG_WIDTH (1 << PG_BITS) + +/* clang-format off */ +/* exp_table[x] = round((exp2((double)x / 256.0) - 1) * 1024) */ +static uint16_t exp_table[256] = { +0, 3, 6, 8, 11, 14, 17, 20, 22, 25, 28, 31, 34, 37, 40, 42, +45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, +93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 130, 133, 136, 139, +142, 145, 148, 152, 155, 158, 161, 164, 168, 171, 174, 177, 181, 184, 187, 190, +194, 197, 200, 204, 207, 210, 214, 217, 220, 224, 227, 231, 234, 237, 241, 244, +248, 251, 255, 258, 262, 265, 268, 272, 276, 279, 283, 286, 290, 293, 297, 300, +304, 308, 311, 315, 318, 322, 326, 329, 333, 337, 340, 344, 348, 352, 355, 359, +363, 367, 370, 374, 378, 382, 385, 389, 393, 397, 401, 405, 409, 412, 416, 420, +424, 428, 432, 436, 440, 444, 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, +488, 492, 496, 501, 505, 509, 513, 517, 521, 526, 530, 534, 538, 542, 547, 551, +555, 560, 564, 568, 572, 577, 581, 585, 590, 594, 599, 603, 607, 612, 616, 621, +625, 630, 634, 639, 643, 648, 652, 657, 661, 666, 670, 675, 680, 684, 689, 693, +698, 703, 708, 712, 717, 722, 726, 731, 736, 741, 745, 750, 755, 760, 765, 770, +774, 779, 784, 789, 794, 799, 804, 809, 814, 819, 824, 829, 834, 839, 844, 849, +854, 859, 864, 869, 874, 880, 885, 890, 895, 900, 906, 911, 916, 921, 927, 932, +937, 942, 948, 953, 959, 964, 969, 975, 980, 986, 991, 996, 1002, 1007, 1013, 1018 +}; +/* fullsin_table[x] = round(-log2(sin((x + 0.5) * PI / (PG_WIDTH / 4) / 2)) * 256) */ +static uint16_t fullsin_table[PG_WIDTH] = { +2137, 1731, 1543, 1419, 1326, 1252, 1190, 1137, 1091, 1050, 1013, 979, 949, 920, 894, 869, +846, 825, 804, 785, 767, 749, 732, 717, 701, 687, 672, 659, 646, 633, 621, 609, +598, 587, 576, 566, 556, 546, 536, 527, 518, 509, 501, 492, 484, 476, 468, 461, +453, 446, 439, 432, 425, 418, 411, 405, 399, 392, 386, 380, 375, 369, 363, 358, +352, 347, 341, 336, 331, 326, 321, 316, 311, 307, 302, 297, 293, 289, 284, 280, +276, 271, 267, 263, 259, 255, 251, 248, 244, 240, 236, 233, 229, 226, 222, 219, +215, 212, 209, 205, 202, 199, 196, 193, 190, 187, 184, 181, 178, 175, 172, 169, +167, 164, 161, 159, 156, 153, 151, 148, 146, 143, 141, 138, 136, 134, 131, 129, +127, 125, 122, 120, 118, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98, 96, +94, 92, 91, 89, 87, 85, 83, 82, 80, 78, 77, 75, 74, 72, 70, 69, +67, 66, 64, 63, 62, 60, 59, 57, 56, 55, 53, 52, 51, 49, 48, 47, +46, 45, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, +29, 28, 27, 26, 25, 24, 23, 23, 22, 21, 20, 20, 19, 18, 17, 17, +16, 15, 15, 14, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, +7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, +2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, +}; +/* clang-format on */ + +static uint16_t halfsin_table[PG_WIDTH]; +static uint16_t *wave_table_map[2] = {fullsin_table, halfsin_table}; + +/* pitch modulator */ +/* offset to fnum, rough approximation of 14 cents depth. */ +static int8_t pm_table[8][8] = { + {0, 0, 0, 0, 0, 0, 0, 0}, /* fnum = 000xxxxxx */ + {0, 0, 1, 0, 0, 0, -1, 0}, /* fnum = 001xxxxxx */ + {0, 1, 2, 1, 0, -1, -2, -1}, /* fnum = 010xxxxxx */ + {0, 1, 3, 1, 0, -1, -3, -1}, /* fnum = 011xxxxxx */ + {0, 2, 4, 2, 0, -2, -4, -2}, /* fnum = 100xxxxxx */ + {0, 2, 5, 2, 0, -2, -5, -2}, /* fnum = 101xxxxxx */ + {0, 3, 6, 3, 0, -3, -6, -3}, /* fnum = 110xxxxxx */ + {0, 3, 7, 3, 0, -3, -7, -3}, /* fnum = 111xxxxxx */ +}; + +/* amplitude lfo table */ +/* The following envelop pattern is verified on real YM2413. */ +/* each element repeates 64 cycles */ +static uint8_t am_table[210] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* */ + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* */ + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, /* */ + 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, /* */ + 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, /* */ + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, /* */ + 12, 12, 12, 12, 12, 12, 12, 12, /* */ + 13, 13, 13, /* */ + 12, 12, 12, 12, 12, 12, 12, 12, /* */ + 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, /* */ + 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, /* */ + 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, /* */ + 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* */ + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, /* */ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 +}; + +/* envelope decay increment step table */ +/* based on andete's research */ +static uint8_t eg_step_tables[4][8] = { + {0, 1, 0, 1, 0, 1, 0, 1}, + {0, 1, 0, 1, 1, 1, 0, 1}, + {0, 1, 1, 1, 0, 1, 1, 1}, + {0, 1, 1, 1, 1, 1, 1, 1}, +}; + +enum __OPLL_EG_STATE { ATTACK, DECAY, SUSTAIN, RELEASE, DAMP, UNKNOWN }; + +static uint32_t ml_table[16] = {1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, + 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2}; + +#define dB2(x) ((x)*2) +static double kl_table[16] = {dB2(0.000), dB2(9.000), dB2(12.000), dB2(13.875), dB2(15.000), dB2(16.125), + dB2(16.875), dB2(17.625), dB2(18.000), dB2(18.750), dB2(19.125), dB2(19.500), + dB2(19.875), dB2(20.250), dB2(20.625), dB2(21.000)}; + +static uint32_t tll_table[8 * 16][1 << TL_BITS][4]; +static int32_t rks_table[8 * 2][2]; + +static OPLL_PATCH null_patch = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +static OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2]; + +/* don't forget min/max is defined as a macro in stdlib.h of Visual C. */ +#ifndef min +static INLINE int min(int i, int j) { return (i < j) ? i : j; } +#endif +#ifndef max +static INLINE int max(int i, int j) { return (i > j) ? i : j; } +#endif + +/*************************************************** + + Internal Sample Rate Converter + +****************************************************/ +/* Note: to disable internal rate converter, set clock/72 to output sampling rate. */ + +/* + * LW is truncate length of sinc(x) calculation. + * Lower LW is faster, higher LW results better quality. + * LW must be a non-zero positive even number, no upper limit. + * LW=16 or greater is recommended when upsampling. + * LW=8 is practically okay for downsampling. + */ +#define LW 16 + +/* resolution of sinc(x) table. sinc(x) where 0.0<=x<1.0 corresponds to sinc_table[0...SINC_RESO-1] */ +#define SINC_RESO 256 +#define SINC_AMP_BITS 12 + +/* double hamming(double x) { return 0.54 - 0.46 * cos(2 * PI * x); } */ +static double blackman(double x) { return 0.42 - 0.5 * cos(2 * _PI_ * x) + 0.08 * cos(4 * _PI_ * x); } +static double sinc(double x) { return (x == 0.0 ? 1.0 : sin(_PI_ * x) / (_PI_ * x)); } +static double windowed_sinc(double x) { return blackman(0.5 + 0.5 * x / (LW / 2)) * sinc(x); } + +/* f_inp: input frequency. f_out: output frequencey, ch: number of channels */ +OPLL_RateConv *OPLL_RateConv_new(double f_inp, double f_out, int ch) { + OPLL_RateConv *conv = malloc(sizeof(OPLL_RateConv)); + int i; + + conv->ch = ch; + conv->f_ratio = f_inp / f_out; + conv->buf = malloc(sizeof(void *) * ch); + for (i = 0; i < ch; i++) { + conv->buf[i] = malloc(sizeof(conv->buf[0][0]) * LW); + } + + /* create sinc_table for positive 0 <= x < LW/2 */ + conv->sinc_table = malloc(sizeof(conv->sinc_table[0]) * SINC_RESO * LW / 2); + for (i = 0; i < SINC_RESO * LW / 2; i++) { + const double x = (double)i / SINC_RESO; + if (f_out < f_inp) { + /* for downsampling */ + conv->sinc_table[i] = (int16_t)((1 << SINC_AMP_BITS) * windowed_sinc(x / conv->f_ratio) / conv->f_ratio); + } else { + /* for upsampling */ + conv->sinc_table[i] = (int16_t)((1 << SINC_AMP_BITS) * windowed_sinc(x)); + } + } + + return conv; +} + +static INLINE int16_t lookup_sinc_table(int16_t *table, double x) { + int16_t index = (int16_t)(x * SINC_RESO); + if (index < 0) + index = -index; + return table[min(SINC_RESO * LW / 2 - 1, index)]; +} + +void OPLL_RateConv_reset(OPLL_RateConv *conv) { + int i; + conv->timer = 0; + for (i = 0; i < conv->ch; i++) { + memset(conv->buf[i], 0, sizeof(conv->buf[i][0]) * LW); + } +} + +/* put original data to this converter at f_inp. */ +void OPLL_RateConv_putData(OPLL_RateConv *conv, int ch, int16_t data) { + int16_t *buf = conv->buf[ch]; + int i; + for (i = 0; i < LW - 1; i++) { + buf[i] = buf[i + 1]; + } + buf[LW - 1] = data; +} + +/* get resampled data from this converter at f_out. */ +/* this function must be called f_out / f_inp times per one putData call. */ +int16_t OPLL_RateConv_getData(OPLL_RateConv *conv, int ch) { + int16_t *buf = conv->buf[ch]; + int32_t sum = 0; + int k; + double dn; + conv->timer += conv->f_ratio; + dn = conv->timer - floor(conv->timer); + conv->timer = dn; + + for (k = 0; k < LW; k++) { + double x = ((double)k - (LW / 2 - 1)) - dn; + sum += buf[k] * lookup_sinc_table(conv->sinc_table, x); + } + return sum >> SINC_AMP_BITS; +} + +void OPLL_RateConv_delete(OPLL_RateConv *conv) { + int i; + for (i = 0; i < conv->ch; i++) { + free(conv->buf[i]); + } + free(conv->buf); + free(conv->sinc_table); + free(conv); +} + +/*************************************************** + + Create tables + +****************************************************/ + +static void makeSinTable(void) { + int x; + + for (x = 0; x < PG_WIDTH / 4; x++) { + fullsin_table[PG_WIDTH / 4 + x] = fullsin_table[PG_WIDTH / 4 - x - 1]; + } + + for (x = 0; x < PG_WIDTH / 2; x++) { + fullsin_table[PG_WIDTH / 2 + x] = 0x8000 | fullsin_table[x]; + } + + for (x = 0; x < PG_WIDTH / 2; x++) + halfsin_table[x] = fullsin_table[x]; + + for (x = PG_WIDTH / 2; x < PG_WIDTH; x++) + halfsin_table[x] = 0xfff; +} + +static void makeTllTable(void) { + + int32_t tmp; + int32_t fnum, block, TL, KL; + + for (fnum = 0; fnum < 16; fnum++) { + for (block = 0; block < 8; block++) { + for (TL = 0; TL < 64; TL++) { + for (KL = 0; KL < 4; KL++) { + if (KL == 0) { + tll_table[(block << 4) | fnum][TL][KL] = TL2EG(TL); + } else { + tmp = (int32_t)(kl_table[fnum] - dB2(3.000) * (7 - block)); + if (tmp <= 0) + tll_table[(block << 4) | fnum][TL][KL] = TL2EG(TL); + else + tll_table[(block << 4) | fnum][TL][KL] = (uint32_t)((tmp >> (3 - KL)) / EG_STEP) + TL2EG(TL); + } + } + } + } + } +} + +static void makeRksTable(void) { + int fnum8, block; + for (fnum8 = 0; fnum8 < 2; fnum8++) + for (block = 0; block < 8; block++) { + rks_table[(block << 1) | fnum8][1] = (block << 1) + fnum8; + rks_table[(block << 1) | fnum8][0] = block >> 1; + } +} + +static void makeDefaultPatch(void) { + int i, j; + for (i = 0; i < OPLL_TONE_NUM; i++) + for (j = 0; j < 19; j++) + OPLL_getDefaultPatch(i, j, &default_patch[i][j * 2]); +} + +static uint8_t table_initialized = 0; + +static void initializeTables(void) { + makeTllTable(); + makeRksTable(); + makeSinTable(); + makeDefaultPatch(); + table_initialized = 1; +} + +/********************************************************* + + Synthesizing + +*********************************************************/ +#define SLOT_BD1 12 +#define SLOT_BD2 13 +#define SLOT_HH 14 +#define SLOT_SD 15 +#define SLOT_TOM 16 +#define SLOT_CYM 17 + +/* utility macros */ +#define MOD(o, x) (&(o)->slot[(x) << 1]) +#define CAR(o, x) (&(o)->slot[((x) << 1) | 1]) +#define BIT(s, b) (((s) >> (b)) & 1) + +#if OPLL_DEBUG +static void _debug_print_patch(OPLL_SLOT *slot) { + OPLL_PATCH *p = slot->patch; + printf("[slot#%d am:%d pm:%d eg:%d kr:%d ml:%d kl:%d tl:%d ws:%d fb:%d A:%d D:%d S:%d R:%d]\n", slot->number, // + p->AM, p->PM, p->EG, p->KR, p->ML, // + p->KL, p->TL, p->WS, p->FB, // + p->AR, p->DR, p->SL, p->RR); +} + +static char *_debug_eg_state_name(OPLL_SLOT *slot) { + switch (slot->eg_state) { + case ATTACK: + return "attack"; + case DECAY: + return "decay"; + case SUSTAIN: + return "sustain"; + case RELEASE: + return "release"; + case DAMP: + return "damp"; + default: + return "unknown"; + } +} + +static INLINE void _debug_print_slot_info(OPLL_SLOT *slot) { + char *name = _debug_eg_state_name(slot); + printf("[slot#%d state:%s fnum:%03x rate:%d-%d]\n", slot->number, name, slot->blk_fnum, slot->eg_rate_h, + slot->eg_rate_l); + _debug_print_patch(slot); + fflush(stdout); +} +#endif + +static INLINE int get_parameter_rate(OPLL_SLOT *slot) { + + if ((slot->type & 1) == 0 && slot->key_flag == 0) { + return 0; + } + + switch (slot->eg_state) { + case ATTACK: + return slot->patch->AR; + case DECAY: + return slot->patch->DR; + case SUSTAIN: + return slot->patch->EG ? 0 : slot->patch->RR; + case RELEASE: + if (slot->sus_flag) { + return 5; + } else if (slot->patch->EG) { + return slot->patch->RR; + } else { + return 7; + } + case DAMP: + return DAMPER_RATE; + default: + return 0; + } +} + +enum SLOT_UPDATE_FLAG { + UPDATE_WS = 1, + UPDATE_TLL = 2, + UPDATE_RKS = 4, + UPDATE_EG = 8, + UPDATE_ALL = 255 +}; + +static INLINE void request_update(OPLL_SLOT *slot, int flag) { slot->update_requests |= flag; } + +static void commit_slot_update(OPLL_SLOT *slot) { + +#if OPLL_DEBUG + if (slot->last_eg_state != slot->eg_state) { + _debug_print_slot_info(slot); + slot->last_eg_state = slot->eg_state; + } +#endif + + if (slot->update_requests & UPDATE_WS) { + slot->wave_table = wave_table_map[slot->patch->WS]; + } + + if (slot->update_requests & UPDATE_TLL) { + if ((slot->type & 1) == 0) { + slot->tll = tll_table[slot->blk_fnum >> 5][slot->patch->TL][slot->patch->KL]; + } else { + slot->tll = tll_table[slot->blk_fnum >> 5][slot->volume][slot->patch->KL]; + } + } + + if (slot->update_requests & UPDATE_RKS) { + slot->rks = rks_table[slot->blk_fnum >> 8][slot->patch->KR]; + } + + if (slot->update_requests & (UPDATE_RKS | UPDATE_EG)) { + int p_rate = get_parameter_rate(slot); + + if (p_rate == 0) { + slot->eg_shift = 0; + slot->eg_rate_h = 0; + slot->eg_rate_l = 0; + return; + } + + slot->eg_rate_h = min(15, p_rate + (slot->rks >> 2)); + slot->eg_rate_l = slot->rks & 3; + if (slot->eg_state == ATTACK) { + slot->eg_shift = (0 < slot->eg_rate_h && slot->eg_rate_h < 12) ? (13 - slot->eg_rate_h) : 0; + } else { + slot->eg_shift = (slot->eg_rate_h < 13) ? (13 - slot->eg_rate_h) : 0; + } + } + + slot->update_requests = 0; +} + +static void reset_slot(OPLL_SLOT *slot, int number) { + slot->number = number; + slot->type = number % 2; + slot->pg_keep = 0; + slot->wave_table = wave_table_map[0]; + slot->pg_phase = 0; + slot->output[0] = 0; + slot->output[1] = 0; + slot->eg_state = RELEASE; + slot->eg_shift = 0; + slot->rks = 0; + slot->tll = 0; + slot->key_flag = 0; + slot->sus_flag = 0; + slot->blk_fnum = 0; + slot->blk = 0; + slot->fnum = 0; + slot->volume = 0; + slot->pg_out = 0; + slot->eg_out = EG_MUTE; + slot->patch = &null_patch; +} + +static INLINE void slotOn(OPLL *opll, int i) { + OPLL_SLOT *slot = &opll->slot[i]; + slot->key_flag = 1; + slot->eg_state = DAMP; + request_update(slot, UPDATE_EG); +} + +static INLINE void slotOff(OPLL *opll, int i) { + OPLL_SLOT *slot = &opll->slot[i]; + slot->key_flag = 0; + if (slot->type & 1) { + slot->eg_state = RELEASE; + request_update(slot, UPDATE_EG); + } +} + +static INLINE void update_key_status(OPLL *opll) { + const uint8_t r14 = opll->reg[0x0e]; + const uint8_t rhythm_mode = BIT(r14, 5); + uint32_t new_slot_key_status = 0; + uint32_t updated_status; + int ch; + + for (ch = 0; ch < 9; ch++) + if (opll->reg[0x20 + ch] & 0x10) + new_slot_key_status |= 3 << (ch * 2); + + if (rhythm_mode) { + if (r14 & 0x10) + new_slot_key_status |= 3 << SLOT_BD1; + + if (r14 & 0x01) + new_slot_key_status |= 1 << SLOT_HH; + + if (r14 & 0x08) + new_slot_key_status |= 1 << SLOT_SD; + + if (r14 & 0x04) + new_slot_key_status |= 1 << SLOT_TOM; + + if (r14 & 0x02) + new_slot_key_status |= 1 << SLOT_CYM; + } + + updated_status = opll->slot_key_status ^ new_slot_key_status; + + if (updated_status) { + int i; + for (i = 0; i < 18; i++) + if (BIT(updated_status, i)) { + if (BIT(new_slot_key_status, i)) { + slotOn(opll, i); + } else { + slotOff(opll, i); + } + } + } + + opll->slot_key_status = new_slot_key_status; +} + +static INLINE void set_patch(OPLL *opll, int32_t ch, int32_t num) { + opll->patch_number[ch] = num; + MOD(opll, ch)->patch = &opll->patch[num * 2 + 0]; + CAR(opll, ch)->patch = &opll->patch[num * 2 + 1]; + request_update(MOD(opll, ch), UPDATE_ALL); + request_update(CAR(opll, ch), UPDATE_ALL); +} + +static INLINE void set_sus_flag(OPLL *opll, int ch, int flag) { + CAR(opll, ch)->sus_flag = flag; + request_update(CAR(opll, ch), UPDATE_EG); + if (MOD(opll, ch)->type & 1) { + MOD(opll, ch)->sus_flag = flag; + request_update(MOD(opll, ch), UPDATE_EG); + } +} + +/* set volume ( volume : 6bit, register value << 2 ) */ +static INLINE void set_volume(OPLL *opll, int ch, int volume) { + CAR(opll, ch)->volume = volume; + request_update(CAR(opll, ch), UPDATE_TLL); +} + +static INLINE void set_slot_volume(OPLL_SLOT *slot, int volume) { + slot->volume = volume; + request_update(slot, UPDATE_TLL); +} + +/* set f-Nnmber ( fnum : 9bit ) */ +static INLINE void set_fnumber(OPLL *opll, int ch, int fnum) { + OPLL_SLOT *car = CAR(opll, ch); + OPLL_SLOT *mod = MOD(opll, ch); + car->fnum = fnum; + car->blk_fnum = (car->blk_fnum & 0xe00) | (fnum & 0x1ff); + mod->fnum = fnum; + mod->blk_fnum = (mod->blk_fnum & 0xe00) | (fnum & 0x1ff); + request_update(car, UPDATE_EG | UPDATE_RKS | UPDATE_TLL); + request_update(mod, UPDATE_EG | UPDATE_RKS | UPDATE_TLL); +} + +/* set block data (blk : 3bit ) */ +static INLINE void set_block(OPLL *opll, int ch, int blk) { + OPLL_SLOT *car = CAR(opll, ch); + OPLL_SLOT *mod = MOD(opll, ch); + car->blk = blk; + car->blk_fnum = ((blk & 7) << 9) | (car->blk_fnum & 0x1ff); + mod->blk = blk; + mod->blk_fnum = ((blk & 7) << 9) | (mod->blk_fnum & 0x1ff); + request_update(car, UPDATE_EG | UPDATE_RKS | UPDATE_TLL); + request_update(mod, UPDATE_EG | UPDATE_RKS | UPDATE_TLL); +} + +static INLINE void update_rhythm_mode(OPLL *opll) { + const uint8_t new_rhythm_mode = (opll->reg[0x0e] >> 5) & 1; + + if (opll->rhythm_mode != new_rhythm_mode) { + + if (new_rhythm_mode) { + opll->slot[SLOT_HH].type = 3; + opll->slot[SLOT_HH].pg_keep = 1; + opll->slot[SLOT_SD].type = 3; + opll->slot[SLOT_TOM].type = 3; + opll->slot[SLOT_CYM].type = 3; + opll->slot[SLOT_CYM].pg_keep = 1; + set_patch(opll, 6, 16); + set_patch(opll, 7, 17); + set_patch(opll, 8, 18); + set_slot_volume(&opll->slot[SLOT_HH], ((opll->reg[0x37] >> 4) & 15) << 2); + set_slot_volume(&opll->slot[SLOT_TOM], ((opll->reg[0x38] >> 4) & 15) << 2); + } else { + opll->slot[SLOT_HH].type = 0; + opll->slot[SLOT_HH].pg_keep = 0; + opll->slot[SLOT_SD].type = 1; + opll->slot[SLOT_TOM].type = 0; + opll->slot[SLOT_CYM].type = 1; + opll->slot[SLOT_CYM].pg_keep = 0; + set_patch(opll, 6, opll->reg[0x36] >> 4); + set_patch(opll, 7, opll->reg[0x37] >> 4); + set_patch(opll, 8, opll->reg[0x38] >> 4); + } + } + + opll->rhythm_mode = new_rhythm_mode; +} + +static void update_ampm(OPLL *opll) { + if (opll->test_flag & 2) { + opll->pm_phase = 0; + opll->am_phase = 0; + } else { + opll->pm_phase += (opll->test_flag & 8) ? 1024 : 1; + opll->am_phase += (opll->test_flag & 8) ? 64 : 1; + } + opll->lfo_am = am_table[(opll->am_phase >> 6) % sizeof(am_table)]; +} + +static void update_noise(OPLL *opll, int cycle) { + int i; + for (i = 0; i < cycle; i++) { + if (opll->noise & 1) { + opll->noise ^= 0x800200; + } + opll->noise >>= 1; + } +} + +static void update_short_noise(OPLL *opll) { + const uint32_t pg_hh = opll->slot[SLOT_HH].pg_out; + const uint32_t pg_cym = opll->slot[SLOT_CYM].pg_out; + + const uint8_t h_bit2 = BIT(pg_hh, PG_BITS - 8); + const uint8_t h_bit7 = BIT(pg_hh, PG_BITS - 3); + const uint8_t h_bit3 = BIT(pg_hh, PG_BITS - 7); + + const uint8_t c_bit3 = BIT(pg_cym, PG_BITS - 7); + const uint8_t c_bit5 = BIT(pg_cym, PG_BITS - 5); + + opll->short_noise = (h_bit2 ^ h_bit7) | (h_bit3 ^ c_bit5) | (c_bit3 ^ c_bit5); +} + +static INLINE void calc_phase(OPLL_SLOT *slot, int32_t pm_phase, uint8_t reset) { + const int8_t pm = slot->patch->PM ? pm_table[(slot->fnum >> 6) & 7][(pm_phase >> 10) & 7] : 0; + if (reset) { + slot->pg_phase = 0; + } + slot->pg_phase += (((slot->fnum & 0x1ff) * 2 + pm) * ml_table[slot->patch->ML]) << slot->blk >> 2; + slot->pg_phase &= (DP_WIDTH - 1); + slot->pg_out = slot->pg_phase >> DP_BASE_BITS; +} + +static INLINE uint8_t lookup_attack_step(OPLL_SLOT *slot, uint32_t counter) { + int index; + + switch (slot->eg_rate_h) { + case 12: + index = (counter & 0xc) >> 1; + return 4 - eg_step_tables[slot->eg_rate_l][index]; + case 13: + index = (counter & 0xc) >> 1; + return 3 - eg_step_tables[slot->eg_rate_l][index]; + case 14: + index = (counter & 0xc) >> 1; + return 2 - eg_step_tables[slot->eg_rate_l][index]; + case 0: + case 15: + return 0; + default: + index = counter >> slot->eg_shift; + return eg_step_tables[slot->eg_rate_l][index & 7] ? 4 : 0; + } +} + +static INLINE uint8_t lookup_decay_step(OPLL_SLOT *slot, uint32_t counter) { + int index; + + switch (slot->eg_rate_h) { + case 0: + return 0; + case 13: + index = ((counter & 0xc) >> 1) | (counter & 1); + return eg_step_tables[slot->eg_rate_l][index]; + case 14: + index = ((counter & 0xc) >> 1); + return eg_step_tables[slot->eg_rate_l][index] + 1; + case 15: + return 2; + default: + index = counter >> slot->eg_shift; + return eg_step_tables[slot->eg_rate_l][index & 7]; + } +} + +static INLINE void start_envelope(OPLL_SLOT *slot) { + if (min(15, slot->patch->AR + (slot->rks >> 2)) == 15) { + slot->eg_state = DECAY; + slot->eg_out = 0; + } else { + slot->eg_state = ATTACK; + } + request_update(slot, UPDATE_EG); +} + +static INLINE void calc_envelope(OPLL_SLOT *slot, OPLL_SLOT *buddy, uint16_t eg_counter, uint8_t test) { + + uint32_t mask = (1 << slot->eg_shift) - 1; + uint8_t s; + + if (slot->eg_state == ATTACK) { + if (0 < slot->eg_out && 0 < slot->eg_rate_h && (eg_counter & mask & ~3) == 0) { + s = lookup_attack_step(slot, eg_counter); + if (0 < s) { + slot->eg_out = max(0, ((int)slot->eg_out - (slot->eg_out >> s) - 1)); + } + } + } else { + if (slot->eg_rate_h > 0 && (eg_counter & mask) == 0) { + slot->eg_out = min(EG_MUTE, slot->eg_out + lookup_decay_step(slot, eg_counter)); + } + } + + switch (slot->eg_state) { + case DAMP: + /* DAMP to ATTACK transition is occured when the envelope reaches EG_MAX (max attenuation but it's not mute). + Do not forget to check (eg_counter & mask) == 0 to synchronize it with the progress of the envelope. */ + if (slot->eg_out >= EG_MAX && (eg_counter & mask) == 0) { + start_envelope(slot); + if (slot->type & 1) { + if (!slot->pg_keep) { + slot->pg_phase = 0; + } + if (buddy && !buddy->pg_keep) { + buddy->pg_phase = 0; + } + } + } + break; + + case ATTACK: + if (slot->eg_out == 0) { + slot->eg_state = DECAY; + request_update(slot, UPDATE_EG); + } + break; + + case DECAY: + /* DECAY to SUSTAIN transition must be checked at every cycle regardless of the conditions of the envelope rate and + counter. i.e. the transition is not synchronized with the progress of the envelope. */ + if ((slot->eg_out >> 3) == slot->patch->SL) { + slot->eg_state = SUSTAIN; + request_update(slot, UPDATE_EG); + } + break; + + case SUSTAIN: + case RELEASE: + default: + break; + } + + if (test) { + slot->eg_out = 0; + } +} + +static void update_slots(OPLL *opll) { + int i; + opll->eg_counter++; + + for (i = 0; i < 18; i++) { + OPLL_SLOT *slot = &opll->slot[i]; + OPLL_SLOT *buddy = NULL; + if (slot->type == 0) { + buddy = &opll->slot[i + 1]; + } + if (slot->type == 1) { + buddy = &opll->slot[i - 1]; + } + if (slot->update_requests) { + commit_slot_update(slot); + } + calc_envelope(slot, buddy, opll->eg_counter, opll->test_flag & 1); + calc_phase(slot, opll->pm_phase, opll->test_flag & 4); + } +} + +/* output: -4095...4095 */ +static INLINE int16_t lookup_exp_table(uint16_t i) { + /* from andete's expression */ + int16_t t = (exp_table[(i & 0xff) ^ 0xff] + 1024); + int16_t res = t >> ((i & 0x7f00) >> 8); + return ((i & 0x8000) ? ~res : res) << 1; +} + +static INLINE int16_t to_linear(uint16_t h, OPLL_SLOT *slot, int16_t am) { + uint16_t att; + if (slot->eg_out > EG_MAX) + return 0; + + att = min(EG_MUTE, (slot->eg_out + slot->tll + am)) << 4; + return lookup_exp_table(h + att); +} + +static INLINE int16_t calc_slot_car(OPLL *opll, int ch, int16_t fm) { + OPLL_SLOT *slot = CAR(opll, ch); + + uint8_t am = slot->patch->AM ? opll->lfo_am : 0; + + slot->output[1] = slot->output[0]; + slot->output[0] = to_linear(slot->wave_table[(slot->pg_out + 2 * (fm >> 1)) & (PG_WIDTH - 1)], slot, am); + + return slot->output[0]; +} + +static INLINE int16_t calc_slot_mod(OPLL *opll, int ch) { + OPLL_SLOT *slot = MOD(opll, ch); + + int16_t fm = slot->patch->FB > 0 ? (slot->output[1] + slot->output[0]) >> (9 - slot->patch->FB) : 0; + uint8_t am = slot->patch->AM ? opll->lfo_am : 0; + + slot->output[1] = slot->output[0]; + slot->output[0] = to_linear(slot->wave_table[(slot->pg_out + fm) & (PG_WIDTH - 1)], slot, am); + + return slot->output[0]; +} + +static INLINE int16_t calc_slot_tom(OPLL *opll) { + OPLL_SLOT *slot = MOD(opll, 8); + + return to_linear(slot->wave_table[slot->pg_out], slot, 0); +} + +/* Specify phase offset directly based on 10-bit (1024-length) sine table */ +#define _PD(phase) ((PG_BITS < 10) ? (phase >> (10 - PG_BITS)) : (phase << (PG_BITS - 10))) + +static INLINE int16_t calc_slot_snare(OPLL *opll) { + OPLL_SLOT *slot = CAR(opll, 7); + + uint32_t phase; + + if (BIT(slot->pg_out, PG_BITS - 2)) + phase = (opll->noise & 1) ? _PD(0x300) : _PD(0x200); + else + phase = (opll->noise & 1) ? _PD(0x0) : _PD(0x100); + + return to_linear(slot->wave_table[phase], slot, 0); +} + +static INLINE int16_t calc_slot_cym(OPLL *opll) { + OPLL_SLOT *slot = CAR(opll, 8); + + uint32_t phase = opll->short_noise ? _PD(0x300) : _PD(0x100); + + return to_linear(slot->wave_table[phase], slot, 0); +} + +static INLINE int16_t calc_slot_hat(OPLL *opll) { + OPLL_SLOT *slot = MOD(opll, 7); + + uint32_t phase; + + if (opll->short_noise) + phase = (opll->noise & 1) ? _PD(0x2d0) : _PD(0x234); + else + phase = (opll->noise & 1) ? _PD(0x34) : _PD(0xd0); + + return to_linear(slot->wave_table[phase], slot, 0); +} + +#define _MO(x) (-(x) >> 1) +#define _RO(x) (x) + +static void update_output(OPLL *opll) { + int16_t *out; + int i; + + update_ampm(opll); + update_short_noise(opll); + update_slots(opll); + + out = opll->ch_out; + + /* CH1-6 */ + for (i = 0; i < 6; i++) { + if (!(opll->mask & OPLL_MASK_CH(i))) { + out[i] = _MO(calc_slot_car(opll, i, calc_slot_mod(opll, i))); + } + } + + /* CH7 */ + if (!opll->rhythm_mode) { + if (!(opll->mask & OPLL_MASK_CH(6))) { + out[6] = _MO(calc_slot_car(opll, 6, calc_slot_mod(opll, 6))); + } + } else { + if (!(opll->mask & OPLL_MASK_BD)) { + out[9] = _RO(calc_slot_car(opll, 6, calc_slot_mod(opll, 6))); + } + } + update_noise(opll, 14); + + /* CH8 */ + if (!opll->rhythm_mode) { + if (!(opll->mask & OPLL_MASK_CH(7))) { + out[7] = _MO(calc_slot_car(opll, 7, calc_slot_mod(opll, 7))); + } + } else { + if (!(opll->mask & OPLL_MASK_HH)) { + out[10] = _RO(calc_slot_hat(opll)); + } + if (!(opll->mask & OPLL_MASK_SD)) { + out[11] = _RO(calc_slot_snare(opll)); + } + } + update_noise(opll, 2); + + /* CH9 */ + if (!opll->rhythm_mode) { + if (!(opll->mask & OPLL_MASK_CH(8))) { + out[8] = _MO(calc_slot_car(opll, 8, calc_slot_mod(opll, 8))); + } + } else { + if (!(opll->mask & OPLL_MASK_TOM)) { + out[12] = _RO(calc_slot_tom(opll)); + } + if (!(opll->mask & OPLL_MASK_CYM)) { + out[13] = _RO(calc_slot_cym(opll)); + } + } + update_noise(opll, 2); +} + +INLINE static void mix_output(OPLL *opll) { + int16_t out = 0; + int i; + for (i = 0; i < 14; i++) { + out += opll->ch_out[i]; + } + if (opll->conv) { + OPLL_RateConv_putData(opll->conv, 0, out); + } else { + opll->mix_out[0] = out; + } +} + +INLINE static void mix_output_stereo(OPLL *opll) { + int16_t *out = opll->mix_out; + int i; + out[0] = out[1] = 0; + for (i = 0; i < 14; i++) { + if (opll->pan[i] & 2) + out[0] += (int16_t)(opll->ch_out[i] * opll->pan_fine[i][0]); + if (opll->pan[i] & 1) + out[1] += (int16_t)(opll->ch_out[i] * opll->pan_fine[i][1]); + } + if (opll->conv) { + OPLL_RateConv_putData(opll->conv, 0, out[0]); + OPLL_RateConv_putData(opll->conv, 1, out[1]); + } +} + +/*********************************************************** + + External Interfaces + +***********************************************************/ + +OPLL *OPLL_new(uint32_t clk, uint32_t rate) { + OPLL *opll; + int i; + + if (!table_initialized) { + initializeTables(); + } + + opll = (OPLL *)calloc(sizeof(OPLL), 1); + if (opll == NULL) + return NULL; + + for (i = 0; i < 19 * 2; i++) + memcpy(&opll->patch[i], &null_patch, sizeof(OPLL_PATCH)); + + opll->clk = clk; + opll->rate = rate; + opll->mask = 0; + opll->conv = NULL; + opll->mix_out[0] = 0; + opll->mix_out[1] = 0; + + OPLL_reset(opll); + OPLL_setChipType(opll, 0); + OPLL_resetPatch(opll, 0); + return opll; +} + +void OPLL_delete(OPLL *opll) { + if (opll->conv) { + OPLL_RateConv_delete(opll->conv); + opll->conv = NULL; + } + free(opll); +} + +static void reset_rate_conversion_params(OPLL *opll) { + const double f_out = opll->rate; + const double f_inp = opll->clk / 72.0; + + opll->out_time = 0; + opll->out_step = f_inp; + opll->inp_step = f_out; + + if (opll->conv) { + OPLL_RateConv_delete(opll->conv); + opll->conv = NULL; + } + + if (floor(f_inp) != f_out && floor(f_inp + 0.5) != f_out) { + opll->conv = OPLL_RateConv_new(f_inp, f_out, 2); + } + + if (opll->conv) { + OPLL_RateConv_reset(opll->conv); + } +} + +void OPLL_reset(OPLL *opll) { + int i; + + if (!opll) + return; + + opll->adr = 0; + + opll->pm_phase = 0; + opll->am_phase = 0; + + opll->noise = 0x1; + opll->mask = 0; + + opll->rhythm_mode = 0; + opll->slot_key_status = 0; + opll->eg_counter = 0; + + reset_rate_conversion_params(opll); + + for (i = 0; i < 18; i++) + reset_slot(&opll->slot[i], i); + + for (i = 0; i < 9; i++) { + set_patch(opll, i, 0); + } + + for (i = 0; i < 0x40; i++) + OPLL_writeReg(opll, i, 0); + + for (i = 0; i < 15; i++) { + opll->pan[i] = 3; + opll->pan_fine[i][1] = opll->pan_fine[i][0] = 1.0f; + } + + for (i = 0; i < 14; i++) { + opll->ch_out[i] = 0; + } +} + +void OPLL_forceRefresh(OPLL *opll) { + int i; + + if (opll == NULL) + return; + + for (i = 0; i < 9; i++) { + set_patch(opll, i, opll->patch_number[i]); + } + + for (i = 0; i < 18; i++) { + request_update(&opll->slot[i], UPDATE_ALL); + } +} + +void OPLL_setRate(OPLL *opll, uint32_t rate) { + opll->rate = rate; + reset_rate_conversion_params(opll); +} + +void OPLL_setQuality(OPLL *opll, uint8_t q) {} + +void OPLL_setChipType(OPLL *opll, uint8_t type) { opll->chip_type = type; } + +void OPLL_writeReg(OPLL *opll, uint32_t reg, uint8_t data) { + int ch, i; + + if (reg >= 0x40) + return; + + /* mirror registers */ + if ((0x19 <= reg && reg <= 0x1f) || (0x29 <= reg && reg <= 0x2f) || (0x39 <= reg && reg <= 0x3f)) { + reg -= 9; + } + + opll->reg[reg] = (uint8_t)data; + + switch (reg) { + case 0x00: + opll->patch[0].AM = (data >> 7) & 1; + opll->patch[0].PM = (data >> 6) & 1; + opll->patch[0].EG = (data >> 5) & 1; + opll->patch[0].KR = (data >> 4) & 1; + opll->patch[0].ML = (data)&15; + for (i = 0; i < 9; i++) { + if (opll->patch_number[i] == 0) { + request_update(MOD(opll, i), UPDATE_RKS | UPDATE_EG); + } + } + break; + + case 0x01: + opll->patch[1].AM = (data >> 7) & 1; + opll->patch[1].PM = (data >> 6) & 1; + opll->patch[1].EG = (data >> 5) & 1; + opll->patch[1].KR = (data >> 4) & 1; + opll->patch[1].ML = (data)&15; + for (i = 0; i < 9; i++) { + if (opll->patch_number[i] == 0) { + request_update(CAR(opll, i), UPDATE_RKS | UPDATE_EG); + } + } + break; + + case 0x02: + opll->patch[0].KL = (data >> 6) & 3; + opll->patch[0].TL = (data)&63; + for (i = 0; i < 9; i++) { + if (opll->patch_number[i] == 0) { + request_update(MOD(opll, i), UPDATE_TLL); + } + } + break; + + case 0x03: + opll->patch[1].KL = (data >> 6) & 3; + opll->patch[1].WS = (data >> 4) & 1; + opll->patch[0].WS = (data >> 3) & 1; + opll->patch[0].FB = (data)&7; + for (i = 0; i < 9; i++) { + if (opll->patch_number[i] == 0) { + request_update(MOD(opll, i), UPDATE_WS); + request_update(CAR(opll, i), UPDATE_WS | UPDATE_TLL); + } + } + break; + + case 0x04: + opll->patch[0].AR = (data >> 4) & 15; + opll->patch[0].DR = (data)&15; + for (i = 0; i < 9; i++) { + if (opll->patch_number[i] == 0) { + request_update(MOD(opll, i), UPDATE_EG); + } + } + break; + + case 0x05: + opll->patch[1].AR = (data >> 4) & 15; + opll->patch[1].DR = (data)&15; + for (i = 0; i < 9; i++) { + if (opll->patch_number[i] == 0) { + request_update(CAR(opll, i), UPDATE_EG); + } + } + break; + + case 0x06: + opll->patch[0].SL = (data >> 4) & 15; + opll->patch[0].RR = (data)&15; + for (i = 0; i < 9; i++) { + if (opll->patch_number[i] == 0) { + request_update(MOD(opll, i), UPDATE_EG); + } + } + break; + + case 0x07: + opll->patch[1].SL = (data >> 4) & 15; + opll->patch[1].RR = (data)&15; + for (i = 0; i < 9; i++) { + if (opll->patch_number[i] == 0) { + request_update(CAR(opll, i), UPDATE_EG); + } + } + break; + + case 0x0e: + if (opll->chip_type == 1) + break; + update_rhythm_mode(opll); + update_key_status(opll); + break; + + case 0x0f: + opll->test_flag = data; + break; + + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + ch = reg - 0x10; + set_fnumber(opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8)); + break; + + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + ch = reg - 0x20; + set_fnumber(opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]); + set_block(opll, ch, (data >> 1) & 7); + set_sus_flag(opll, ch, (data >> 5) & 1); + update_key_status(opll); + break; + + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + if ((opll->reg[0x0e] & 32) && (reg >= 0x36)) { + switch (reg) { + case 0x37: + set_slot_volume(MOD(opll, 7), ((data >> 4) & 15) << 2); + break; + case 0x38: + set_slot_volume(MOD(opll, 8), ((data >> 4) & 15) << 2); + break; + default: + break; + } + } else { + set_patch(opll, reg - 0x30, (data >> 4) & 15); + } + set_volume(opll, reg - 0x30, (data & 15) << 2); + break; + + default: + break; + } +} + +void OPLL_writeIO(OPLL *opll, uint32_t adr, uint8_t val) { + if (adr & 1) + OPLL_writeReg(opll, opll->adr, val); + else + opll->adr = val; +} + +void OPLL_setPan(OPLL *opll, uint32_t ch, uint8_t pan) { opll->pan[ch & 15] = pan; } + +void OPLL_setPanFine(OPLL *opll, uint32_t ch, float pan[2]) { + opll->pan_fine[ch & 15][0] = pan[0]; + opll->pan_fine[ch & 15][1] = pan[1]; +} + +void OPLL_dumpToPatch(const uint8_t *dump, OPLL_PATCH *patch) { + patch[0].AM = (dump[0] >> 7) & 1; + patch[1].AM = (dump[1] >> 7) & 1; + patch[0].PM = (dump[0] >> 6) & 1; + patch[1].PM = (dump[1] >> 6) & 1; + patch[0].EG = (dump[0] >> 5) & 1; + patch[1].EG = (dump[1] >> 5) & 1; + patch[0].KR = (dump[0] >> 4) & 1; + patch[1].KR = (dump[1] >> 4) & 1; + patch[0].ML = (dump[0]) & 15; + patch[1].ML = (dump[1]) & 15; + patch[0].KL = (dump[2] >> 6) & 3; + patch[1].KL = (dump[3] >> 6) & 3; + patch[0].TL = (dump[2]) & 63; + patch[1].TL = 0; + patch[0].FB = (dump[3]) & 7; + patch[1].FB = 0; + patch[0].WS = (dump[3] >> 3) & 1; + patch[1].WS = (dump[3] >> 4) & 1; + patch[0].AR = (dump[4] >> 4) & 15; + patch[1].AR = (dump[5] >> 4) & 15; + patch[0].DR = (dump[4]) & 15; + patch[1].DR = (dump[5]) & 15; + patch[0].SL = (dump[6] >> 4) & 15; + patch[1].SL = (dump[7] >> 4) & 15; + patch[0].RR = (dump[6]) & 15; + patch[1].RR = (dump[7]) & 15; +} + +void OPLL_getDefaultPatch(int32_t type, int32_t num, OPLL_PATCH *patch) { + OPLL_dumpToPatch(default_inst[type] + num * 8, patch); +} + +void OPLL_setPatch(OPLL *opll, const uint8_t *dump) { + OPLL_PATCH patch[2]; + int i; + for (i = 0; i < 19; i++) { + OPLL_dumpToPatch(dump + i * 8, patch); + memcpy(&opll->patch[i * 2 + 0], &patch[0], sizeof(OPLL_PATCH)); + memcpy(&opll->patch[i * 2 + 1], &patch[1], sizeof(OPLL_PATCH)); + } +} + +void OPLL_patchToDump(const OPLL_PATCH *patch, uint8_t *dump) { + dump[0] = (uint8_t)((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML); + dump[1] = (uint8_t)((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML); + dump[2] = (uint8_t)((patch[0].KL << 6) + patch[0].TL); + dump[3] = (uint8_t)((patch[1].KL << 6) + (patch[1].WS << 4) + (patch[0].WS << 3) + patch[0].FB); + dump[4] = (uint8_t)((patch[0].AR << 4) + patch[0].DR); + dump[5] = (uint8_t)((patch[1].AR << 4) + patch[1].DR); + dump[6] = (uint8_t)((patch[0].SL << 4) + patch[0].RR); + dump[7] = (uint8_t)((patch[1].SL << 4) + patch[1].RR); +} + +void OPLL_copyPatch(OPLL *opll, int32_t num, OPLL_PATCH *patch) { + memcpy(&opll->patch[num], patch, sizeof(OPLL_PATCH)); +} + +void OPLL_resetPatch(OPLL *opll, uint8_t type) { + int i; + for (i = 0; i < 19 * 2; i++) + OPLL_copyPatch(opll, i, &default_patch[type % OPLL_TONE_NUM][i]); +} + +int16_t OPLL_calc(OPLL *opll) { + while (opll->out_step > opll->out_time) { + opll->out_time += opll->inp_step; + update_output(opll); + mix_output(opll); + } + opll->out_time -= opll->out_step; + if (opll->conv) { + opll->mix_out[0] = OPLL_RateConv_getData(opll->conv, 0); + } + return opll->mix_out[0]; +} + +void OPLL_calcStereo(OPLL *opll, int32_t out[2]) { + while (opll->out_step > opll->out_time) { + opll->out_time += opll->inp_step; + update_output(opll); + mix_output_stereo(opll); + } + opll->out_time -= opll->out_step; + if (opll->conv) { + out[0] = OPLL_RateConv_getData(opll->conv, 0); + out[1] = OPLL_RateConv_getData(opll->conv, 1); + } else { + out[0] = opll->mix_out[0]; + out[1] = opll->mix_out[1]; + } +} + +uint32_t OPLL_setMask(OPLL *opll, uint32_t mask) { + uint32_t ret; + + if (opll) { + ret = opll->mask; + opll->mask = mask; + return ret; + } else + return 0; +} + +uint32_t OPLL_toggleMask(OPLL *opll, uint32_t mask) { + uint32_t ret; + + if (opll) { + ret = opll->mask; + opll->mask ^= mask; + return ret; + } else + return 0; +} diff --git a/src/mappers/sound/emu2413.h b/src/mappers/sound/emu2413.h new file mode 100644 index 000000000..dbc0af1d9 --- /dev/null +++ b/src/mappers/sound/emu2413.h @@ -0,0 +1,237 @@ +#ifndef _EMU2413_H_ +#define _EMU2413_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define OPLL_DEBUG 0 + +enum OPLL_TONE_ENUM { OPLL_2413_TONE = 0, OPLL_VRC7_TONE = 1, OPLL_281B_TONE = 2 }; + +/* voice data */ +typedef struct __OPLL_PATCH { + uint32_t TL, FB, EG, ML, AR, DR, SL, RR, KR, KL, AM, PM, WS; +} OPLL_PATCH; + +/* slot */ +typedef struct __OPLL_SLOT { + uint8_t number; + + /* type flags: + * 000000SM + * |+-- M: 0:modulator 1:carrier + * +--- S: 0:normal 1:single slot mode (sd, tom, hh or cym) + */ + uint8_t type; + + OPLL_PATCH *patch; /* voice parameter */ + + /* slot output */ + int32_t output[2]; /* output value, latest and previous. */ + + /* phase generator (pg) */ + uint16_t *wave_table; /* wave table */ + uint32_t pg_phase; /* pg phase */ + uint32_t pg_out; /* pg output, as index of wave table */ + uint8_t pg_keep; /* if 1, pg_phase is preserved when key-on */ + uint16_t blk_fnum; /* (block << 9) | f-number */ + uint16_t fnum; /* f-number (9 bits) */ + uint8_t blk; /* block (3 bits) */ + + /* envelope generator (eg) */ + uint8_t eg_state; /* current state */ + int32_t volume; /* current volume */ + uint8_t key_flag; /* key-on flag 1:on 0:off */ + uint8_t sus_flag; /* key-sus option 1:on 0:off */ + uint16_t tll; /* total level + key scale level*/ + uint8_t rks; /* key scale offset (rks) for eg speed */ + uint8_t eg_rate_h; /* eg speed rate high 4bits */ + uint8_t eg_rate_l; /* eg speed rate low 2bits */ + uint32_t eg_shift; /* shift for eg global counter, controls envelope speed */ + uint32_t eg_out; /* eg output */ + + uint32_t update_requests; /* flags to debounce update */ + +#if OPLL_DEBUG + uint8_t last_eg_state; +#endif +} OPLL_SLOT; + +/* mask */ +#define OPLL_MASK_CH(x) (1 << (x)) +#define OPLL_MASK_HH (1 << (9)) +#define OPLL_MASK_CYM (1 << (10)) +#define OPLL_MASK_TOM (1 << (11)) +#define OPLL_MASK_SD (1 << (12)) +#define OPLL_MASK_BD (1 << (13)) +#define OPLL_MASK_RHYTHM (OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD) + +/* rate conveter */ +typedef struct __OPLL_RateConv { + int ch; + double timer; + double f_ratio; + int16_t *sinc_table; + int16_t **buf; +} OPLL_RateConv; + +OPLL_RateConv *OPLL_RateConv_new(double f_inp, double f_out, int ch); +void OPLL_RateConv_reset(OPLL_RateConv *conv); +void OPLL_RateConv_putData(OPLL_RateConv *conv, int ch, int16_t data); +int16_t OPLL_RateConv_getData(OPLL_RateConv *conv, int ch); +void OPLL_RateConv_delete(OPLL_RateConv *conv); + +typedef struct __OPLL { + uint32_t clk; + uint32_t rate; + + uint8_t chip_type; + + uint32_t adr; + + double inp_step; + double out_step; + double out_time; + + uint8_t reg[0x40]; + uint8_t test_flag; + uint32_t slot_key_status; + uint8_t rhythm_mode; + + uint32_t eg_counter; + + uint32_t pm_phase; + int32_t am_phase; + + uint8_t lfo_am; + + uint32_t noise; + uint8_t short_noise; + + int32_t patch_number[9]; + OPLL_SLOT slot[18]; + OPLL_PATCH patch[19 * 2]; + + uint8_t pan[16]; + float pan_fine[16][2]; + + uint32_t mask; + + /* channel output */ + /* 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym */ + int16_t ch_out[14]; + + int16_t mix_out[2]; + + OPLL_RateConv *conv; +} OPLL; + +OPLL *OPLL_new(uint32_t clk, uint32_t rate); +void OPLL_delete(OPLL *); + +void OPLL_reset(OPLL *); +void OPLL_resetPatch(OPLL *, uint8_t); + +/** + * Set output wave sampling rate. + * @param rate sampling rate. If clock / 72 (typically 49716 or 49715 at 3.58MHz) is set, the internal rate converter is + * disabled. + */ +void OPLL_setRate(OPLL *opll, uint32_t rate); + +/** + * Set internal calcuration quality. Currently no effects, just for compatibility. + * >= v1.0.0 always synthesizes internal output at clock/72 Hz. + */ +void OPLL_setQuality(OPLL *opll, uint8_t q); + +/** + * Set pan pot (extra function - not YM2413 chip feature) + * @param ch 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym 14,15:reserved + * @param pan 0:mute 1:right 2:left 3:center + * ``` + * pan: 76543210 + * |+- bit 1: enable Left output + * +-- bit 0: enable Right output + * ``` + */ +void OPLL_setPan(OPLL *opll, uint32_t ch, uint8_t pan); + +/** + * Set fine-grained panning + * @param ch 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym 14,15:reserved + * @param pan output strength of left/right channel. + * pan[0]: left, pan[1]: right. pan[0]=pan[1]=1.0f for center. + */ +void OPLL_setPanFine(OPLL *opll, uint32_t ch, float pan[2]); + +/** + * Set chip type. If vrc7 is selected, r#14 is ignored. + * This method not change the current ROM patch set. + * To change ROM patch set, use OPLL_resetPatch. + * @param type 0:YM2413 1:VRC7 + */ +void OPLL_setChipType(OPLL *opll, uint8_t type); + +void OPLL_writeIO(OPLL *opll, uint32_t reg, uint8_t val); +void OPLL_writeReg(OPLL *opll, uint32_t reg, uint8_t val); + +/** + * Calculate one sample + */ +int16_t OPLL_calc(OPLL *opll); + +/** + * Calulate stereo sample + */ +void OPLL_calcStereo(OPLL *opll, int32_t out[2]); + +void OPLL_setPatch(OPLL *, const uint8_t *dump); +void OPLL_copyPatch(OPLL *, int32_t, OPLL_PATCH *); + +/** + * Force to refresh. + * External program should call this function after updating patch parameters. + */ +void OPLL_forceRefresh(OPLL *); + +void OPLL_dumpToPatch(const uint8_t *dump, OPLL_PATCH *patch); +void OPLL_patchToDump(const OPLL_PATCH *patch, uint8_t *dump); +void OPLL_getDefaultPatch(int32_t type, int32_t num, OPLL_PATCH *); + +/** + * Set channel mask + * @param mask mask flag: OPLL_MASK_* can be used. + * - bit 0..8: mask for ch 1 to 9 (OPLL_MASK_CH(i)) + * - bit 9: mask for Hi-Hat (OPLL_MASK_HH) + * - bit 10: mask for Top-Cym (OPLL_MASK_CYM) + * - bit 11: mask for Tom (OPLL_MASK_TOM) + * - bit 12: mask for Snare Drum (OPLL_MASK_SD) + * - bit 13: mask for Bass Drum (OPLL_MASK_BD) + */ +uint32_t OPLL_setMask(OPLL *, uint32_t mask); + +/** + * Toggler channel mask flag + */ +uint32_t OPLL_toggleMask(OPLL *, uint32_t mask); + +/* for compatibility */ +#define OPLL_set_rate OPLL_setRate +#define OPLL_set_quality OPLL_setQuality +#define OPLL_set_pan OPLL_setPan +#define OPLL_set_pan_fine OPLL_setPanFine +#define OPLL_calc_stereo OPLL_calcStereo +#define OPLL_reset_patch OPLL_resetPatch +#define OPLL_dump2patch OPLL_dumpToPatch +#define OPLL_patch2dump OPLL_patchToDump +#define OPLL_setChipMode OPLL_setChipType + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/mappers/sound/fdssound.c b/src/mappers/sound/fdssound.c new file mode 100644 index 000000000..28bd3c8d6 --- /dev/null +++ b/src/mappers/sound/fdssound.c @@ -0,0 +1,417 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* FDSSound rewrite based on MDFN NES fds sound implementation, modifed for fceumm's use. */ +/* WIP as some crackling sounds can be annoyingly heard and other issues. */ + +#include "mapinc.h" +#include "fdssound.h" + +static void RenderSoundHQ(void); +static void RenderSound(void); + +static const int32 mod_bias_tab[8] = { 0, 1, 2, 4, 0, -4, -2, -1 }; + +static FDSSOUND fdso = { 0 }; +static int32 FBC = 0; + +void FDSSound_AddStateInfo(void) { + AddExState(&fdso.EnvUnits[EVOL].speed, 1, 0, "SPD0"); + AddExState(&fdso.EnvUnits[EVOL].control, 1, 0, "CTL0"); + AddExState(&fdso.EnvUnits[EVOL].volume, 1, 0, "VOL0"); + AddExState(&fdso.EnvUnits[EVOL].counter, 1, 0, "CNT0"); + + AddExState(&fdso.EnvUnits[EMOD].speed, 1, 0, "SPD1"); + AddExState(&fdso.EnvUnits[EMOD].control, 1, 0, "CTL1"); + AddExState(&fdso.EnvUnits[EMOD].volume, 1, 0, "VOL1"); + AddExState(&fdso.EnvUnits[EMOD].counter, 1, 0, "CNT1"); + + AddExState(fdso.cwave, 64, 0, "WAVE"); + AddExState(fdso.mwave, 32, 0, "MWAV"); + + AddExState(&fdso.cwave_freq, 2, 0, "WFRQ"); + AddExState(&fdso.cwave_pos, 4, 0, "WPOS"); + AddExState(&fdso.cwave_control, 1, 0, "WCTL"); + + AddExState(&fdso.mod_freq, 2, 0, "MFRQ"); + AddExState(&fdso.mod_pos, 4, 0, "MPOS"); + AddExState(&fdso.mod_control, 1, 0, "MCTL"); + + AddExState(&fdso.sweep_bias, 4, 0, "SWBS"); + + AddExState(&fdso.master_control, 1, 0, "MCTL"); + AddExState(&fdso.master_env_speed, 1, 0, "MSPD"); + + AddExState(&fdso.envcount, 2, 0, "EDIV"); +} + +static void FDSSoundUpdate(void) { + if (FSettings.SndRate) { + if (FSettings.soundq >= 1) { + RenderSoundHQ(); + } else { + RenderSound(); + } + } +} + +DECLFR(FDSWaveRead) { + if (fdso.master_control & WAVE_WRITE_MODE) { + return (FDS_OPENBUS | fdso.cwave[A & 0x3F]); + } + return (FDS_OPENBUS | fdso.cwave[(fdso.cwave_pos >> 21) & 0x3F]); +} + +DECLFW(FDSWaveWrite) { + if (fdso.master_control & WAVE_WRITE_MODE) { + fdso.cwave[A & 0x3f] = V & 0x3F; + } +} + +DECLFW(FDSSReg0Write) { + FDSSoundUpdate(); + + fdso.EnvUnits[EVOL].speed = V & 0x3F; + fdso.EnvUnits[EVOL].control = V & 0xC0; + + fdso.EnvUnits[EVOL].counter = fdso.EnvUnits[EVOL].speed + 1; + + if (fdso.EnvUnits[EVOL].control & ENV_CTRL_DISABLE) { + fdso.EnvUnits[EVOL].volume = fdso.EnvUnits[EVOL].speed; + } +} + +DECLFW(FDSSReg1Write) { + FDSSoundUpdate(); + + fdso.cwave_freq &= 0x0F00; + fdso.cwave_freq |= V; +} + +DECLFW(FDSSReg2Write) { + FDSSoundUpdate(); + + fdso.cwave_freq &= 0x00FF; + fdso.cwave_freq |= (V & 0x0F) << 8; + + fdso.cwave_control = V & 0xC0; + + if ((fdso.cwave_control & WAVE_DISABLE)) { + fdso.cwave_pos = 0; + } +} + +DECLFW(FDSSReg3Write) { + FDSSoundUpdate(); + + fdso.EnvUnits[EMOD].speed = V & 0x3F; + fdso.EnvUnits[EMOD].control = V & 0xC0; + + fdso.EnvUnits[EMOD].counter = fdso.EnvUnits[EMOD].speed + 1; + + if (fdso.EnvUnits[EMOD].control & ENV_CTRL_DISABLE) { + fdso.EnvUnits[EMOD].volume = fdso.EnvUnits[EMOD].speed; + } +} + +DECLFW(FDSSReg4Write) { + FDSSoundUpdate(); + + fdso.sweep_bias = (V & 0x7F) << 4; + fdso.mod_pos = 0; +} + +DECLFW(FDSSReg5Write) { + FDSSoundUpdate(); + + fdso.mod_freq &= 0x0F00; + fdso.mod_freq |= V; +} + +DECLFW(FDSSReg6Write) { + FDSSoundUpdate(); + + fdso.mod_freq &= 0x00FF; + fdso.mod_freq |= (V & 0x0F) << 8; + + fdso.mod_control = V & 0xC0; + + if (fdso.mod_control & MOD_WRITE_MODE) { + fdso.mod_pos = 0; + } +} + +DECLFW(FDSSReg7Write) { + FDSSoundUpdate(); + + if (fdso.mod_control & MOD_WRITE_MODE) { + int i; + for (i = 0; i < 31; i++) { + fdso.mwave[i] = fdso.mwave[i + 1]; + } + fdso.mwave[0x1F] = mod_bias_tab[V & 0x07]; + if ((V & 0x07) == 0x04) { + fdso.mwave[0x1F] = 0x10; + } + } +} + +DECLFW(FDSSReg8Write) { + FDSSoundUpdate(); + + fdso.master_control = V; +} + +DECLFW(FDSSReg9Write) { + FDSSoundUpdate(); + + fdso.master_env_speed = V; +} + +DECLFR(FDSEnvVolumeRead) { + FDSSoundUpdate(); + return (FDS_OPENBUS | fdso.EnvUnits[EVOL].volume); +} + +DECLFR(FDSEnvModRead) { + FDSSoundUpdate(); + return (FDS_OPENBUS | fdso.EnvUnits[EMOD].volume); +} + +#define sign_x_to_s32(n, v) ((int32)((uint32)(v) << (32 - (n))) >> (32 - (n))) + +static INLINE int32 FDSDoSound(void) { + uint32 prev_cwave_pos = fdso.cwave_pos; + static int32 temp; + + fdso.count += fdso.cycles; + if (fdso.count >= ((int64)1 << 40)) { +dogk: + fdso.count -= (int64)1 << 40; + + if (!(fdso.cwave_control & ENVELOPES_DISABLE) && fdso.master_env_speed) { + if (fdso.envcount) { + fdso.envcount--; + } else { + fdso.envcount = fdso.master_env_speed * 3; + if (!(fdso.EnvUnits[EVOL].control & ENV_CTRL_DISABLE)) { + if (fdso.EnvUnits[EVOL].counter) { + fdso.EnvUnits[EVOL].counter--; + } else { + fdso.EnvUnits[EVOL].counter = fdso.EnvUnits[EVOL].speed + 1; + if ((fdso.EnvUnits[EVOL].control & ENV_CTRL_INCREASE)) { + if (fdso.EnvUnits[EVOL].volume < 0x20) { + fdso.EnvUnits[EVOL].volume++; + } + } else { + if (fdso.EnvUnits[EVOL].volume > 0) { + fdso.EnvUnits[EVOL].volume--; + } + } + } + } + + if (!(fdso.EnvUnits[EMOD].control & ENV_CTRL_DISABLE)) { + if (fdso.EnvUnits[EMOD].counter) { + fdso.EnvUnits[EMOD].counter--; + } else { + fdso.EnvUnits[EMOD].counter = fdso.EnvUnits[EMOD].speed + 1; + if ((fdso.EnvUnits[EMOD].control & ENV_CTRL_INCREASE)) { + if (fdso.EnvUnits[EMOD].volume < 0x20) { + fdso.EnvUnits[EMOD].volume++; + } + } else { + if (fdso.EnvUnits[EMOD].volume > 0) { + fdso.EnvUnits[EMOD].volume--; + } + } + } + } + } + } + + if (!(fdso.mod_control & MOD_WRITE_MODE)) { + uint32 prev_mod_pos = fdso.mod_pos; + + fdso.mod_pos += fdso.mod_freq; + if ((fdso.mod_pos & (0x3F << 11)) != + (prev_mod_pos & (0x3F << 11))) { + const int32 mw = fdso.mwave[((fdso.mod_pos >> 16) & 0x1F)]; + + fdso.sweep_bias = (fdso.sweep_bias + mw) & 0x7FF; + if (mw == 0x10) { + fdso.sweep_bias = 0; + } + } + + temp = sign_x_to_s32(11, fdso.sweep_bias) * + ((fdso.EnvUnits[EMOD].volume > 0x20) ? 0x20 : fdso.EnvUnits[EMOD].volume); + + if (temp & 0x0F0) { + temp /= 256; + if (fdso.sweep_bias & 0x400) { + temp--; + } else { + temp += 2; + } + } else { + temp /= 256; + } + + if (temp >= 192) { + temp -= 256; + } + if (temp < -64) { + temp += 256; + } + } + + if (!(fdso.cwave_control & WAVE_DISABLE)) { + int32 cur_cwave_freq = (int32)(fdso.cwave_freq << 6); + + if (!(fdso.mod_control & MOD_WRITE_MODE)) { + cur_cwave_freq += (int32)fdso.cwave_freq * temp; + if (cur_cwave_freq < 0) { + cur_cwave_freq = 0; + } + } + fdso.cwave_pos = (fdso.cwave_pos + cur_cwave_freq) & 0x7FFFFFF; + } + } + if (fdso.count >= 32768) { + goto dogk; + } + + /* Might need to emulate applying the amplitude to the waveform a bit better... */ + { + int k = fdso.EnvUnits[EVOL].volume; + if (k > 0x20) { + k = 0x20; + } + return (fdso.cwave[fdso.cwave_pos >> 21] * FSettings.ExpSoundVolume[SND_FDS] * k * 4 / ((fdso.master_control & MASTER_VOLUME) + 2)) >> 8; + } +} + +static void RenderSound(void) { + int32 end, start; + int32 x; + + start = FBC; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) { + return; + } + FBC = end; + + if (!(fdso.master_control & WAVE_WRITE_MODE)) { + for (x = start; x < end; x++) { + uint32 t = FDSDoSound(); + t += t >> 1; + t >>= 4; + Wave[x >> 4] += t; /* (t>>2)-(t>>3); */ /* >>3; */ + } + } +} + +static void RenderSoundHQ(void) { + uint32 x; + + if (!(fdso.master_control & WAVE_WRITE_MODE)) { + for (x = FBC; x < SOUNDTS; x++) { + uint32 t = FDSDoSound(); + t += t >> 1; + WaveHi[x] += t; /* (t<<2)-(t<<1); */ + } + } + FBC = SOUNDTS; +} + +static void HQSync(int32 ts) { + FBC = ts; +} + +static void FDSSound(int c) { + RenderSound(); + FBC = c; +} + +void FDSSound_SC(void) { + GameExpSound.HiSync = HQSync; + GameExpSound.HiFill = RenderSoundHQ; + GameExpSound.Fill = FDSSound; + GameExpSound.RChange = FDSSound_SC; + + if (FSettings.SndRate) { + if (FSettings.soundq >= 1) { + fdso.cycles = (int64)1 << 39; + } else { + fdso.cycles = ((int64)1 << 40) * FDSClock; + fdso.cycles /= FSettings.SndRate * 16; + } + } +} + +void FDSSoundRegReset(void) { + memset(&fdso, 0, sizeof(fdso)); + + /* https://github.com/bbbradsmith/nsfplay/blob/f563b9fe32df9ef0a94944026642d8ce5144c000/xgm/devices/Sound/nes_fds.cpp#L109 */ + + /* NOTE: the FDS BIOS reset only does the following related to audio: */ + /* $4023 = $00 + * $4023 = $83 enables master_io + * $4080 = $80 output volume = 0, envelope disabled + * $408A = $E8 master envelope speed + * $4023 = $00 + * $4023 = $83 */ + FDSSReg0Write(0x4080, 0x80); + FDSSReg9Write(0x408A, 0xE8); + + /* reset other stuff */ + FDSSReg1Write(0x4082, 0x00); /* wav freq 0 */ + FDSSReg2Write(0x4083, 0x80); /* wav disable */ + FDSSReg3Write(0x4084, 0x80); /* mod strength 0 */ + FDSSReg4Write(0x4085, 0x00); /* mod position 0 */ + FDSSReg5Write(0x4086, 0x00); /* mod freq 0 */ + FDSSReg6Write(0x4087, 0x80); /* mod disable */ + FDSSReg8Write(0x4089, 0x00); /* wav write disable, max global volume} */ +} + +/* callback for bootleg mappers */ + +void FDSSound_Power(void) { + FDSSoundRegReset(); + FDSSound_SC(); + + SetReadHandler(0x4040, 0x407F, FDSWaveRead); + SetReadHandler(0x4090, 0x4090, FDSEnvVolumeRead); + SetReadHandler(0x4092, 0x4092, FDSEnvModRead); + + SetWriteHandler(0x4040, 0x407F, FDSWaveWrite); + SetWriteHandler(0x4080, 0x4080, FDSSReg0Write); + SetWriteHandler(0x4082, 0x4082, FDSSReg1Write); + SetWriteHandler(0x4083, 0x4083, FDSSReg2Write); + SetWriteHandler(0x4084, 0x4084, FDSSReg3Write); + SetWriteHandler(0x4085, 0x4085, FDSSReg4Write); + SetWriteHandler(0x4086, 0x4086, FDSSReg5Write); + SetWriteHandler(0x4087, 0x4087, FDSSReg6Write); + SetWriteHandler(0x4088, 0x4088, FDSSReg7Write); + SetWriteHandler(0x4089, 0x4089, FDSSReg8Write); + SetWriteHandler(0x408A, 0x408A, FDSSReg9Write); +} diff --git a/src/mappers/sound/fdssound.h b/src/mappers/sound/fdssound.h new file mode 100644 index 000000000..8f6f266a9 --- /dev/null +++ b/src/mappers/sound/fdssound.h @@ -0,0 +1,96 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FDS_APU_H +#define _FDS_APU_H + +#define FDSClock (NTSC_CLOCK_SPEED / 2) + +enum { FDS_OPENBUS = 0x40 }; +enum { EVOL = 0, EMOD }; +enum { + ENV_CTRL_INCREASE = 0x40, + ENV_CTRL_DISABLE = 0x80, + ENVELOPES_DISABLE = 0x40, + WAVE_DISABLE = 0x80, + MOD_WRITE_MODE = 0x80, + MASTER_VOLUME = 0x03, + WAVE_WRITE_MODE = 0x80 +}; + +typedef struct __FDSENVUNIT { + uint8 speed; + uint8 volume; /* Current volumes. */ + uint8 control; /* $4080/$4084 with low 6bits masked */ + uint8 counter; /**/ +} FDSENVUNIT; + +typedef struct __FDSSOUND { + int64 cycles; /* fds cycles to run */ + int64 count; /* current cycle count */ + + FDSENVUNIT EnvUnits[2]; + + uint16 envcount; /* Main envelope clock divider. */ + + uint16 cwave_freq; /* $4082 and lower 4 bits of $4083 */ + uint32 cwave_pos; /* main phase */ + uint8 cwave_control; /* $4083 with low 6bits masked */ + + uint16 mod_freq; /* $4086 and lower 4 bits of $4087 */ + uint32 mod_pos; /* Should be named "mwave_pos", but "mod_pos" distinguishes it more. */ + uint8 mod_control; /* $4087 bit7 */ + + uint8 master_control; /* $4089 with lower 6 bits masked */ + uint8 master_env_speed; /* Master envelope speed controller($408A). */ + + int32 mwave[0x20]; /* Modulation waveform. Stored in expanded(after LUT) */ + /* form. Set to 0x10 if the original value is */ + /* 0x4(reset sweep bias accumulator). */ + uint8 cwave[0x40]; /* Game-defined waveform(carrier) */ + uint32 sweep_bias; +} FDSSOUND; + +DECLFR(FDSWaveRead); +DECLFW(FDSWaveWrite); +DECLFW(FDSSReg0Write); +DECLFW(FDSSReg1Write); +DECLFW(FDSSReg2Write); +DECLFW(FDSSReg3Write); +DECLFW(FDSSReg4Write); +DECLFW(FDSSReg5Write); +DECLFW(FDSSReg6Write); +DECLFW(FDSSReg7Write); +DECLFW(FDSSReg8Write); +DECLFW(FDSSReg9Write); +DECLFR(FDSEnvVolumeRead); +DECLFR(FDSEnvModRead); + +void FDSSound_SC(void); +void FDSSound_Reset(void); +void FDSSoundRegReset(void); +void FDSSound_AddStateInfo(void); + +/* For mappers utilizing FDS expansion audio */ +void FDSSound_Power(void); +DECLFR(FDSSound_Read); /* $4040-$4092 */ +DECLFW(FDSSound_Write); /* $4040-$408A */ + +#endif /* _FDS_APU_H */ diff --git a/src/mappers/sound/mmc5sound.c b/src/mappers/sound/mmc5sound.c new file mode 100644 index 000000000..90e8162f7 --- /dev/null +++ b/src/mappers/sound/mmc5sound.c @@ -0,0 +1,301 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc5sound.h" + +typedef struct __MMC5SQUARE { + /* regs */ + uint8 volume; + uint8 duty; + uint8 enabled; + int16 freq; + + /* timers */ + uint8 dcount; + int32 vcount; + int32 cvbc; +} MMC5SQUARE; + +typedef struct __MMC5PCM { + uint8 rawdata; + uint8 control; + int32 cvbc; +} MMC5PCM; + +typedef struct __MMC5SOUND { + MMC5SQUARE square[2]; + MMC5PCM pcm; +} MMC5SOUND; + +static MMC5SOUND MMC5Sound; + +static void (*sfun)(MMC5SQUARE *channel); +static void (*psfun)(void); + +static void Do5PCM(void) { + int32 V; + int32 start, end; + + start = MMC5Sound.pcm.cvbc; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) { + return; + } + MMC5Sound.pcm.cvbc = end; + + if (!(MMC5Sound.pcm.control & 0x40) && MMC5Sound.pcm.rawdata) { + int32 amp = GetOutput(SND_MMC5, MMC5Sound.pcm.rawdata << 1); + + for (V = start; V < end; V++) { + Wave[V >> 4] += amp; + } + } +} + +static void Do5PCMHQ(void) { + int32 V; + + if (!(MMC5Sound.pcm.control & 0x40) && MMC5Sound.pcm.rawdata) { + int32 amp = GetOutput(SND_MMC5, MMC5Sound.pcm.rawdata << 5); + + for (V = MMC5Sound.pcm.cvbc; V < SOUNDTS; V++) { + WaveHi[V] += amp; + } + } + MMC5Sound.pcm.cvbc = SOUNDTS; +} + +static void Do5SQ(MMC5SQUARE *channel) { + static int tal[4] = { 1, 2, 4, 6 }; + int32 V, amp, duty, freq; + int32 start, end; + + start = channel->cvbc; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) { + return; + } + channel->cvbc = end; + + freq = channel->freq + 1; + amp = GetOutput(SND_MMC5, channel->volume << 4); + duty = tal[channel->duty]; + + if ((freq >= 8) && channel->enabled) { + int32 dc, vc; + + freq <<= 18; + dc = channel->dcount; + vc = channel->vcount; + + for (V = start; V < end; V++) { + if (dc < duty) { + Wave[V >> 4] += amp; + } + vc -= nesincsize; + while (vc <= 0) { + vc += freq; + dc = (dc + 1) & 0x07; + } + } + channel->dcount = dc; + channel->vcount = vc; + } +} + +static void Do5SQHQ(MMC5SQUARE *channel) { + static int tal[4] = { 1, 2, 4, 6 }; + int V, amp, duty, freq; + + freq = channel->freq + 1; + amp = GetOutput(SND_MMC5, channel->volume << 8); + duty = tal[channel->duty]; + + if ((freq >= 8) && channel->enabled) { + int dc, vc; + + freq <<= 1; + + dc = channel->dcount; + vc = channel->vcount; + + for (V = channel->cvbc; V < SOUNDTS; V++) { + if (dc < duty) { + WaveHi[V] += amp; + } + vc--; + if (vc <= 0) { /* Less than zero when first started. */ + vc = freq; + dc = (dc + 1) & 0x07; + } + } + channel->dcount = dc; + channel->vcount = vc; + } + channel->cvbc = SOUNDTS; +} + +static void MMC5RunSoundHQ(void) { + Do5SQHQ(&MMC5Sound.square[0]); + Do5SQHQ(&MMC5Sound.square[1]); + Do5PCMHQ(); +} + +static void MMC5HiSync(int32 ts) { + MMC5Sound.square[0].cvbc = ts; + MMC5Sound.square[1].cvbc = ts; + MMC5Sound.pcm.cvbc = ts; +} + +static void MMC5RunSound(int Count) { + Do5SQ(&MMC5Sound.square[0]); + Do5SQ(&MMC5Sound.square[1]); + Do5PCM(); + MMC5Sound.square[0].cvbc = Count; + MMC5Sound.square[1].cvbc = Count; + MMC5Sound.pcm.cvbc = Count; +} + +static void MMC5Square_Write(MMC5SQUARE *channel, uint8 reg, uint8 V) { + switch (reg) { + case 0: + channel->volume = V & 0x0F; + channel->duty = (V & 0xC0) >> 6; + break; + + case 1: + break; + + case 2: + channel->freq = (channel->freq & ~0x00FF) | V; + break; + + case 3: + channel->freq = (channel->freq & ~0x0700) | ((V & 0x07) << 8); + break; + + case 4: + channel->enabled = (V != 0); + break; + } +} + +DECLFW(MMC5Sound_Write) { + GameExpSound.Fill = MMC5RunSound; + GameExpSound.HiFill = MMC5RunSoundHQ; + + switch (A) { + case 0x5010: + if (psfun) { + psfun(); + } + MMC5Sound.pcm.control = V; + break; + + case 0x5011: + if (psfun) { + psfun(); + } + MMC5Sound.pcm.rawdata = V; + break; + + case 0x5000: + case 0x5001: + case 0x5002: + case 0x5003: + if (sfun) { + sfun(&MMC5Sound.square[0]); + } + MMC5Square_Write(&MMC5Sound.square[0], A & 0x03, V); + break; + + case 0x5004: + case 0x5005: + case 0x5006: + case 0x5007: + if (sfun) { + sfun(&MMC5Sound.square[1]); + } + MMC5Square_Write(&MMC5Sound.square[1], A & 0x03, V); + break; + + case 0x5015: + if (sfun) { + sfun(&MMC5Sound.square[0]); + sfun(&MMC5Sound.square[1]); + } + MMC5Square_Write(&MMC5Sound.square[0], 4, V & 0x01); + MMC5Square_Write(&MMC5Sound.square[1], 4, V & 0x02); + break; + } +} + +static void MMC5SC(void) { + GameExpSound.HiSync = MMC5HiSync; + + MMC5Sound.square[0].vcount = 0; + MMC5Sound.square[1].vcount = 0; + + MMC5Sound.square[0].cvbc = 0; + MMC5Sound.square[1].cvbc = 0; + MMC5Sound.pcm.cvbc = 0; + + if (FSettings.SndRate) { + if (FSettings.soundq >= 1) { + sfun = Do5SQHQ; + psfun = Do5PCMHQ; + } else { + sfun = Do5SQ; + psfun = Do5PCM; + } + } else { + sfun = 0; + psfun = 0; + } +} + +void MMC5Sound_ESI(void) { + memset(&MMC5Sound, 0, sizeof(MMC5Sound)); + GameExpSound.RChange = MMC5SC; + MMC5SC(); +} + +void MMC5Sound_AddStateInfo(void) { + AddExState(&MMC5Sound.square[0].enabled, 1, 0, "S0EN"); + AddExState(&MMC5Sound.square[0].volume, 1, 0, "S0VL"); + AddExState(&MMC5Sound.square[0].freq, 2, 0, "S0FQ"); + AddExState(&MMC5Sound.square[0].duty, 1, 0, "S0DT"); + AddExState(&MMC5Sound.square[0].dcount, 1, 0, "S0DC"); + AddExState(&MMC5Sound.square[0].vcount, 4, 0, "S0VC"); + AddExState(&MMC5Sound.square[0].cvbc, 4, 0, "S0BC"); + + AddExState(&MMC5Sound.square[1].enabled, 1, 0, "S1EN"); + AddExState(&MMC5Sound.square[1].volume, 1, 0, "S1VL"); + AddExState(&MMC5Sound.square[1].freq, 2, 0, "S1FQ"); + AddExState(&MMC5Sound.square[1].duty, 1, 0, "S1DT"); + AddExState(&MMC5Sound.square[1].dcount, 1, 0, "S1DC"); + AddExState(&MMC5Sound.square[1].vcount, 4, 0, "S1VC"); + AddExState(&MMC5Sound.square[1].cvbc, 4, 0, "S1BC"); + + AddExState(&MMC5Sound.pcm.control, 1, 0, "PCTL"); + AddExState(&MMC5Sound.pcm.rawdata, 1, 0, "PRAW"); + AddExState(&MMC5Sound.pcm.cvbc, 4, 0, "PCVB"); +} diff --git a/src/mappers/sound/mmc5sound.h b/src/mappers/sound/mmc5sound.h new file mode 100644 index 000000000..d0ec715b6 --- /dev/null +++ b/src/mappers/sound/mmc5sound.h @@ -0,0 +1,28 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _MMC5_AUDIO_H +#define _MMC5_AUDIO_H + +void MMC5Sound_ESI(void); +DECLFW(MMC5Sound_Write); +void MMC5Sound_AddStateInfo(void); + +#endif /* _MMC5_AUDIO_H */ diff --git a/src/mappers/sound/n163sound.c b/src/mappers/sound/n163sound.c new file mode 100644 index 000000000..62aa8e0c4 --- /dev/null +++ b/src/mappers/sound/n163sound.c @@ -0,0 +1,326 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* TODO: Things to do: + 1 Read freq low + 2 Read freq mid + 3 Read freq high + 4 Read volume + ...? +*/ + +#include "mapinc.h" +#include "n163sound.h" + +enum SoundReg { + FREQ_L = 0x00, + PHASE_L = 0x01, + FREQ_M = 0x02, + PHASE_M = 0x03, + FREQ_H = 0x04, + WAVELEN = 0x04, + PHASE_H = 0x05, + WAVEADDR = 0x06, + VOLUME = 0x07 +}; + +typedef struct N163Channel { + uint32 PlayIndex; /* should be phase? */ + int32 vcount; + int16 output; +} N163Channel; + +static N163Channel N163Snd[8]; +static uint8 IRAM[128]; +static uint8 ramPos; +static uint8 autoInc; +static int32 CVBC; + +#define VOLADJ (576716) +#define TOINDEX (16 + 1) + +static uint32 GetFrequency(int P) { + uint8 base = 0x40 + P * 0x08; + return ((IRAM[base + FREQ_H] & 0x03) << 16) | + (IRAM[base + FREQ_M] << 8) | + IRAM[base + FREQ_L]; +} + +static uint32 GetPhase(int P) { + uint8 base = 0x40 + P * 0x08; + return (IRAM[base + PHASE_H] << 16) | + (IRAM[base + PHASE_M] << 8) | + IRAM[base + PHASE_L]; +} + +static void SetPhase(int P, uint32 phase) { + uint8 base = 0x40 + P * 0x08; + IRAM[base + PHASE_H] = (phase >> 16) & 0xFF; + IRAM[base + PHASE_M] = (phase >> 8) & 0xFF; + IRAM[base + PHASE_L] = phase & 0xFF; +} + +static uint8 GetWaveAddress(int P) { + uint8 base = 0x40 + P * 0x08; + return IRAM[base + WAVEADDR]; +} + +static uint8 GetWaveLength(int P) { + uint8 base = 0x40 + P * 0x08; + return 256 - (IRAM[base + WAVELEN] & 0xFC); +} + +static uint32 GetVolume(int P) { + uint8 base = 0x40 + P * 0x08; + return (IRAM[base + VOLUME] & 0x0F) * VOLADJ; +} + +static uint8 GetNumberOfChannels() { + return (IRAM[0x7F] >> 4) & 0x07; +} + +static int16 GetSample(uint8 pos, int volume, int outshift) { + int8 sample; + if (pos & 0x01) { + sample = IRAM[pos >> 1] >> 4; + } else { + sample = IRAM[pos >> 1] & 0x0F; + } + return ((sample * volume) >> outshift); +} + +/* 16:15 */ +static void SyncHQ(int32 ts) { + CVBC = ts; +} + +static void DoN163SoundHQ(void) { + int32 cyclesuck = (GetNumberOfChannels() + 1) * 15; + int32 P, V; + + for (P = 7; P >= (7 - GetNumberOfChannels()); P--) { + N163Channel *channel = &N163Snd[P]; + int channelOffset = 0x40 + (P * 8); + + if ((IRAM[FREQ_H + channelOffset] & 0xE0) && (IRAM[VOLUME + channelOffset] & 0xF)) { + int32 vco = channel->vcount; + + uint32 phase = GetPhase(P); + uint32 freq = GetFrequency(P); + uint16 length = GetWaveLength(P); + uint8 offset = GetWaveAddress(P); + uint32 volume = GetVolume(P); + + for (V = CVBC << 1; V < (int)SOUNDTS << 1; V++) { + if (vco == 0) { + vco = cyclesuck; + channel->PlayIndex += freq; + while ((channel->PlayIndex >> TOINDEX) >= length) { + channel->PlayIndex -= length << TOINDEX; + } + channel->output = GetSample((channel->PlayIndex >> TOINDEX) + offset, volume, 16); + } + vco--; + WaveHi[V >> 1] += GetOutput(SND_N163, channel->output); + } + channel->vcount = vco; + } + } + CVBC = SOUNDTS; +} + +static void DoN163Sound(int32 *Wave, int Count) { + int P, V; + + for (P = 7; P >= (7 - GetNumberOfChannels()); P--) { + N163Channel *channel = &N163Snd[P]; + int channelOffset = 0x40 + (P * 8); + + if ((IRAM[FREQ_H + channelOffset] & 0xE0) && (IRAM[VOLUME + channelOffset] & 0xF)) { + int32 vco = channel->vcount; + + uint32 phase = GetPhase(P); + uint32 freq = GetFrequency(P); + uint16 length = GetWaveLength(P); + uint8 offset = GetWaveAddress(P); + uint32 volume = GetVolume(P); + + int32 inc; + + if (!freq) { + continue; + } + + inc = (long double)((int64)FSettings.SndRate << 15) / + ((long double)freq * 21477272 / + ((long double)0x400000 * (GetNumberOfChannels() + 1) * 45)); + + for (V = 0; V < Count * 16; V++) { + if (vco >= inc) { + vco -= inc; + channel->PlayIndex++; + if (channel->PlayIndex >= length) { + channel->PlayIndex = 0; + } + channel->output = GetSample( + channel->PlayIndex + offset, + volume, 19); + } + vco += 0x8000; + Wave[V >> 4] += GetOutput(SND_N163, channel->output); + } + channel->vcount = vco; + } + } +} + +static int dwave = 0; + +static void N163Sound(int Count) { + int32 z, a; + + z = ((SOUNDTS << 16) / soundtsinc) >> 4; + a = z - dwave; + + if (a) { + DoN163Sound(&Wave[dwave], a); + } + + dwave = 0; +} + +static void N163SoundHack(void) { + int32 z, a; + + if (FSettings.soundq >= 1) { + DoN163SoundHQ(); + return; + } + + z = ((SOUNDTS << 16) / soundtsinc) >> 4; + a = z - dwave; + + if (a) { + DoN163Sound(&Wave[dwave], a); + } + + dwave += a; +} + +DECLFR(N163Sound_Read) { + uint8 ret = IRAM[ramPos]; +/* Maybe I should call N163SoundHack() here? */ +#ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) +#endif + ramPos = (ramPos + autoInc) & 0x7F; + return ret; +} + +DECLFW(N163Sound_Write) { + switch (A & 0xF800) { + case 0x4800: + if (ramPos & 0x40) { + if (FSettings.SndRate) { + N163SoundHack(); + GameExpSound.Fill = N163Sound; + GameExpSound.HiFill = DoN163SoundHQ; + GameExpSound.HiSync = SyncHQ; + } + } + IRAM[ramPos] = V; + ramPos = (ramPos + autoInc) & 0x7F; + break; + case 0xF800: + ramPos = V & 0x7F; + autoInc = (V & 0x80) >> 7; + break; + } +} + +uint8 *GetIRAM_ptr(void) { + return IRAM; +} + +uint32 GetIRAM_size(void) { + return sizeof(IRAM); +} + +static void N163SC(void) { + if (FSettings.SndRate) { + int i; + for (i = 0; i < 8; i++) { + memset(&N163Snd[i].vcount, 0, sizeof(N163Snd[i].vcount)); + memset(&N163Snd[i].PlayIndex, 0, sizeof(N163Snd[i].PlayIndex)); + } + CVBC = 0; + ramPos = 0; + } +} + +void N163Sound_ESI(void) { + GameExpSound.RChange = N163SC; + N163SC(); + + if (iNESCart.battery) { + memset(IRAM, 0, sizeof(IRAM)); + } else { + FCEU_MemoryRand(IRAM, sizeof(IRAM)); + } +} + +void N163Sound_AddStateInfo(void) { + AddExState(IRAM, 0x80, 0, "IRAM"); + AddExState(&CVBC, 4, 0, "BC00"); + AddExState(&ramPos, 1, 0, "INDX"); + AddExState(&autoInc, 1, 0, "INCR"); + + AddExState(&N163Snd[0].vcount, 4, 0, "C0VC"); + AddExState(&N163Snd[0].PlayIndex, 4, 0, "C0PI"); + AddExState(&N163Snd[0].output, 2, 0, "C0OP"); + + AddExState(&N163Snd[1].vcount, 4, 0, "C1VC"); + AddExState(&N163Snd[1].PlayIndex, 4, 0, "C1PI"); + AddExState(&N163Snd[1].output, 2, 0, "C1OP"); + + AddExState(&N163Snd[2].vcount, 4, 0, "C2VC"); + AddExState(&N163Snd[2].PlayIndex, 4, 0, "C2PI"); + AddExState(&N163Snd[2].output, 2, 0, "C2OP"); + + AddExState(&N163Snd[3].vcount, 4, 0, "C3VC"); + AddExState(&N163Snd[3].PlayIndex, 4, 0, "C3PI"); + AddExState(&N163Snd[3].output, 2, 0, "C3OP"); + + AddExState(&N163Snd[4].vcount, 4, 0, "C4VC"); + AddExState(&N163Snd[4].PlayIndex, 4, 0, "C4PI"); + AddExState(&N163Snd[4].output, 2, 0, "C4OP"); + + AddExState(&N163Snd[5].vcount, 4, 0, "C5VC"); + AddExState(&N163Snd[5].PlayIndex, 4, 0, "C5PI"); + AddExState(&N163Snd[5].output, 2, 0, "C5OP"); + + AddExState(&N163Snd[6].vcount, 4, 0, "C6VC"); + AddExState(&N163Snd[6].PlayIndex, 4, 0, "C6PI"); + AddExState(&N163Snd[6].output, 2, 0, "C6OP"); + + AddExState(&N163Snd[7].vcount, 4, 0, "C7VC"); + AddExState(&N163Snd[7].PlayIndex, 4, 0, "C7PI"); + AddExState(&N163Snd[7].output, 2, 0, "C7OP"); +} diff --git a/src/mappers/sound/n163sound.h b/src/mappers/sound/n163sound.h new file mode 100644 index 000000000..3d1cbe02f --- /dev/null +++ b/src/mappers/sound/n163sound.h @@ -0,0 +1,32 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _N163_SOUND_H +#define _N163_SOUND_H + +void N163Sound_ESI(void); +DECLFR(N163Sound_Read); +DECLFW(N163Sound_Write); +void N163Sound_AddStateInfo(void); + +uint8 *GetIRAM_ptr(void); /* pointer to internal RAM */ +uint32 GetIRAM_size(void); + +#endif /* _N163_SOUND_H */ diff --git a/src/mappers/sound/s5bsound.c b/src/mappers/sound/s5bsound.c new file mode 100644 index 000000000..34b284320 --- /dev/null +++ b/src/mappers/sound/s5bsound.c @@ -0,0 +1,324 @@ + +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* SUNSOFT-5B Sound */ + +#include "mapinc.h" +#include "s5bsound.h" + +#if 0 /* remove comment to use old S5B emulation */ +#define USE_OLD_SB5 +#endif + +#ifndef USE_OLD_SB5 +#define USE_EMU2149 +#endif + +#ifdef USE_EMU2149 +#include "emu2149.h" + +static int32 dwave = 0; +static PSG *psg_chip = NULL; + +static void PSG_fillbuf(PSG *ssg, int32 *buf, int32 len, int shift) { + while (len > 0) { + *buf += (GetOutput(SND_S5B, PSG_calc(psg_chip) << shift)); + buf++; + len--; + } +} + +static void UpdatePSGNEO(int32 *buf, int Count) { + PSG_fillbuf(psg_chip, buf, Count, 4); +} + +static void UpdatePSG(int Count) { + int32 z, a; + z = ((SOUNDTS << 16) / soundtsinc) >> 4; + a = z - dwave; + if (a) { + PSG_fillbuf(psg_chip, &Wave[dwave], a, 1); + } + dwave = 0; +} + +DECLFW(S5BSound_Write) { + if (!psg_chip) { + return; + } + + switch (A & 0xE000) { + case 0xC000: + PSG_writeIO(psg_chip, 0, V); + break; + case 0xE000: + GameExpSound.Fill = UpdatePSG; + GameExpSound.NeoFill = UpdatePSGNEO; + PSG_writeIO(psg_chip, 1, V); + break; + } +} + +static void S5BSound_SC(void) { + if (psg_chip) { + PSG_setRate(psg_chip, FSettings.SndRate ? FSettings.SndRate : 44100); + PSG_setVolumeMode(psg_chip, 1); + PSG_reset(psg_chip); + } +} + +static void S5BSound_KILL(void) { + if (psg_chip) { + PSG_delete(psg_chip); + psg_chip = NULL; + } +} + +void S5BSound_ESI(void) { + if (!(psg_chip = PSG_new(3579545 / 4, FSettings.SndRate ? FSettings.SndRate : 44100))) { + return; + } + + GameExpSound.RChange = S5BSound_SC; + GameExpSound.Kill = S5BSound_KILL; + + S5BSound_SC(); +} + +void S5BSound_AddStateInfo(void) { + if (!psg_chip) { + return; + } + + /* Sound states */ + AddExState(psg_chip->reg, sizeof(psg_chip->reg), 0, "REG"); + + AddExState(psg_chip->count, sizeof(psg_chip->count), 0, "PCNT"); + AddExState(psg_chip->volume, sizeof(psg_chip->volume), 0, "PVOL"); + AddExState(psg_chip->edge, sizeof(psg_chip->edge), 0, "EDGE"); + AddExState(psg_chip->freq, sizeof(psg_chip->freq), 0, "FREQ"); + AddExState(psg_chip->tmask, sizeof(psg_chip->tmask), 0, "TMSK"); + AddExState(psg_chip->nmask, sizeof(psg_chip->nmask), 0, "NMSK"); + + AddExState(&psg_chip->env_ptr, sizeof(psg_chip->env_ptr), 0, "PTR"); + AddExState(&psg_chip->env_face, sizeof(psg_chip->env_face), 0, "FACE"); + + AddExState(&psg_chip->env_continue, sizeof(psg_chip->env_continue), 0, "CONT"); + AddExState(&psg_chip->env_attack, sizeof(psg_chip->env_attack), 0, "ATTK"); + AddExState(&psg_chip->env_alternate, sizeof(psg_chip->env_alternate), 0, "ALT"); + AddExState(&psg_chip->env_hold, sizeof(psg_chip->env_hold), 0, "HOLD"); + AddExState(&psg_chip->env_pause, sizeof(psg_chip->env_pause), 0, "PAUS"); + + AddExState(&psg_chip->env_freq, sizeof(psg_chip->env_freq), 0, "EFRQ"); + AddExState(&psg_chip->env_count, sizeof(psg_chip->env_count), 0, "ECNT"); + + AddExState(&psg_chip->noise_seed, sizeof(psg_chip->noise_seed), 0, "NSED"); + AddExState(&psg_chip->noise_scaler, sizeof(psg_chip->noise_scaler), 0, "NSCL"); + AddExState(&psg_chip->noise_count, sizeof(psg_chip->noise_count), 0, "NCNT"); + AddExState(&psg_chip->noise_freq, sizeof(psg_chip->noise_freq), 0, "NFRQ"); +} + +#else /* !USE_EMU2149 */ +static void (*sfun[3])(void); +static uint8 sndcmd, sreg[14]; + +static int32 vcount[3]; +static int32 dcount[3]; +static int32 CAYBC[3]; + +static void AYSound(int Count); +static void AYSoundHQ(void); +static void AYHiSync(int ts); +static void DoAYSQ(int x); +static void DoAYSQHQ(int x); + +static void DoAYSQ(int x) { + int32 freq = ((sreg[x << 1] | ((sreg[(x << 1) + 1] & 15) << 8)) + 1) << (4 + 17); + int32 amp = (sreg[0x8 + x] & 15) << 2; + int32 start, end; + int V; + + amp += amp >> 1; + amp = GetOutput(SND_S5B, amp); + + start = CAYBC[x]; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) + return; + CAYBC[x] = end; + + if (amp && !(sreg[0x7] & (1 << x))) { + for (V = start; V < end; V++) { + if (dcount[x]) + Wave[V >> 4] += amp; + vcount[x] -= nesincsize; + while (vcount[x] <= 0) { + dcount[x] ^= 1; + vcount[x] += freq; + } + } + } +} + +static void DoAYSQHQ(int x) { + uint32 V; + int32 freq = ((sreg[x << 1] | ((sreg[(x << 1) + 1] & 15) << 8)) + 1) << 4; + int32 amp = (sreg[0x8 + x] & 15) << 6; + + amp += amp >> 1; + amp = GetOutput(SND_S5B, amp); + + if (!(sreg[0x7] & (1 << x))) { + for (V = CAYBC[x]; V < SOUNDTS; V++) { + if (dcount[x]) + WaveHi[V] += amp; + vcount[x]--; + if (vcount[x] <= 0) { + dcount[x] ^= 1; + vcount[x] = freq; + } + } + } + CAYBC[x] = SOUNDTS; +} + +static void DoAYSQ1(void) { + DoAYSQ(0); +} + +static void DoAYSQ2(void) { + DoAYSQ(1); +} + +static void DoAYSQ3(void) { + DoAYSQ(2); +} + +static void DoAYSQ1HQ(void) { + DoAYSQHQ(0); +} + +static void DoAYSQ2HQ(void) { + DoAYSQHQ(1); +} + +static void DoAYSQ3HQ(void) { + DoAYSQHQ(2); +} + +static void AYSound(int Count) { + DoAYSQ1(); + DoAYSQ2(); + DoAYSQ3(); + CAYBC[0] = Count; + CAYBC[1] = Count; + CAYBC[2] = Count; +} + +static void AYSoundHQ(void) { + DoAYSQ1HQ(); + DoAYSQ2HQ(); + DoAYSQ3HQ(); +} + +static void AYHiSync(int32 ts) { + CAYBC[0] = ts; + CAYBC[1] = ts; + CAYBC[2] = ts; +} + +DECLFW(S5BSound_Write) { + switch (A & 0xE000) { + case 0xC000: + sndcmd = V & 0x0F; + break; + case 0xE000: + GameExpSound.Fill = AYSound; + GameExpSound.HiFill = AYSoundHQ; + GameExpSound.HiSync = AYHiSync; + switch (sndcmd) { + case 0: + case 1: + case 8: + if (sfun[0]) { + sfun[0](); + } + break; + case 2: + case 3: + case 9: + if (sfun[1]) { + sfun[1](); + } + break; + case 4: + case 5: + case 10: + if (sfun[2]) { + sfun[2](); + } + break; + case 7: + if (sfun[0]) { + sfun[0](); + } + if (sfun[1]) { + sfun[1](); + } + break; + } + sreg[sndcmd] = V; + break; + } +} + +static void S5BSound_SC(void) { + memset(dcount, 0, sizeof(dcount)); + memset(vcount, 0, sizeof(vcount)); + memset(CAYBC, 0, sizeof(CAYBC)); + if (FSettings.SndRate) { + if (FSettings.soundq >= 1) { + sfun[0] = DoAYSQ1HQ; + sfun[1] = DoAYSQ2HQ; + sfun[2] = DoAYSQ3HQ; + } else { + sfun[0] = DoAYSQ1; + sfun[1] = DoAYSQ2; + sfun[2] = DoAYSQ3; + } + } else { + memset(sfun, 0, sizeof(sfun)); + } +} + +void S5BSound_ESI(void) { + GameExpSound.RChange = S5BSound_SC; + S5BSound_SC(); +} + +void S5BSound_AddStateInfo(void) { + AddExState(&sndcmd, 1, 0, "SCMD"); + AddExState(sreg, 14, 0, "SREG"); + AddExState(dcount, 12, 0, "DCNT"); + AddExState(vcount, 12, 0, "VCNT"); + AddExState(CAYBC, 12, 0, "BC00"); +} +#endif diff --git a/src/mappers/sound/s5bsound.h b/src/mappers/sound/s5bsound.h new file mode 100644 index 000000000..f6e785568 --- /dev/null +++ b/src/mappers/sound/s5bsound.h @@ -0,0 +1,28 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FME7_SOUND_H +#define _FME7_SOUND_H + +void S5BSound_ESI(void); +DECLFW(S5BSound_Write); +void S5BSound_AddStateInfo(void); + +#endif /* _FME7_SOUND_H */ diff --git a/src/mappers/sound/vrc6sound.c b/src/mappers/sound/vrc6sound.c new file mode 100644 index 000000000..931d2ae44 --- /dev/null +++ b/src/mappers/sound/vrc6sound.c @@ -0,0 +1,351 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-6 Sound + * + */ + +#include "mapinc.h" +#include "vrc6sound.h" + +enum { SQUARE1, SQUARE2, SAW }; + +typedef struct __VRC6SQUARE { + /* regs */ + uint8 volume; + uint8 duty; + uint8 mode; + uint8 enabled; + uint16 freq; + + /* timers */ + uint8 dcount; + int32 vcount; + int32 cvbc; +} VRC6SQUARE; + +typedef struct __VRC6SAW { + /* regs */ + uint8 accumrate; + uint8 enabled; + uint16 freq; + + uint8 phaseacc; + + /* timers */ + uint8 dcount; + int32 vcount; + int32 cvbc; +} VRC6SAW; + +typedef struct __VRC6SOUND { + VRC6SQUARE square[2]; + VRC6SAW saw; + uint8 haltsound; + uint8 freqshift; +} VR6SOUND; + +static VR6SOUND VRC6Sound; + +static void (*sfun[3])(void); + +static INLINE void DoSQV(VRC6SQUARE *channel) { + int32 start, end, V; + + start = channel->cvbc; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) { + return; + } + channel->cvbc = end; + + if (!VRC6Sound.haltsound && channel->enabled) { + int32 amp = ((channel->volume << 8) * 6 / 8) >> 4; + int32 out = GetOutput(SND_VRC6, amp); + + for (V = start; V < end; V++) { + channel->vcount -= nesincsize; + while (channel->vcount <= 0) { + channel->dcount = (channel->dcount + 1) & 0x0F; + channel->vcount += ((channel->freq >> VRC6Sound.freqshift) + 1) << 17; + } + if (channel->mode || (channel->dcount <= channel->duty)) { + Wave[V >> 4] += out; + } + } + } +} + +static void DoSQV1(void) { + DoSQV(&VRC6Sound.square[0]); +} + +static void DoSQV2(void) { + DoSQV(&VRC6Sound.square[1]); +} + +static void DoSawV(void) { + int32 start, end, V; + + start = VRC6Sound.saw.cvbc; + end = (SOUNDTS << 16) / soundtsinc; + if (end <= start) { + return; + } + VRC6Sound.saw.cvbc = end; + + if (VRC6Sound.saw.enabled) { + int32 out; + + for (V = start; V < end; V++) { + VRC6Sound.saw.vcount -= nesincsize; + while (VRC6Sound.saw.vcount <= 0) { + VRC6Sound.saw.dcount++; + VRC6Sound.saw.dcount %= 14; + if (VRC6Sound.saw.dcount == 0) { + VRC6Sound.saw.phaseacc = 0; + } else if (!(VRC6Sound.saw.dcount & 0x01)) { + VRC6Sound.saw.phaseacc += VRC6Sound.saw.accumrate; + } + VRC6Sound.saw.vcount += ((VRC6Sound.saw.freq >> VRC6Sound.freqshift) + 1) << 17; + } + out = (((VRC6Sound.saw.phaseacc >> 3) & 0x1F) << 3) * 6 / 8; + Wave[V >> 4] += GetOutput(SND_VRC6, out); + } + } +} + +static INLINE void DoSQVHQ(VRC6SQUARE *channel) { + int32 V; + + if (channel->enabled) { + int32 amp = (channel->volume << 8) * 6 / 8; + int32 out = GetOutput(SND_VRC6, amp); + + for (V = channel->cvbc; V < (int32)SOUNDTS; V++) { + channel->vcount--; + if (channel->vcount <= 0) { + channel->dcount++; + channel->dcount &= 0x0F; + channel->vcount = (channel->freq >> VRC6Sound.freqshift) + 1; + } + if ((channel->mode || (channel->dcount > channel->duty))) { + WaveHi[V] += out; + } + } + } + channel->cvbc = SOUNDTS; +} + +static void DoSQV1HQ(void) { + DoSQVHQ(&VRC6Sound.square[0]); +} + +static void DoSQV2HQ(void) { + DoSQVHQ(&VRC6Sound.square[1]); +} + +static void DoSawVHQ(void) { + int32 V; + + if (VRC6Sound.saw.enabled) { + int32 out = 0; + + for (V = VRC6Sound.saw.cvbc; V < (int32)SOUNDTS; V++) { + VRC6Sound.saw.vcount--; + while (VRC6Sound.saw.vcount <= 0) { + VRC6Sound.saw.dcount++; + VRC6Sound.saw.dcount %= 14; + if (VRC6Sound.saw.dcount == 0) { + VRC6Sound.saw.phaseacc = 0; + } else if (!(VRC6Sound.saw.dcount & 0x01)) { + VRC6Sound.saw.phaseacc += VRC6Sound.saw.accumrate; + } + VRC6Sound.saw.vcount += ((VRC6Sound.saw.freq >> VRC6Sound.freqshift) + 1) << 0; + } + out = (((VRC6Sound.saw.phaseacc >> 3) & 0x1F) << 7) * 6 / 8; + WaveHi[V] += GetOutput(SND_VRC6, out); + } + } + VRC6Sound.saw.cvbc = SOUNDTS; +} + +static void VRC6RunSound(int32 Count) { + DoSQV1(); + DoSQV2(); + DoSawV(); + VRC6Sound.square[0].cvbc = Count; + VRC6Sound.square[1].cvbc = Count; + VRC6Sound.saw.cvbc = Count; + +} + +static void VRC6RunSoundHQ(void) { + DoSQV1HQ(); + DoSQV2HQ(); + DoSawVHQ(); +} + +static void VRC6SyncHQ(int32 ts) { + VRC6Sound.square[0].cvbc = ts; + VRC6Sound.square[1].cvbc = ts; + VRC6Sound.saw.cvbc = ts; +} + +static void VRC6Square_Write(VRC6SQUARE *channel, uint8 reg, uint8 V) { + switch (reg & 0x03) { + case 0: + channel->volume = V & 0x0F; + channel->duty = (V & 0x70) >> 4; + channel->mode = (V & 0x80) == 0x80; + break; + + case 1: + channel->freq = (channel->freq & 0xF00) | V; + break; + + case 2: + channel->freq = (channel->freq & 0xFF) | ((V & 0x0F) << 8); + channel->enabled = (V & 0x80) == 0x80; + if (!channel->enabled) { + channel->dcount = 0; + } + break; + } +} + +DECLFW(VRC6Sound_Write) { + switch (A & 0xF003) { + case 0x9000: + case 0x9001: + case 0x9002: + VRC6Square_Write(&VRC6Sound.square[0], A & 0x03, V); + if (sfun[SQUARE1]) { + sfun[SQUARE1](); + } + break; + + case 0x9003: + VRC6Sound.haltsound = (V & 0x01) == 0x01; + if (V & 0x04) { + VRC6Sound.freqshift = 8; + } else if (V & 0x02) { + VRC6Sound.freqshift = 4; + } else { + VRC6Sound.freqshift = 0; + } + break; + + case 0xA000: + case 0xA001: + case 0xA002: + VRC6Square_Write(&VRC6Sound.square[1], A & 0x03, V); + if (sfun[SQUARE2]) { + sfun[SQUARE2](); + } + break; + + case 0xB000: + case 0xB001: + case 0xB002: + switch (A & 0x03) { + case 0: + VRC6Sound.saw.accumrate = V & 0x3F; + break; + + case 1: + VRC6Sound.saw.freq = (VRC6Sound.saw.freq & 0xF00) | V; + break; + + case 2: + VRC6Sound.saw.freq = (VRC6Sound.saw.freq & 0xFF) | ((V & 0x0F) << 8); + VRC6Sound.saw.enabled = (V & 0x80) == 0x80; + if (!VRC6Sound.saw.enabled) { + VRC6Sound.saw.dcount = 0; + } + break; + } + if (sfun[SAW]) { + sfun[SAW](); + } + break; + } +} + +static void VRC6Sound_SC(void) { + GameExpSound.Fill = VRC6RunSound; + GameExpSound.HiFill = VRC6RunSoundHQ; + GameExpSound.HiSync = VRC6SyncHQ; + + VRC6Sound.square[0].vcount = 1; + VRC6Sound.square[1].vcount = 1; + VRC6Sound.saw.vcount = 1; + + if (FSettings.SndRate) { + if (FSettings.soundq >= 1) { + sfun[SQUARE1] = DoSQV1HQ; + sfun[SQUARE2] = DoSQV2HQ; + sfun[SAW] = DoSawVHQ; + } else { + sfun[SQUARE1] = DoSQV1; + sfun[SQUARE2] = DoSQV2; + sfun[SAW] = DoSawV; + } + } else { + memset(sfun, 0, sizeof(sfun)); + } +} + +void VRC6Sound_ESI(void) { + memset(&VRC6Sound, 0, sizeof(VRC6Sound)); + GameExpSound.RChange = VRC6Sound_SC; + VRC6Sound_SC(); +} + +void VRC6Sound_AddStateInfo(void) { + AddExState(&VRC6Sound.haltsound, 1, 0, "HLTS"); + AddExState(&VRC6Sound.freqshift, 1, 0, "FRSH"); + + AddExState(&VRC6Sound.square[0].enabled, 1, 0, "S0EN"); + AddExState(&VRC6Sound.square[0].volume, 1, 0, "S0VL"); + AddExState(&VRC6Sound.square[0].freq, 2, 0, "S0FQ"); + AddExState(&VRC6Sound.square[0].duty, 1, 0, "S0DT"); + AddExState(&VRC6Sound.square[0].mode, 1, 0, "S0MD"); + AddExState(&VRC6Sound.square[0].dcount, 1, 0, "S0DC"); + AddExState(&VRC6Sound.square[0].vcount, 4, 0, "S0VC"); + AddExState(&VRC6Sound.square[0].cvbc, 4, 0, "S0BC"); + + AddExState(&VRC6Sound.square[1].enabled, 1, 0, "S1EN"); + AddExState(&VRC6Sound.square[1].volume, 1, 0, "S1VL"); + AddExState(&VRC6Sound.square[1].freq, 2, 0, "S1FQ"); + AddExState(&VRC6Sound.square[1].duty, 1, 0, "S1DT"); + AddExState(&VRC6Sound.square[1].mode, 1, 0, "S1MD"); + AddExState(&VRC6Sound.square[1].dcount, 1, 0, "S1DC"); + AddExState(&VRC6Sound.square[1].vcount, 4, 0, "S1VC"); + AddExState(&VRC6Sound.square[1].cvbc, 4, 0, "S1BC"); + + AddExState(&VRC6Sound.saw.enabled, 1, 0, "SWEN"); + AddExState(&VRC6Sound.saw.accumrate, 1, 0, "SWAR"); + AddExState(&VRC6Sound.saw.phaseacc, 1, 0, "SWAC"); + AddExState(&VRC6Sound.saw.freq, 2, 0, "SWFR"); + AddExState(&VRC6Sound.saw.dcount, 1, 0, "SWDC"); + AddExState(&VRC6Sound.saw.vcount, 4, 0, "SWVC"); + AddExState(&VRC6Sound.saw.cvbc, 4, 0, "SWBC"); +} diff --git a/src/mappers/sound/vrc6sound.h b/src/mappers/sound/vrc6sound.h new file mode 100644 index 000000000..31b7eb7f2 --- /dev/null +++ b/src/mappers/sound/vrc6sound.h @@ -0,0 +1,28 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _VRC6_SOUND_H +#define _VRC6_SOUND_H + +void VRC6Sound_ESI(void); +DECLFW(VRC6Sound_Write); +void VRC6Sound_AddStateInfo(void); + +#endif /* _VRC6_SOUND_H */ diff --git a/src/mappers/sound/vrc7sound.c b/src/mappers/sound/vrc7sound.c new file mode 100644 index 000000000..dc416f8e9 --- /dev/null +++ b/src/mappers/sound/vrc7sound.c @@ -0,0 +1,150 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "emu2413.h" +#include "vrc7sound.h" + +static int32 dwave = 0; + +static OPLL *chip = NULL; + +static void OPLL_fillbuf(OPLL *opll, int32 *buf, int32 len, int shift) { + while (len > 0) { + *buf += GetOutput(SND_VRC7, (OPLL_calc(chip) + 32768)) << shift; + buf++; + len--; + } +} + +static void UpdateOPLNEO(int32 *buf, int Count) { + OPLL_fillbuf(chip, buf, Count, 4); +} + +static void UpdateOPL(int Count) { + int32 z, a; + z = ((SOUNDTS << 16) / soundtsinc) >> 4; + a = z - dwave; + if (a) { + OPLL_fillbuf(chip, &Wave[dwave], a, 1); + } + dwave = 0; +} + +DECLFW(VRC7Sound_Write) { + if (!chip) { + return; + } + + switch (A & 0xF030) { + case 0x9010: + OPLL_writeIO(chip, 0, V); + break; + case 0x9030: + GameExpSound.Fill = UpdateOPL; + GameExpSound.NeoFill = UpdateOPLNEO; + OPLL_writeIO(chip, 1, V); + break; + } +} + +static void VRC7SC(void) { + if (chip) { + OPLL_setChipType(chip, OPLL_VRC7_TONE); + OPLL_setRate(chip, FSettings.SndRate ? FSettings.SndRate : 44100); + OPLL_resetPatch(chip, OPLL_VRC7_TONE); + } +} + +static void VRC7SKill(void) { + if (chip) { + OPLL_delete(chip); + chip = NULL; + } +} + +void VRC7Sound_ESI(void) { + if (!(chip = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 44100))) { + return; + } + + GameExpSound.RChange = VRC7SC; + GameExpSound.Kill = VRC7SKill; + + VRC7SC(); +} + +void VRC7Sound_AddStateInfo(void) { + if (!chip) { + return; + } + + /* Sound states */ + AddExState(&chip->clk, sizeof(chip->clk), 0, "CLK7"); + AddExState(&chip->rate, sizeof(chip->rate), 0, "RATE"); + + AddExState(&chip->chip_type, sizeof(chip->chip_type), 0, "CHIP"); + + AddExState(&chip->adr, sizeof(chip->adr), 0, "ADR7"); + + AddExState(&chip->inp_step, sizeof(chip->inp_step), 0, "ISTP"); + AddExState(&chip->out_step, sizeof(chip->out_step), 0, "OSTP"); + AddExState(&chip->out_time, sizeof(chip->out_time), 0, "OTME"); + + AddExState(chip->reg, sizeof(chip->reg), 0, "REG7"); + AddExState(&chip->test_flag, sizeof(chip->test_flag), 0, "TFLG"); + AddExState(&chip->slot_key_status, sizeof(chip->slot_key_status), 0, "SKST"); + AddExState(&chip->rhythm_mode, sizeof(chip->rhythm_mode), 0, "RMOD"); + + AddExState(&chip->eg_counter, sizeof(chip->eg_counter), 0, "ECTR"); + + AddExState(&chip->pm_phase, sizeof(chip->pm_phase), 0, "PMPH"); + AddExState(&chip->am_phase, sizeof(chip->am_phase), 0, "AMPH"); + + AddExState(&chip->lfo_am, sizeof(chip->lfo_am), 0, "LFO7"); + + AddExState(&chip->noise, sizeof(chip->noise), 0, "NOIS"); + AddExState(&chip->short_noise, sizeof(chip->short_noise), 0, "SNOS"); + + AddExState(chip->patch_number, sizeof(chip->patch_number), 0, "PTNM"); + + /* VRC7 only uses 12 slots */ + AddExState(&chip->slot[0], sizeof(chip->slot[0]), 0, "SL00"); + AddExState(&chip->slot[1], sizeof(chip->slot[1]), 0, "SL01"); + AddExState(&chip->slot[2], sizeof(chip->slot[2]), 0, "SL02"); + AddExState(&chip->slot[3], sizeof(chip->slot[3]), 0, "SL03"); + AddExState(&chip->slot[4], sizeof(chip->slot[4]), 0, "SL04"); + AddExState(&chip->slot[5], sizeof(chip->slot[5]), 0, "SL05"); + AddExState(&chip->slot[6], sizeof(chip->slot[6]), 0, "SL06"); + AddExState(&chip->slot[7], sizeof(chip->slot[7]), 0, "SL07"); + AddExState(&chip->slot[8], sizeof(chip->slot[8]), 0, "SL08"); + AddExState(&chip->slot[9], sizeof(chip->slot[9]), 0, "SL09"); + AddExState(&chip->slot[10], sizeof(chip->slot[10]), 0, "SL10"); + AddExState(&chip->slot[11], sizeof(chip->slot[11]), 0, "SL11"); + + AddExState(&chip->mask, sizeof(chip->mask), 0, "MASK"); + + AddExState(chip->ch_out, sizeof(chip->ch_out), 0, "CHOU"); + AddExState(chip->mix_out, sizeof(chip->mix_out), 0, "MIXO"); + + /* custom patches */ + AddExState(&chip->patch[0], sizeof(chip->patch[0]), 0, "PAT0"); + AddExState(&chip->patch[1], sizeof(chip->patch[1]), 0, "PAT1"); +} diff --git a/src/mappers/sound/vrc7sound.h b/src/mappers/sound/vrc7sound.h new file mode 100644 index 000000000..a28e396a2 --- /dev/null +++ b/src/mappers/sound/vrc7sound.h @@ -0,0 +1,28 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _VRC7_SOUND_H +#define _VRC7_SOUND_H + +void VRC7Sound_ESI(void); +DECLFW(VRC7Sound_Write); +void VRC7Sound_AddStateInfo(void); + +#endif /* _VRC7_SOUND_H */ diff --git a/src/mappers/unif3Dblock.c b/src/mappers/unif3Dblock.c new file mode 100644 index 000000000..99d1aacbb --- /dev/null +++ b/src/mappers/unif3Dblock.c @@ -0,0 +1,109 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 CaH4e3 + * Copyright (C) 2023-2024 negativeExponent + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* NOTE: This only emulates the UNIF variant of 3D-Blocks */ + +#include "mapinc.h" + +static uint8 reg[4], IRQa; +static int16 IRQCount, IRQPause; + +static int16 Count = 0x0000; + +static SFORMAT StateRegs[] = { + { reg, 4, "REGS" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8(0); +} + +/* #define Count 0x1800 */ +#define Pause 0x010 + +static DECLFW(UNL3DBlockWrite) { + switch (A) { + /* 4800 32 */ + /* 4900 37 */ + /* 4a00 01 */ + /* 4e00 18 */ + case 0x4800: + reg[0] = V; + break; + case 0x4900: + reg[1] = V; + break; + case 0x4a00: + reg[2] = V; + break; + case 0x4e00: + reg[3] = V; + IRQCount = Count; + IRQPause = Pause; + IRQa = 1; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +static void UNL3DBlockPower(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4800, 0x4E00, UNL3DBlockWrite); +} + +static void UNL3DBlockReset(void) { + Count += 0x10; + FCEU_printf("Count=%04x\n", Count); +} + +static void UNL3DBlockIRQHook(int a) { + if (IRQa) { + if (IRQCount > 0) { + IRQCount -= a; + } else { + if (IRQPause > 0) { + IRQPause -= a; + X6502_IRQBegin(FCEU_IQEXT); + } else { + IRQCount = Count; + IRQPause = Pause; + X6502_IRQEnd(FCEU_IQEXT); + } + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void UNL3DBlock_Init(CartInfo *info) { + info->Power = UNL3DBlockPower; + info->Reset = UNL3DBlockReset; + MapIRQHook = UNL3DBlockIRQHook; + GameStateRestore = StateRestore; + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/unifEt4320.c b/src/mappers/unifEt4320.c new file mode 100644 index 000000000..bc000901f --- /dev/null +++ b/src/mappers/unifEt4320.c @@ -0,0 +1,154 @@ +/* FCE Ultra - NES/Famicom Emulator +* +* Copyright notice for this file: +* Copyright (C) 2016 Cluster +* http://clusterrr.com +* clusterrr@clusterrr.com +* Copyright (C) 2023 +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* +MMC3-based multicart mapper with CHR RAM, CHR ROM and PRG RAM + +$6000-7FFF: A~[011xxxxx xxMRSBBB] Multicart reg +This register can only be written to if PRG-RAM is enabled and writable (see $A001) +and BBB = 000 (power on state) + +BBB = CHR+PRG block select bits (A19, A18, A17 for both PRG and CHR) +S = PRG block size & mirroring mode (0=128k with normal MMC3, 1=256k with TxSROM-like single-screen mirroring) +R = CHR mode (0=CHR ROM 1=CHR RAM) +M = CHR block size (0=256k 1=128k) +ignored when S is 0 for some reason + +Example Game: +-------------------------- +7 in 1 multicart (Amarello, TMNT2, Contra, Ninja Cat, Ninja Crusaders, Rainbow Islands 2) +*/ + +/* NOTE: + * Appears similar to Mapper 327 but with mirroring similar to Mapper 118? + * Cannot find a cart to confirm this though +*/ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reg; + +static void BMC810131C_PW(uint16 A, uint16 V) { + uint16 mask = (reg & 0x08) ? 0x1F : 0x0F; + uint16 base = (reg << 4) & 0x70; + + setprg8(A, (base | (V & mask))); +} + +static void BMC810131C_CW(uint16 A, uint16 V) { + uint16 base = (reg << 7) & 0x380; + + if (reg & 0x10) { + setchr1r(0x10, A, V); + } else if ((reg & 0x20) && (reg & 0x08)) { + setchr1(A, (base | (V & 0xFF))); + } else { + setchr1(A, (base | (V & 0x7F))); + } +} + +static void BMC810131C_SyncMIRR(void) { + if (reg & 0x08) { + if (mmc3.cmd & 0x80) { + setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); + } else { + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); + setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); + setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); + } + } else { + setmirror((mmc3.mirr & 0x01) ^ 0x01); + } +} + +static DECLFW(BMC810131C_Write) { + if (((mmc3.wram & 0xC0) == 0x80) && !(reg & 0x07)) { + reg = A & 0x3F; + MMC3_FixPRG(); + MMC3_FixCHR(); + } else { + CartBW(A, V); + } +} + +static DECLFW(BMC810131C_WriteCMD) { + switch (A & 0xE001) { + case 0x8001: + switch (mmc3.cmd & 0x07) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + mmc3.reg[mmc3.cmd & 0x07] = V; + MMC3_FixCHR(); + MMC3_FixMIR(); + break; + default: + MMC3_CMDWrite(A, V); + break; + } + break; + default: + MMC3_CMDWrite(A, V); + break; + } +} + +static void BMC810131C_Reset(void) { + reg = 0; + MMC3_Reset(); +} + +static void BMC810131C_Power(void) { + reg = 0; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, BMC810131C_Write); + SetWriteHandler(0x8000, 0x9FFF, BMC810131C_WriteCMD); +} + +static void BMC810131C_Close(void) { + MMC3_Close(); +} + +void BMC810131C_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_FixMIR = BMC810131C_SyncMIRR; + MMC3_pwrap = BMC810131C_PW; + MMC3_cwrap = BMC810131C_CW; + info->Power = BMC810131C_Power; + info->Reset = BMC810131C_Reset; + info->Close = BMC810131C_Close; + AddExState(®, 1, 0, "EXPR"); + + CHRRAMSIZE = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} diff --git a/src/mappers/unifFamicombox.c b/src/mappers/unifFamicombox.c new file mode 100644 index 000000000..e4f78fe23 --- /dev/null +++ b/src/mappers/unifFamicombox.c @@ -0,0 +1,115 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 regs[8]; + +static SFORMAT StateRegs[] = +{ + { regs, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg2r(0x10, 0x0800, 0); + setprg2r(0x10, 0x1000, 1); + setprg2r(0x10, 0x1800, 2); + setprg8r(0x10, 0x6000, 1); + setprg16(0x8000, 0); + setprg16(0xC000, ~0); + setchr8(0); +} + +#if 0 + static DECLFW(SSSNROMWrite) +{ + CartBW(A,V); +} +#endif + +static DECLFW(SSSNROMWrite) { +#if 0 + FCEU_printf("write %04x %02x\n",A,V); + regs[A&7] = V; +#endif +} + +static DECLFR(SSSNROMRead) { +/* FCEU_printf("read %04x\n",A); */ + switch (A & 7) { + case 0: return regs[0] = 0xff; /* clear all exceptions */ + case 2: return 0xc0; /* DIP selftest + freeplay */ + case 3: return 0x00; /* 0, 1 - attract + * 2 + * 4 - menu + * 8 - self check and game casette check + * 10 - lock? + * 20 - game title & count display + */ + case 7: return 0x22; /* TV type, key not turned, relay B */ + default: return 0; + } +} + +static void SSSNROMPower(void) { + regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0; + regs[7] = 0xff; + Sync(); + FCEU_MemoryRand(WRAM, WRAMSIZE); +/* SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite); */ + SetReadHandler(0x0800, 0x1FFF, CartBR); + SetWriteHandler(0x0800, 0x1FFF, CartBW); + SetReadHandler(0x5000, 0x5FFF, SSSNROMRead); + SetWriteHandler(0x5000, 0x5FFF, SSSNROMWrite); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); +} + +static void SSSNROMReset(void) { + regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0; +} + +static void SSSNROMClose(void) { +} + +static void SSSNROMIRQHook(void) { +/* X6502_IRQBegin(FCEU_IQEXT); */ +} + +static void StateRestore(int version) { + Sync(); +} + +void SSSNROM_Init(CartInfo *info) { + info->Reset = SSSNROMReset; + info->Power = SSSNROMPower; + info->Close = SSSNROMClose; + GameHBIRQHook = SSSNROMIRQHook; + GameStateRestore = StateRestore; + + WRAMSIZE = 16384; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(StateRegs, ~0, 0, NULL); +} diff --git a/src/mappers/unifKG256.c b/src/mappers/unifKG256.c new file mode 100644 index 000000000..70bd2e713 --- /dev/null +++ b/src/mappers/unifKG256.c @@ -0,0 +1,111 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * + * Copyright (C) 2008 -2020 dragon2snow,loong2snow from www.nesbbs.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * + */ + +#include "mapinc.h" + +static uint8 regs[4]; + +static SFORMAT StateRegs[] = +{ + { regs, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) +{ + uint8 mirr; + int r = 0; + + if ((regs[1]) & 0x20) + r = 1; + if ((regs[1] >> 4) & 0x01) + { + setprg16(0x8000, (regs[1] & 0x07) | (r << 3)); + setprg16(0xC000, (regs[1] & 0x07) | (r << 3)); + setchr8((regs[0] & 0x07) | (r << 3)); + } + else + { + setprg32(0x8000, ((regs[1] >> 1) & 0x03) | (r << 2)); + setchr8((regs[2] & 0x01) | (r << 3)); + } + + mirr = (((regs[0] >> 4) & 0x1)); + + if (mirr) + setmirror(0); + else + setmirror(1); + +} + +static DECLFW(KG256WriteHi) { + regs[2] = V; + Sync(); +} + +static DECLFW(KG256WriteLo) { + regs[A & 0x03] = V; + Sync(); +} + +static void KG256Power(void) { + + regs[0] = 0; + regs[1] = 0; + regs[2] = 0; + regs[3] = 0; + + SetWriteHandler(0x8000, 0xFFFF, KG256WriteHi); + SetWriteHandler(0x6000, 0x7FFF, KG256WriteLo); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + Sync(); + +} + +static void StateRestore(int version) { + Sync(); +} + +static void KG256Reset(void) { + + regs[0] = 0; + regs[1] = 0; + regs[2] = 0; + + Sync(); +} + +void KG256_Init(CartInfo *info) { + + Sync(); + + info->Power = KG256Power; + info->Reset = KG256Reset; + AddExState(StateRegs, ~0, 0, NULL); + GameStateRestore = StateRestore; +} + + + diff --git a/src/mappers/unifT2271.c b/src/mappers/unifT2271.c new file mode 100644 index 000000000..585e57da3 --- /dev/null +++ b/src/mappers/unifT2271.c @@ -0,0 +1,101 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2008 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* T-227-1, 820632, MMC3 based, multimenu, 60000in1 (0010) dip switches */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reset_flag = 0x07; +static uint8 reg; + +static void BMCT2271CW(uint16 A, uint16 V) { + uint32 va = V; + if (reg & 0x20) { + va |= 0x200; + va |= (reg & 0x10) << 4; + } else { + va &= 0x7F; + va |= (reg & 0x18) << 4; + } + setchr1(A, va); +} + +static void BMCT2271PW(uint16 A, uint16 V) { + uint32 va = V & 0x3F; + if (reg & 0x20) { + va &= 0x1F; + va |= 0x40; + va |= (reg & 0x10) << 1; + } else { + va &= 0x0F; + va |= (reg & 0x18) << 1; + } + switch (reg & 3) { + case 0x00: setprg8(A, va); break; + case 0x02: + { + va = (va & 0xFD) | ((reg & 4) >> 1); + if (A < 0xC000) { + setprg16(0x8000, va >> 1); + setprg16(0xC000, va >> 1); + } + break; + } + case 0x01: + case 0x03: if (A < 0xC000) setprg32(0x8000, va >> 2); break; + } +} + +static DECLFW(BMCT2271LoWrite) { + if (!(reg & 0x80)) + reg = A & 0xFF; + MMC3_FixPRG(); + MMC3_FixCHR(); +} + +static DECLFR(BMCT2271HiRead) { + uint32 av = A; + if (reg & 0x40) av = (av & 0xFFF0) | reset_flag; + return CartBR(av); +} + +static void BMCT2271Reset(void) { + reg = 0x00; + reset_flag++; + reset_flag &= 0x0F; + MMC3_Reset(); +} + +static void BMCT2271Power(void) { + reg = 0x00; + MMC3_Power(); + SetWriteHandler(0x6000, 0x7FFF, BMCT2271LoWrite); + SetReadHandler(0x8000, 0xFFFF, BMCT2271HiRead); +} + +void BMCT2271_Init(CartInfo *info) { + MMC3_Init(info, 8, 0); + MMC3_pwrap = BMCT2271PW; + MMC3_cwrap = BMCT2271CW; + info->Power = BMCT2271Power; + info->Reset = BMCT2271Reset; + AddExState(®, 1, 0, "EXPR"); +} diff --git a/src/mappers/unifTransformer.c b/src/mappers/unifTransformer.c new file mode 100644 index 000000000..257149fd9 --- /dev/null +++ b/src/mappers/unifTransformer.c @@ -0,0 +1,103 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * All regs access only by READ + * + * 5000 - I/O - when read, 0 goes to tape output + * ---m3210 + * 3210 - lower scancode nibble + * m - tape input bit + * 5001 - I + * ----7654 + * 7654 - higher scancode nibble + * 5002 - I - reset scancode buffer, ready to new input + * 5004 - O - when read, 1 goes to tape output + * + */ + +#include "mapinc.h" + +char *GetKeyboard(void); + +static char *TransformerKeys, oldkeys[256]; +static int TransformerCycleCount, TransformerChar = 0; + +static void TransformerIRQHook(int a) { + TransformerCycleCount += a; + if (TransformerCycleCount >= 1000) { + uint32 i; + TransformerCycleCount -= 1000; + TransformerKeys = GetKeyboard(); + + for (i = 0; i < 256; i++) { + if (oldkeys[i] != TransformerKeys[i]) { + if (oldkeys[i] == 0) + TransformerChar = i; + else + TransformerChar = i | 0x80; + X6502_IRQBegin(FCEU_IQEXT); + memcpy((void*)&oldkeys[0], (void*)TransformerKeys, sizeof(oldkeys)); + break; + } + } + } +} + +static DECLFR(TransformerRead) { + uint8 ret = 0; + switch (A & 3) { + case 0: ret = TransformerChar & 15; break; + case 1: ret = (TransformerChar >> 4); break; + case 2: X6502_IRQEnd(FCEU_IQEXT); break; + case 4: break; + } + return ret; +} + +static void TransformerPower(void) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, 0); + setprg16(0xC000, ~0); + setchr8(0); + + SetReadHandler(0x5000, 0x5004, TransformerRead); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); + + MapIRQHook = TransformerIRQHook; +} + +static void TransformerClose(void) { +} + +void Transformer_Init(CartInfo *info) { + info->Power = TransformerPower; + info->Close = TransformerClose; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/ppu.c b/src/ppu.c index 628e56495..199cb84b2 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -92,6 +92,10 @@ static uint8 ppudead = 1; static uint8 kook = 0; int fceuindbg = 0; +uint8 QTAIHack = 0; /* bool */ +uint8 qtaintramreg = 0; +uint8 QTAINTRAM[0x800]; + int MMC5Hack = 0, PEC586Hack = 0; uint32 MMC5HackVROMMask = 0; uint8 *MMC5HackExNTARAMPtr = 0; @@ -135,6 +139,8 @@ uint8 UPALRAM[0x03];/* for 0x4/0x8/0xC addresses in palette, the ones in #define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] #define VRAMADR(V) &VPage[(V) >> 10][(V)] +#if 0 +/* moved to MMC5 */ uint8 * MMC5BGVRAMADR(uint32 V) { if (!Sprite16) { extern uint8 mmc5ABMode; /* A=0, B=1 */ @@ -144,6 +150,7 @@ uint8 * MMC5BGVRAMADR(uint32 V) { return &MMC5BGVPage[(V) >> 10][(V)]; } else return &MMC5BGVPage[(V) >> 10][(V)]; } +#endif static DECLFR(A2002) { uint8 ret; diff --git a/src/ppu.h b/src/ppu.h index e3f6cfd78..6bc6e7caf 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -23,4 +23,19 @@ void FCEUPPU_LoadState(int version); extern int scanline; extern uint8 PPU[4]; +/* MMC5 specifics */ +#define Sprite16 (PPU[0] & 0x20) /* Sprites 8x16/8x8 */ +#define PPUON (PPU[1] & 0x18) /* PPU should operate */ + +#define ABANKS MMC5SPRVPage +#define BBANKS MMC5BGVPage +#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] +#define VRAMADR(V) &VPage[(V) >> 10][(V)] +uint8 *MMC5BGVRAMADR(uint32 A); + +/* m547 */ +extern uint8 QTAIHack; +extern uint8 qtaintramreg; +extern uint8 QTAINTRAM[0x800]; + #endif diff --git a/src/sound.c b/src/sound.c index dbf1c8a44..f375a5914 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1143,6 +1143,26 @@ void FCEUI_SetSoundVolume(uint32 volume) { FSettings.SoundVolume = volume; } +int FCEUI_GetExpSoundVolume(int ch) { + return FSettings.ExpSoundVolume[ch]; +} + +int32 GetOutput(int ch, int32 in) { + if ((ch >= SND_VRC6) && (ch <= SND_LAST)) + { + int mod = FCEUI_GetExpSoundVolume(ch); + + if (in == 0 || mod == 0) + { + return 0; /* silence */ + } + if (mod != 256) + { + return (int32)((in * mod) / 256); + } + } + return in; +} SFORMAT FCEUSND_STATEINFO[] = { { &fhcnt, 4 | FCEUSTATE_RLSB, "FHCN" }, diff --git a/src/sound.h b/src/sound.h index c4413ccc6..4e749a9a8 100644 --- a/src/sound.h +++ b/src/sound.h @@ -64,4 +64,11 @@ void FCEUSND_LoadState(int version); void FASTAPASS(1) FCEU_SoundCPUHook(int); +/* Modify channel wave volume based on volume modifiers + * Note: the formulat x = x * y /256 does not yield exact results, + * but is "close enough" and avoids the need for using double values + * or implicit cohersion which are slower (we need speed here) */ +/* TODO: Optimize this. */ +int32 GetOutput(int ch, int32 in); + #endif diff --git a/src/unif.c b/src/unif.c index a022ec82f..e28b0692b 100644 --- a/src/unif.c +++ b/src/unif.c @@ -48,12 +48,21 @@ typedef struct { uint32 info; } UNIF_HEADER; +#if 0 typedef struct { char *name; int ines_mapper; void (*init)(CartInfo *); int flags; } BMAPPING; +#endif +typedef struct { + char *name; + int mapper; + int submapper; + void (*init)(CartInfo *); + int flags; +} BMAPPING; typedef struct { char *name; @@ -411,6 +420,7 @@ static void CheckHashInfo(void) { } +#if 0 #define NO_INES -1 #define BMCFLAG_FORCE4 0x01 #define BMCFLAG_16KCHRR 0x02 @@ -629,6 +639,237 @@ static BMAPPING bmap[] = { { NULL, NO_INES, NULL, 0 } }; +#endif + +#define NO_INES (-1) + +#define BMCFLAG_FORCE4 0x0001 +#define BMCFLAG_16KCHRR 0x0002 +#define BMCFLAG_32KCHRR 0x0004 +#define BMCFLAG_128KCHRR 0x0008 +#define BMCFLAG_256KCHRR 0x0010 +#define BMCFLAG_512KCHRR 0x0020 + +#define BMCFLAG_8KWRAM 0x0020 +#define BMCFLAG_16KWRAM 0x0040 +#define BMCFLAG_32KWRAM 0x0080 + +static BMAPPING bmap[] = { + { "NROM", 0, 0, Mapper000_Init, 0 }, + { "NROM-128", 0, 0, Mapper000_Init, 0 }, + { "NROM-256", 0, 0, Mapper000_Init, 0 }, + { "RROM", 0, 0, Mapper000_Init, 0 }, + { "RROM-128", 0, 0, Mapper000_Init, 0 }, + { "SBROM", 1, 0, Mapper001_Init, 0 }, + { "SCROM", 1, 0, Mapper001_Init, 0 }, + { "SEROM", 1, 0, Mapper001_Init, 0 }, + { "SGROM", 1, 0, Mapper001_Init, 0 }, + { "SL1ROM", 1, 0, Mapper001_Init, 0 }, + { "SLROM", 1, 0, Mapper001_Init, 0 }, + { "SAROM", 1, 0, SAROM_Init, 0 }, + { "SKROM", 1, 0, SKROM_Init, 0 }, + { "SNROM", 1, 0, SNROM_Init, 0 }, + { "SOROM", 1, 0, SOROM_Init, 0 }, + { "UNROM", 2, 0, Mapper002_Init, 0 }, + { "UOROM", 2, 0, Mapper002_Init, 0 }, + { "CNROM", 3, 0, Mapper003_Init, 0 }, + { "HKROM", 4, 0, Mapper004_Init, 0 }, /* 1K WRAM, mapper 004.1 */ + { "TBROM", 4, 0, Mapper004_Init, 0 }, + { "TEROM", 4, 0, Mapper004_Init, 0 }, + { "TFROM", 4, 0, Mapper004_Init, 0 }, + { "TGROM", 4, 0, Mapper004_Init, 0 }, + { "TKROM", 4, 0, Mapper004_Init, 0 }, + { "TLROM", 4, 0, Mapper004_Init, 0 }, + { "TSROM", 4, 0, Mapper004_Init, 0 }, + { "TVROM", 4, 0, Mapper004_Init, BMCFLAG_FORCE4 }, + { "TR1ROM", 4, 0, Mapper004_Init, BMCFLAG_FORCE4 }, + { "EKROM", 5, 0, EKROM_Init, 0 }, + { "ELROM", 5, 0, ELROM_Init, 0 }, + { "ETROM", 5, 0, ETROM_Init, 0 }, + { "EWROM", 5, 0, EWROM_Init, 0 }, + { "ANROM", 7, 0, Mapper007_Init, 0 }, + { "CPROM", 13, 0, Mapper013_Init, BMCFLAG_16KCHRR }, + { "SL1632", 14, 0, Mapper014_Init, 0 }, + { "CC-21", 27, 0, Mapper027_Init, 0 }, + { "RET-CUFROM", 29, 0, Mapper029_Init, BMCFLAG_32KCHRR }, + { "UNROM-512-8", 30, 0, Mapper030_Init, 0 }, + { "UNROM-512-16", 30, 0, Mapper030_Init, BMCFLAG_16KCHRR }, + { "UNROM-512-32", 30, 0, Mapper030_Init, BMCFLAG_32KCHRR }, + { "SC-127", 35, 0, Mapper035_Init, 0 }, + { "AC08", 42, 0, Mapper042_Init, 0 }, + { "SuperHIK8in1", 45, 0, Mapper045_Init, 0 }, + { "STREETFIGTER-GAME4IN1", 49, 0, Mapper049_Init, 0 }, /* mapper 49? submapper 1*/ + { "Supervision16in1", 53, 0, Mapper053_Init, 0 }, + { "MARIO1-MALEE2", 55, 0, Mapper055_Init, 0 }, + { "GK-192", 58, 0, Mapper058_Init, 0 }, + { "D1038", 59, 0, Mapper059_Init, 0 }, + { "T3H53", 59, 0, Mapper059_Init, 0 }, + { "MHROM", 66, 0, Mapper066_Init, 0 }, + { "NTBROM", 68, 0, Mapper068_Init, 0 }, + { "SA-016-1M", 79, 0, Mapper079_Init, 0 }, + { "VRC7", 85, 0, Mapper085_Init, 0 }, + { "TEK90", 90, 0, Mapper090_Init, 0 }, + { "SUNSOFT_UNROM", 93, 0, Mapper093_Init, 0 }, /* fix me, real pcb name, real pcb type */ + { "BB", 108, 0, Mapper108_Init, 0 }, + { "LE05", 108, 0, Mapper108_Init, 0 }, + { "SL12", 116, 0, Mapper116_Init, 0 }, + { "TKSROM", 118, 0, Mapper118_Init, 0 }, + { "TLSROM", 118, 0, Mapper118_Init, 0 }, + { "TQROM", 119, 0, Mapper119_Init, 0 }, + { "H2288", 123, 0, Mapper123_Init, 0 }, + { "LH32", 125, 0, Mapper125_Init, 0 }, + { "22211", 132, 0, Mapper132_Init, 0 }, + { "SA-72008", 133, 0, Mapper133_Init, 0 }, + { "T4A54A", 134, 0, Mapper134_Init, 0 }, + { "WX-KB4K", 134, 0, Mapper134_Init, 0 }, + { "SA-002", 136, 0, Mapper136_Init, 0 }, + { "Sachen-8259D", 137, 0, Mapper137_Init, 0 }, + { "Sachen-8259B", 138, 0, Mapper138_Init, 0 }, + { "Sachen-8259C", 139, 0, Mapper139_Init, 0 }, + { "Sachen-8259A", 141, 0, Mapper141_Init, 0 }, + { "KS7032", 142, 0, Mapper142_Init, 0 }, + { "SA-NROM", 143, 0, Mapper143_Init, 0 }, + { "SA-72007", 145, 0, Mapper145_Init, 0 }, + { "TC-U01-1.5M", 147, 0, Mapper147_Init, 0 }, + { "SA-0037", 148, 0, Mapper148_Init, 0 }, + { "SA-0036", 149, 0, Mapper149_Init, 0 }, + { "Sachen-74LS374N", 150, 0, Mapper150_Init, 0 }, + { "Sachen-74LS374NA", 150, 0, Mapper150_Init, 0 }, /* seems to be custom mapper */ + /* { "SA-009", 160, 0, Mapper160_Init, 0 }, */ + { "FS304", 162, 0, Mapper162_Init, 0 }, + { "FK23C", 176, 0, BMCFK23C_Init, BMCFLAG_256KCHRR }, + { "FK23CA", 176, 0, BMCFK23CA_Init, BMCFLAG_256KCHRR }, + { "Super24in1SC03", 176, 0, Super24_Init, 0 }, + { "WAIXING-FS005", 176, 0, WAIXINGFS005_Init, 0 }, + { "NovelDiamond9999999in1", 201, 0, Mapper201_Init, 0 }, + { "JC-016-2", 205, 0, Mapper205_Init, 0 }, + { "8237", 215, 0, Mapper215_Init, 0 }, + { "8237A", 215, 0, Mapper215_Init, 0 }, /* m215 sub 1*/ + { "N625092", 221, 0, Mapper221_Init, 0 }, + { "Ghostbusters63in1", 226, 0, Mapper226_Init, 0 }, + { "G631", 226, 0, Mapper226_Init, 0 }, /* duplicate, probably wrong name */ + { "WAIXING-FW01", 227, 0, Mapper227_Init, 0 }, + { "42in1ResetSwitch", 233, 0, Mapper233_Init, 0 }, + { "70in1", 236, 0, Mapper236_Init, 0 }, + { "70in1B", 236, 0, Mapper236_Init, 0 }, + { "603-5052", 238, 0, Mapper238_Init, 0 }, + { "43272", 242, 0, Mapper242_Init, 0 }, + { "DANCE", 256, 0, Mapper256_Init, 0 }, + { "OneBus", 256, 0, Mapper256_Init, 0 }, + { "PEC-586", 257, 0, Mapper257_Init, 0 }, + { "158B", 258, 0, Mapper215_Init, 0 }, + { "F-15", 259, 0, Mapper259_Init, 0 }, + { "HPxx", 260, 0, Mapper260_Init, 0 }, + { "HP2018-A", 260, 0, Mapper260_Init, 0 }, + { "810544-C-A1", 261, 0, Mapper261_Init, 0 }, + { "SHERO", 262, 0, Mapper262_Init, BMCFLAG_FORCE4 }, + { "KOF97", 263, 0, Mapper263_Init, 0 }, + { "YOKO", 264, 0, Mapper264_Init, 0 }, + { "T-262", 265, 0, Mapper265_Init, 0 }, + { "CITYFIGHT", 266, 0, Mapper266_Init, 0 }, + { "COOLBOY", 268, 0, COOLBOY_Init, BMCFLAG_256KCHRR }, + { "MINDKIDS", 224, 0, MINDKIDS_Init, BMCFLAG_256KCHRR }, + { "22026", 271, 0, Mapper271_Init, 0 }, + { "80013-B", 274, 0, Mapper274_Init, 0 }, + { "GS-2004", 283, 0, Mapper283_Init, 0 }, + { "DRIPGAME", 284, 0, Mapper284_Init, 0 }, + { "GS-2013", 283, 0, Mapper283_Init, 0 }, + { "A65AS", 285, 0, Mapper285_Init, 0 }, + { "BS-5", 286, 0, Mapper286_Init, 0 }, + { "411120-C", 287, 0, Mapper287_Init, 0 }, + { "K-3088", 287, 0, Mapper287_Init, 0 }, + { "60311C", 289, 0, Mapper289_Init, 0 }, + { "NTD-03", 290, 0, Mapper290_Init, 0 }, + { "DRAGONFIGHTER", 292, 0, Mapper292_Init, 0 }, + { "13in1JY110", 295, 0, Mapper295_Init, 0 }, + { "TF1201", 298, 0, Mapper298_Init, 0 }, + { "11160", 299, 0, Mapper299_Init, 0 }, + { "190in1", 300, 0, Mapper300_Init, 0 }, + { "8157", 301, 0, Mapper301_Init, 0 }, + { "KS7057", 302, 0, Mapper302_Init, 0 }, + { "KS7017", 303, 0, Mapper303_Init, 0 }, + { "SMB2J", 304, 0, Mapper304_Init, 0 }, + { "KS7031", 305, 0, Mapper305_Init, 0 }, + { "KS7016", 306, 0, Mapper306_Init, 0 }, + { "KS7037", 307, 0, Mapper307_Init, 0 }, + { "TH2131-1", 308, 0, Mapper308_Init, 0 }, + { "LH51", 309, 0, Mapper309_Init, 0 }, + { "KS7013B", 312, 0, Mapper312_Init, 0 }, + { "RESET-TXROM", 313, 0, Mapper313_Init, 0 }, + { "64in1NoRepeat", 314, 0, Mapper314_Init, 0 }, + { "830134C", 315, 0, Mapper315_Init, 0 }, + { "HP898F", 319, 0, Mapper319_Init, 0 }, /* UNIF implementation of mapper 319 */ + { "830425C-4391T", 320, 0, Mapper320_Init, 0 }, + { "K-3033", 322, 0, Mapper322_Init, 0 }, + { "FARID_SLROM_8-IN-1", 323, 0, Mapper323_Init, 0 }, + { "FARID_UNROM_8-IN-1", 324, 0, Mapper324_Init, 0 }, + { "MALISB", 325, 0, Mapper325_Init, 0 }, + { "10-24-C-A1", 327, 0, Mapper327_Init, 0 }, + { "RT-01", 328, 0, Mapper328_Init, 0 }, + { "EDU2000", 329, 0, Mapper329_Init, 0 }, + { "12-IN-1", 331, 0, Mapper331_Init, 0 }, + { "WS", 332, 0, Mapper332_Init, 0 }, + { "8-IN-1", 333, 0, Mapper333_Init, 0 }, + { "NEWSTAR-GRM070-8IN1", 333, 0, Mapper333_Init, 0 }, + { "CTC-09", 335, 0, Mapper335_Init, 0 }, + { "K-3046", 336, 0, Mapper336_Init, 0 }, + { "CTC-12IN1", 337, 0, Mapper337_Init, 0 }, + { "SA005-A", 338, 0, Mapper338_Init, 0 }, + { "K-3006", 339, 0, Mapper339_Init, 0 }, + { "K-3036", 340, 0, Mapper340_Init, 0 }, + { "TJ-03", 341, 0, Mapper341_Init, 0 }, + { "COOLGIRL", 342, 0, Mapper342_Init, BMCFLAG_512KCHRR }, + { "RESETNROM-XIN1", 343, 0, Mapper343_Init, 0 }, + { "GN-26", 344, 0, Mapper344_Init, 0 }, + { "L6IN1", 345, 0, Mapper345_Init, 0 }, + { "KS7012", 346, 0, Mapper346_Init, 0 }, + { "KS7030", 347, 0, Mapper347_Init, 0 }, + { "830118C", 348, 0, Mapper348_Init, 0 }, + { "G-146", 349, 0, Mapper349_Init, 0 }, + { "891227", 350, 0, Mapper350_Init, 0 }, + { "KS106C", 352, 0, Mapper352_Init, 0 }, + { "3D-BLOCK", 355, 0, UNL3DBlock_Init, 0 }, + { "SB-5013", 359, 0, Mapper359_Init, 0 }, + { "N49C-300", 369, 0, Mapper369_Init, 0 }, + { "830752C", 396, 0, Mapper396_Init, 0 }, + { "GOLDEN-16IN1-SPC001", 396, 0, Mapper396_Init, 0 }, + { "BS-400R", 422, 0, Mapper422_Init, 0 }, + { "BS-4040R", 422, 0, Mapper422_Init, 0 }, + { "AB-G1L", 428, 0, Mapper428_Init, 0 }, + { "WELL-NO-DG450", 428, 0, Mapper428_Init, 0 }, + { "TF2740", 428, 0, Mapper428_Init, 0 }, + { "S-2009", 434, 0, Mapper434_Init, 0 }, + { "K-3010", 438, 0, Mapper438_Init, 0 }, + { "K-3071", 438, 0, Mapper438_Init, 0 }, + { "DS-07", 439, 0, Mapper439_Init, 0 }, + { "K86B", 439, 0, Mapper439_Init, 0 }, + { "BS-110", 444, 0, Mapper444_Init, 0 }, /* Due to a mix-up, UNIF MAPR BMC-BS-110 is actually the NC7000M PCB and refers to NES 2.0 Mapper 444 instead. */ + { "DG574B", 445, 0, Mapper445_Init, 0 }, + { "SA-9602B", 513, 0, Mapper513_Init, BMCFLAG_32KCHRR }, + { "DANCE2000", 518, 0, Mapper518_Init, 0 }, + { "EH8813A", 519, 0, Mapper519_Init, 0 }, + { "DREAMTECH01", 521, 0, Mapper521_Init, 0 }, + { "LH10", 522, 0, Mapper522_Init, 0 }, + { "900218", 524, 0, Mapper524_Init, 0 }, + { "KS7021A", 525, 0, Mapper525_Init, 0 }, + { "BJ-56", 526, 0, Mapper526_Init, 0 }, + { "AX-40G", 527, 0, Mapper527_Init, 0 }, + { "831128C", 528, 0, Mapper528_Init, 0 }, + { "T-230", 529, 0, Mapper529_Init, 0 }, + { "AX5705", 530, 0, Mapper530_Init, 0 }, + { "LH53", 535, 0, Mapper535_Init, 0 }, + { "82112C", 540, 0, Mapper540_Init, 0 }, + { "KONAMI-QTAI", 547, 0, Mapper547_Init, 0 }, + + { "SSS-NROM-256", NO_INES, 0, SSSNROM_Init, 0 }, /* famicombox - cant find similar cart */ + { "T-227-1", NO_INES, 0, BMCT2271_Init, 0 }, /* cant find similar cart */ + { "Transformer", NO_INES, 0, Transformer_Init, 0 }, + { "81-01-31-C", NO_INES, 0, BMC810131C_Init, 0 }, /* might be mapper 327 with m118-like mirroring */ + { "KG256", NO_INES, 0, KG256_Init, 0 }, /* cant find similar cart */ + { "CHINA_ER_SAN2", NO_INES, 0, Mapper019_Init, 0 }, /* Needs more than just what mapper 19 can handle */ + + { NULL, NO_INES, 0, NULL, 0 } +}; static BFMAPPING bfunc[] = { { "CTRL", CTRL }, @@ -703,7 +944,7 @@ static int InitializeBoard(void) { mirrortodo = 4; MooMirroring(); - UNIFCart.mapper = bmap[x].ines_mapper; + UNIFCart.mapper = bmap[x].mapper; UNIFCart.submapper = submapper; GameInfo->cspecial = cspecial; diff --git a/src/unif.h b/src/unif.h index 353235aa6..927a647d8 100644 --- a/src/unif.h +++ b/src/unif.h @@ -99,7 +99,7 @@ void TQROM_Init(CartInfo *info); void TQROM_Init(CartInfo *info); void TSROM_Init(CartInfo *info); void Transformer_Init(CartInfo *info); -void UNL22211_Init(CartInfo *info); +/* void UNL22211_Init(CartInfo *info); m132 */ void UNL3DBlock_Init(CartInfo *info); void UNL43272_Init(CartInfo *info); void UNL6035052_Init(CartInfo *info); diff --git a/src/x6502.c b/src/x6502.c index b8bf2d95d..b80afa723 100644 --- a/src/x6502.c +++ b/src/x6502.c @@ -393,6 +393,10 @@ void FCEUI_GetIVectors(uint16 *reset, uint16 *irq, uint16 *nmi) { static int debugmode; #endif +void X6502_SetNewPC(uint16 newPC) { + X.newPC = newPC; +} + void X6502_Reset(void) { _IRQlow = FCEU_IQRESET; } @@ -418,6 +422,9 @@ void X6502_Power(void) { _S = 0xFD; timestamp = sound_timestamp = 0; X6502_Reset(); + if (X.newPC) { + X.PC = X.newPC; + } } #ifdef FCEUDEF_DEBUGGER diff --git a/src/x6502.h b/src/x6502.h index f4805440f..703b5006c 100644 --- a/src/x6502.h +++ b/src/x6502.h @@ -48,15 +48,24 @@ extern X6502 X; extern void FP_FASTAPASS(1) (*MapIRQHook)(int a); -#define NTSC_CPU (dendy ? 1773447.467 : 1789772.7272727272727272) -#define PAL_CPU 1662607.125 +/* 21.47~ MHz ÷ 12 = 1.789773 MHz */ +#define NTSC_CLOCK_SPEED 1789772.7272727272727272 + +/* 26.60~ MHz ÷ 16 = 1.662607 MHz */ +#define PAL_CLOCK_SPEED 1662607.125 + +/* 26.60~ MHz ÷ 15 = 1.773448 MHz */ +#define DENDY_CLOCK_SPEED 1773447.467 + +#define NTSC_CPU (dendy ? DENDY_CLOCK_SPEED : NTSC_CLOCK_SPEED) +#define PAL_CPU PAL_CLOCK_SPEED #define FCEU_IQEXT 0x001 #define FCEU_IQEXT2 0x002 /* ... */ #define FCEU_IQRESET 0x020 -#define FCEU_IQNMI2 0x040 /* Delayed NMI, gets converted to *_IQNMI */ -#define FCEU_IQNMI 0x080 +#define FCEU_IQNMI2 0x040 /* Delayed NMI, gets converted to *_IQNMI */ +#define FCEU_IQNMI 0x080 #define FCEU_IQDPCM 0x100 #define FCEU_IQFCOUNT 0x200 #define FCEU_IQTEMP 0x800 @@ -74,4 +83,6 @@ void FASTAPASS(2) X6502_DMW(uint32 A, uint8 V); void FASTAPASS(1) X6502_IRQBegin(int w); void FASTAPASS(1) X6502_IRQEnd(int w); +void X6502_SetNewPC(uint16 newPC); + #endif diff --git a/src/x6502struct.h b/src/x6502struct.h index fec30032f..cacb899ee 100644 --- a/src/x6502struct.h +++ b/src/x6502struct.h @@ -6,6 +6,7 @@ typedef struct __X6502 { uint16 PC; /* I'll change this to uint32 later... */ /* I'll need to AND PC after increments to 0xFFFF */ /* when I do, though. Perhaps an IPC() macro? */ + uint16 newPC; /* used to override PC after at power on */ uint8 A, X, Y, S, P, mooPI; uint8 jammed; From 61fb08a8b7185edc52d331534862c8721d6da1e4 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 12:05:46 +0800 Subject: [PATCH 02/16] fds: Start using new fds expansion audio --- src/fds.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/fds.c b/src/fds.c index 196fbd043..171e46f07 100644 --- a/src/fds.c +++ b/src/fds.c @@ -38,6 +38,8 @@ #include "cart.h" #include "md5.h" +#include "mappers/sound/fdssound.h" + /* TODO: Add code to put a delay in between the time a disk is inserted * and the when it can be successfully read/written to. This should * prevent writes to wrong places OR add code to prevent disk ejects @@ -154,7 +156,27 @@ static void FDSInit(void) { IRQCount = IRQLatch = IRQa = 0; - FDSSoundReset(); + /* FDSSoundReset(); */ + + FDSSoundRegReset(); + FDSSound_SC(); + + SetReadHandler(0x4040, 0x407F, FDSWaveRead); + SetReadHandler(0x4090, 0x4090, FDSEnvVolumeRead); + SetReadHandler(0x4092, 0x4092, FDSEnvModRead); + + SetWriteHandler(0x4040, 0x407F, FDSWaveWrite); + SetWriteHandler(0x4080, 0x4080, FDSSReg0Write); + SetWriteHandler(0x4082, 0x4082, FDSSReg1Write); + SetWriteHandler(0x4083, 0x4083, FDSSReg2Write); + SetWriteHandler(0x4084, 0x4084, FDSSReg3Write); + SetWriteHandler(0x4085, 0x4085, FDSSReg4Write); + SetWriteHandler(0x4086, 0x4086, FDSSReg5Write); + SetWriteHandler(0x4087, 0x4087, FDSSReg6Write); + SetWriteHandler(0x4088, 0x4088, FDSSReg7Write); + SetWriteHandler(0x4089, 0x4089, FDSSReg8Write); + SetWriteHandler(0x408A, 0x408A, FDSSReg9Write); + InDisk = 0; SelectDisk = 0; @@ -691,7 +713,7 @@ int FDSLoad(const char *name, FCEUFILE *fp) { InDisk = 255; ResetExState(PreSave, PostSave); - FDSSoundStateAdd(); + /* FDSSoundStateAdd(); */ for (x = 0; x < TotalSides; x++) { char temp[5]; @@ -723,6 +745,8 @@ int FDSLoad(const char *name, FCEUFILE *fp) { AddExState(&mapperFDS_diskaddr, 2 | FCEUSTATE_RLSB, 1, "DADR"); AddExState(&mapperFDS_diskaccess, 1, 0, "DACC"); + FDSSound_AddStateInfo(); + CHRRAMSize = 8192; CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1); From 8b25312511b847b7210099bbb49ab661d1be416b Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 12:57:14 +0800 Subject: [PATCH 03/16] Fix PRGROM/CHRROM size --- src/ines.c | 6 ------ src/mappers/hw/mmc3.c | 2 +- src/mappers/hw/mmc6.c | 2 +- src/mappers/hw/vrc24.c | 2 +- src/mappers/mapinc.h | 20 ++++++++++---------- src/mappers/mapper000.c | 4 ++-- src/mappers/mapper006.c | 26 +++++++++++++------------- src/mappers/mapper030.c | 2 +- src/mappers/mapper034.c | 4 ++-- src/mappers/mapper042.c | 4 ++-- src/mappers/mapper045.c | 2 +- src/mappers/mapper051.c | 2 +- src/mappers/mapper052.c | 2 +- src/mappers/mapper083.c | 4 ++-- src/mappers/mapper100.c | 2 +- src/mappers/mapper108.c | 6 +++--- src/mappers/mapper111.c | 2 +- src/mappers/mapper116.c | 2 +- src/mappers/mapper121.c | 2 +- src/mappers/mapper141.c | 2 +- src/mappers/mapper163.c | 2 +- src/mappers/mapper173.c | 2 +- src/mappers/mapper176.c | 24 ++++++++++++------------ src/mappers/mapper215.c | 2 +- src/mappers/mapper226.c | 2 +- src/mappers/mapper228.c | 17 ++++++++--------- src/mappers/mapper235.c | 2 +- src/mappers/mapper236.c | 2 +- src/mappers/mapper242.c | 4 ++-- src/mappers/mapper268.c | 2 +- src/mappers/mapper269.c | 12 ++++++------ src/mappers/mapper283.c | 2 +- src/mappers/mapper287.c | 2 +- src/mappers/mapper342.c | 2 +- src/mappers/mapper351.c | 12 ++++++------ src/mappers/mapper355.c | 2 +- src/mappers/mapper359.c | 2 +- src/mappers/mapper413.c | 4 ++-- src/mappers/mapper432.c | 4 ++-- src/mappers/mapper513.c | 2 +- src/mappers/mapper558.c | 2 +- src/mappers/mapper561.c | 37 ++++++++++++++++++------------------- src/mappers/mapper562.c | 16 ++++++++-------- 43 files changed, 124 insertions(+), 132 deletions(-) diff --git a/src/ines.c b/src/ines.c index df3462710..5aa2aa566 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1412,10 +1412,8 @@ int iNESLoad(const char *name, FCEUFILE *fp) { const char *tv_region[] = { "NTSC", "PAL", "Multi-region", "Dendy" }; struct md5_context md5; -#ifdef DEBUG char* mappername = NULL; uint32 mappertest = 0; -#endif uint64 filesize = FCEU_fgetsize(fp); /* size of file including header */ uint64 romSize = 0; /* size of PRG + CHR rom */ /* used for malloc and cart mapping */ @@ -1509,7 +1507,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) memcpy(&GameInfo->MD5, &iNESCart.MD5, sizeof(iNESCart.MD5)); -#ifdef DEBUG mappername = "Not Listed"; for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) @@ -1520,7 +1517,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) break; } } -#endif if (iNESCart.iNES2 == 0) { if (strstr(name, "(E)") || strstr(name, "(e)") || @@ -1538,7 +1534,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) } } -#ifdef DEBUG FCEU_printf(" PRG-ROM CRC32: 0x%08X\n", iNESCart.PRGCRC32); FCEU_printf(" PRG+CHR CRC32: 0x%08X\n", iNESCart.CRC32); FCEU_printf(" PRG+CHR MD5: 0x%s\n", md5_asciistr(iNESCart.MD5)); @@ -1572,7 +1567,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) } } } -#endif ResetCartMapping(); ResetExState(0, 0); diff --git a/src/mappers/hw/mmc3.c b/src/mappers/hw/mmc3.c index 5cc2acf8b..a32a099ad 100644 --- a/src/mappers/hw/mmc3.c +++ b/src/mappers/hw/mmc3.c @@ -271,7 +271,7 @@ static void StateRestore(int version) { } void MMC3_Power(void) { - if (!CHR_ROM_SIZE_8K) { + if (!CHR_ROM_SIZE) { setchr8(0); } diff --git a/src/mappers/hw/mmc6.c b/src/mappers/hw/mmc6.c index d9b2848ca..7382b56e9 100644 --- a/src/mappers/hw/mmc6.c +++ b/src/mappers/hw/mmc6.c @@ -239,7 +239,7 @@ static void StateRestore(int version) { } static void MMC6_Power(void) { - if (!CHR_ROM_SIZE_8K) { + if (!CHR_ROM_SIZE) { setchr8(0); } diff --git a/src/mappers/hw/vrc24.c b/src/mappers/hw/vrc24.c index 8a2791f9a..ba5216eb6 100644 --- a/src/mappers/hw/vrc24.c +++ b/src/mappers/hw/vrc24.c @@ -220,7 +220,7 @@ void VRC24_Power(void) { SetWriteHandler(0x6000, 0x6FFF, VRC24LatchWrite); } - if (!CHR_ROM_SIZE_8K) { + if (!CHR_ROM_SIZE) { setchr8(0); } } diff --git a/src/mappers/mapinc.h b/src/mappers/mapinc.h index 7423f8b7e..ce1b5067b 100644 --- a/src/mappers/mapinc.h +++ b/src/mappers/mapinc.h @@ -28,19 +28,19 @@ extern uint32 miscROMSIZE; #define CPU_OPENBUS X.DB -#define PRG_PAGE_SIZE (16 * 1024) -#define CHR_PAGE_SIZE (8 * 1024) +#define PRG_PAGE_SIZE (16 * 1024) +#define CHR_PAGE_SIZE ( 8 * 1024) -#define PRG_ROM_DATA ROM -#define PRG_ROM_SIZE_16K ROM_size +#define PRG_ROM_PTR ROM +#define PRG_ROM_SIZE (ROM_size * PRG_PAGE_SIZE) -#define CHR_ROM_DATA VROM -#define CHR_ROM_SIZE_8K VROM_size +#define CHR_ROM_PTR VROM +#define CHR_ROM_SIZE (VROM_size * CHR_PAGE_SIZE) -#define PRG_BANK_COUNT(x) ((PRG_ROM_SIZE_16K * PRG_PAGE_SIZE) / ((x) * 1024)) -#define CHR_BANK_COUNT(x) ((CHR_ROM_SIZE_8K * CHR_PAGE_SIZE) / ((x) * 1024)) +#define PRG_BANK_COUNT(x) (PRG_ROM_SIZE / ((x) * 1024)) +#define CHR_BANK_COUNT(x) (CHR_ROM_SIZE / ((x) * 1024)) -#define MISC_ROM_DATA miscROM -#define MISC_ROM_SIZE miscROMSIZE +#define MISC_ROM_PTR miscROM +#define MISC_ROM_SIZE miscROMSIZE #endif /* _MAPINC_H */ diff --git a/src/mappers/mapper000.c b/src/mappers/mapper000.c index 6b031dabc..82f210eec 100644 --- a/src/mappers/mapper000.c +++ b/src/mappers/mapper000.c @@ -25,7 +25,7 @@ static void NROMClose(void) { } static void NROMPower(void) { - if (PRG_ROM_SIZE_16K == (48 * 1024)) { /* NROM-368 */ + if (PRG_ROM_SIZE == (48 * 1024)) { /* NROM-368 */ setprg16(0x4000, 0); setprg16(0x8000, 1); setprg16(0xC000, 2); @@ -66,7 +66,7 @@ void Mapper000_Init(CartInfo *info) { } } - if ((info->CRC32 == 0x4233B70E) || ((info->PRGCRC32 == 0x17E013A2) && CHR_ROM_SIZE_8K)) { + if ((info->CRC32 == 0x4233B70E) || ((info->PRGCRC32 == 0x17E013A2) && CHR_ROM_SIZE)) { /* BADDUMP: A variant of Wild Ball with chrrom when its suppose to use chrram */ SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 1); } diff --git a/src/mappers/mapper006.c b/src/mappers/mapper006.c index 7e9f62c14..ff3f5c85b 100644 --- a/src/mappers/mapper006.c +++ b/src/mappers/mapper006.c @@ -310,7 +310,7 @@ static void SetTrainer(void) { iNESCart.submapper << 8 | 0x5C00; for (i = 0; i < (int)MISC_ROM_SIZE; i++) { - PRGPAGE_DMW((trainerAddr & 0x7F00) + i, MISC_ROM_DATA[i]); + PRGPAGE_DMW((trainerAddr & 0x7F00) + i, MISC_ROM_PTR[i]); } X6502_SetNewPC((iNESCart.mapper == 17) ? trainerAddr : 0x5000); @@ -452,26 +452,26 @@ void Mapper006_Init(CartInfo *info) { prg_size_8K = PRG_BANK_COUNT(8); - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { if (info->mapper == 12) { int i; - size_t ssize; + size_t ssize, prgsize; - PRG_ROM_SIZE_16K = (512 * 1024); - PRG_ROM_DATA = realloc(PRG_ROM_DATA, PRG_ROM_SIZE_16K); - for (i = 0; i < ((CHR_ROM_SIZE_8K < (256 * 1024)) ? CHR_ROM_SIZE_8K : (256 * 1024)); i++) { - PRG_ROM_DATA[(256 * 1024) + i] = CHR_ROM_DATA[i]; + prgsize = 512 * 1024; + PRG_ROM_PTR = realloc(PRG_ROM_PTR, prgsize); + for (i = 0; i < ((CHR_ROM_SIZE < (256 * 1024)) ? CHR_ROM_SIZE : (256 * 1024)); i++) { + PRG_ROM_PTR[(256 * 1024) + i] = CHR_ROM_PTR[i]; } - SetupCartPRGMapping(0, PRG_ROM_DATA, PRG_ROM_SIZE_16K, TRUE); + SetupCartPRGMapping(0, PRG_ROM_PTR, prgsize, TRUE); - memset(CHR_ROM_DATA, 0, CHR_ROM_SIZE_8K); + memset(CHR_ROM_PTR, 0, CHR_ROM_SIZE); ssize = info->CHRRamSize ? info->CHRRamSize : (32 * 1024); - SetupCartCHRMapping(0, CHR_ROM_DATA, ssize, TRUE); - AddExState(CHR_ROM_DATA, ssize, 0, "CHRR"); - CHR_ROM_SIZE_8K = 0; + SetupCartCHRMapping(0, CHR_ROM_PTR, ssize, TRUE); + AddExState(CHR_ROM_PTR, ssize, 0, "CHRR"); + VROM_size = 0; } else { SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], TRUE); - AddExState(CHR_ROM_DATA, CHR_ROM_SIZE_8K, 0, "CHRR"); + AddExState(CHR_ROM_PTR, CHR_ROM_SIZE, 0, "CHRR"); } } diff --git a/src/mappers/mapper030.c b/src/mappers/mapper030.c index 8014966e1..cbfb7495c 100644 --- a/src/mappers/mapper030.c +++ b/src/mappers/mapper030.c @@ -116,7 +116,7 @@ void Mapper030_Init(CartInfo *info) { SetupCartMirroring(MI_0, 0, NULL); break; case 3: /* hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical) */ - SetupCartMirroring(4, 1, CHR_ROM_DATA + (info->CHRRamSize - 8192)); + SetupCartMirroring(4, 1, CHR_ROM_PTR + (info->CHRRamSize - 8192)); break; } } diff --git a/src/mappers/mapper034.c b/src/mappers/mapper034.c index 472a3f416..2695d12c4 100644 --- a/src/mappers/mapper034.c +++ b/src/mappers/mapper034.c @@ -123,11 +123,11 @@ void Mapper034_Init(CartInfo *info) { type = M034_NESTICLE; WSync = Sync_Nesticle; info->Power = M034Power_Nesticle; - } else if ((info->submapper == 1) || ((info->submapper != 2) && CHR_ROM_SIZE_8K)) { + } else if ((info->submapper == 1) || ((info->submapper != 2) && CHR_ROM_SIZE)) { type = M034_NINA001; WSync = Sync_NINA001; info->Power = M034Power_NINA001; - } else if ((info->submapper == 2) || ((info->submapper != 1) && !CHR_ROM_SIZE_8K)) { + } else if ((info->submapper == 2) || ((info->submapper != 1) && !CHR_ROM_SIZE)) { type = M034_BNROM; Latch_Init(info, Sync_BNROM, NULL, FALSE, TRUE); info->Reset = Latch_RegReset; diff --git a/src/mappers/mapper042.c b/src/mappers/mapper042.c index 147ac1e21..b4ba6bc90 100644 --- a/src/mappers/mapper042.c +++ b/src/mappers/mapper042.c @@ -166,11 +166,11 @@ static void StateRestore(int version) { void Mapper042_Init(CartInfo *info) { if (info->submapper == 0 || info-> submapper > 3) { - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { /* Ai Senshi Nicol, only cart with CHR-ROM, all others use CHR-RAM */ info->submapper = 1; } else { - if (PRG_ROM_SIZE_16K > (128 * 1024)) { + if (PRG_ROM_SIZE > (128 * 1024)) { /* Green Beret LH09 FDS Conversion can be 160K or 256K */ info->submapper = 2; } else { diff --git a/src/mappers/mapper045.c b/src/mappers/mapper045.c index 0bb22e3a6..0343082ef 100644 --- a/src/mappers/mapper045.c +++ b/src/mappers/mapper045.c @@ -33,7 +33,7 @@ static SFORMAT StateRegs[] = { }; static void M045CW(uint16 A, uint16 V) { - if (CHR_ROM_SIZE_8K || (iNESCart.CHRRamSize > 8192)) { + if (CHR_ROM_SIZE || (iNESCart.CHRRamSize > 8192)) { uint32 mask = 0xFF >> (~reg[2] & 0x0F); uint32 base = ((reg[2] << 4) & 0xF00) | reg[0]; diff --git a/src/mappers/mapper051.c b/src/mappers/mapper051.c index 550d5a28c..536007f4b 100644 --- a/src/mappers/mapper051.c +++ b/src/mappers/mapper051.c @@ -87,7 +87,7 @@ void Mapper051_Init(CartInfo *info) { AddExState(StateRegs, ~0, 0, NULL); GameStateRestore = StateRestore; - if ((CHR_ROM_SIZE_8K == 8192) && (info->CHRRamSize == 8192)) { + if ((CHR_ROM_SIZE == 8192) && (info->CHRRamSize == 8192)) { /* at least 1 variant has 8K CHR-ROM which should be treated as CHR-RAM */ SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 1); AddExState(CHRptr[0], CHRsize[0], 0, "CHRR"); diff --git a/src/mappers/mapper052.c b/src/mappers/mapper052.c index 1612b0ee7..af25c32ee 100644 --- a/src/mappers/mapper052.c +++ b/src/mappers/mapper052.c @@ -101,7 +101,7 @@ void Mapper052_Init(CartInfo *info) { iNESCart.CHRRamSize = 8192; } - if (CHR_ROM_SIZE_8K && iNESCart.CHRRamSize) { + if (CHR_ROM_SIZE && iNESCart.CHRRamSize) { CHRRAMSIZE = info->CHRRamSize ? info->CHRRamSize : 8192; CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); diff --git a/src/mappers/mapper083.c b/src/mappers/mapper083.c index bf833d4b2..e0da6b960 100644 --- a/src/mappers/mapper083.c +++ b/src/mappers/mapper083.c @@ -235,9 +235,9 @@ void Mapper083_Init(CartInfo *info) { AddExState(StateRegs, ~0, 0, NULL); if (!info->iNES2) { - if (CHR_ROM_SIZE_8K >= (1024 * 1024)) { + if (CHR_ROM_SIZE >= (1024 * 1024)) { info->submapper = 2; - } else if (CHR_ROM_SIZE_8K >= (512 * 1024)) { + } else if (CHR_ROM_SIZE >= (512 * 1024)) { info->submapper = 1; } } diff --git a/src/mappers/mapper100.c b/src/mappers/mapper100.c index 9faf64428..9a07fed29 100644 --- a/src/mappers/mapper100.c +++ b/src/mappers/mapper100.c @@ -151,7 +151,7 @@ static void M100Power(void) { SetWriteHandler(0x8000, 0x9FFF, M100WriteCMD); if (iNESCart.trainer && MISC_ROM_SIZE) { - if (MISC_ROM_DATA[0] == 0x4C) { + if (MISC_ROM_PTR[0] == 0x4C) { X6502_SetNewPC(0x7000); } } diff --git a/src/mappers/mapper108.c b/src/mappers/mapper108.c index 517b1c27a..c19852909 100644 --- a/src/mappers/mapper108.c +++ b/src/mappers/mapper108.c @@ -47,7 +47,7 @@ static void Sync(void) { setprg8(0x6000, reg); } setprg32(0x8000, ~0); - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { setchr8(reg); } else { setchr8(0); @@ -81,14 +81,14 @@ void Mapper108_Init(CartInfo *info) { AddExState(StateRegs, ~0, 0, NULL); if (!info->iNES2 || !info->submapper) { - if (!CHR_ROM_SIZE_8K) { + if (!CHR_ROM_SIZE) { if (info->mirror == MI_H) { info->submapper = 1; } else { info->submapper = 3; } } else { - if (CHR_ROM_SIZE_8K <= (32 * 1024)) { + if (CHR_ROM_SIZE <= (32 * 1024)) { info->submapper = 4; } else { info->submapper = 2; diff --git a/src/mappers/mapper111.c b/src/mappers/mapper111.c index 3ebf16806..b555733f3 100644 --- a/src/mappers/mapper111.c +++ b/src/mappers/mapper111.c @@ -145,7 +145,7 @@ static void StateRestore(int version) { void Mapper111_Init(CartInfo *info) { m111_mmc1 = FALSE; - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { /* Prior to the introduction of GTROM, Mapper 111 was assigned to a Chinese Fan Translation * of Ninja Ryukenden (Japanese Ninja Gaiden). This translation uses a non-serialized * version of MMC1 and supports 256KiB of CHR-ROM, whereas the official MMC1 is limited to diff --git a/src/mappers/mapper116.c b/src/mappers/mapper116.c index a1ceed70c..c6990b27d 100644 --- a/src/mappers/mapper116.c +++ b/src/mappers/mapper116.c @@ -202,7 +202,7 @@ void Mapper116_Init(CartInfo *info) { AddExState(StateRegs, ~0, 0, NULL); /* PRG 128K and CHR 128K is Huang-2 (iNESCart.submapper 2) */ - if ((info->submapper != 2) && (PRG_ROM_SIZE_16K == (128 * 1024)) && (CHR_ROM_SIZE_8K == (128 * 1024))) { + if ((info->submapper != 2) && (PRG_ROM_SIZE == (128 * 1024)) && (CHR_ROM_SIZE == (128 * 1024))) { info->submapper = 2; } } diff --git a/src/mappers/mapper121.c b/src/mappers/mapper121.c index e0f08d041..61a647f7d 100644 --- a/src/mappers/mapper121.c +++ b/src/mappers/mapper121.c @@ -45,7 +45,7 @@ static SFORMAT StateRegs[] = { }; static void M121CW(uint16 A, uint16 V) { - if (PRG_ROM_SIZE_16K > (256 * 1024)) { + if (PRG_ROM_SIZE > (256 * 1024)) { setchr1(A, ((reg & 0x80) << 1) | V); } else { if ((A & 0x1000) == (uint32)((mmc3.cmd & 0x80) << 5)){ diff --git a/src/mappers/mapper141.c b/src/mappers/mapper141.c index 8a271b7b3..270ad32f1 100644 --- a/src/mappers/mapper141.c +++ b/src/mappers/mapper141.c @@ -33,7 +33,7 @@ static SFORMAT StateRegs[] = { static void Sync(void) { setprg32(0x8000, reg[5]); - if (!CHR_ROM_SIZE_8K) { + if (!CHR_ROM_SIZE) { setchr8(0); } else { setchr2(0x0000, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 0] & 0x07)) << 1) | 0); diff --git a/src/mappers/mapper163.c b/src/mappers/mapper163.c index 08be1e076..1e12f3913 100644 --- a/src/mappers/mapper163.c +++ b/src/mappers/mapper163.c @@ -57,7 +57,7 @@ static DECLFW(writeReg) { uint8 index = (A >> 8) & 0x03; /* Swap bits of registers 0-2 again if the "swap bits" bit is set. Exclude register 2 on when PRG-ROM is 1 MiB. */ - if ((reg[3] & 0x01) && (index <= (PRG_ROM_SIZE_16K < (2024 * 1024)))) { + if ((reg[3] & 0x01) && (index <= (PRG_ROM_SIZE < (2024 * 1024)))) { V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); } diff --git a/src/mappers/mapper173.c b/src/mappers/mapper173.c index cf608d5fd..0aa493900 100644 --- a/src/mappers/mapper173.c +++ b/src/mappers/mapper173.c @@ -24,7 +24,7 @@ static void M173Sync(void) { setprg32(0x8000, 0); - if (CHR_ROM_SIZE_8K >= (16 * 1024)) { + if (CHR_ROM_SIZE >= (16 * 1024)) { setchr8(((txc.output & 0x01) | (txc.Y ? 0x02 : 0x00) | ((txc.output & 2) << 0x01))); } else { setchr8(0); diff --git a/src/mappers/mapper176.c b/src/mappers/mapper176.c index d470b7a91..883051a81 100644 --- a/src/mappers/mapper176.c +++ b/src/mappers/mapper176.c @@ -95,7 +95,7 @@ static void CHRWRAP(uint16 A, uint16 V) { uint8 bank = 0; /* some workaround for chr rom / ram access */ - if (!CHR_ROM_SIZE_8K) { + if (!CHR_ROM_SIZE) { /* CHR-RAM only */ bank = 0; } else if (CHRRAMSIZE) { @@ -484,7 +484,7 @@ void Mapper176_Init(CartInfo *info) { /* .NES file */ if (info->iNES2) { subType = info->submapper; after_power = subType != 2; /* FS005 never has DIP switches, the others may have one, so use the heuristic. */ - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; } WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; @@ -498,22 +498,22 @@ void Mapper176_Init(CartInfo *info) { /* .NES file */ /* Always enable WRAM for iNES-headered files */ WRAMSIZE = 8 * 1024; - if ((PRG_ROM_SIZE_16K == (1024 * 1024)) && (CHR_ROM_SIZE_8K == (1024 * 1024))) { + if ((PRG_ROM_SIZE == (1024 * 1024)) && (CHR_ROM_SIZE == (1024 * 1024))) { subType = 1; - } else if ((PRG_ROM_SIZE_16K == (256 * 1024)) && (CHR_ROM_SIZE_8K == (128 * 1024))) { + } else if ((PRG_ROM_SIZE == (256 * 1024)) && (CHR_ROM_SIZE == (128 * 1024))) { subType = 1; - } else if ((PRG_ROM_SIZE_16K == (128 * 1024)) && (CHR_ROM_SIZE_8K == (64 * 1024))) { + } else if ((PRG_ROM_SIZE == (128 * 1024)) && (CHR_ROM_SIZE == (64 * 1024))) { subType = 1; - } else if ((PRG_ROM_SIZE_16K >= (8192 * 1024)) && (CHR_ROM_SIZE_8K == (0 * 1024))) { + } else if ((PRG_ROM_SIZE >= (8192 * 1024)) && (CHR_ROM_SIZE == (0 * 1024))) { subType = 2; - } else if ((PRG_ROM_SIZE_16K == (4096 * 1024)) && (CHR_ROM_SIZE_8K == (0 * 1024))) { + } else if ((PRG_ROM_SIZE == (4096 * 1024)) && (CHR_ROM_SIZE == (0 * 1024))) { subType = 3; } /* Detect heuristically whether the address mask should be changed on every soft reset */ after_power = 1; - if (CHRRAMSIZE && !CHR_ROM_SIZE_8K) { + if (CHRRAMSIZE && !CHR_ROM_SIZE) { /* FIXME: CHR-RAM is already set in iNES mapper initializer when there is no CHR ROM present */ /* so avoid reallocation it. */ CHRRAMSIZE = 0; @@ -525,9 +525,9 @@ void Mapper176_Init(CartInfo *info) { /* .NES file */ /* UNIF FK23C. Also includes mislabelled WAIXING-FS005, recognizable by their PRG-ROM size. */ void BMCFK23C_Init(CartInfo *info) { - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { /* Rockman I-VI uses mixed chr rom/ram */ - if (PRG_ROM_SIZE_16K == (2048 * 1024) && CHR_ROM_SIZE_8K == (512 * 1024)) { + if (PRG_ROM_SIZE == (2048 * 1024) && CHR_ROM_SIZE == (512 * 1024)) { CHRRAMSIZE = 8 * 1024; } } @@ -535,7 +535,7 @@ void BMCFK23C_Init(CartInfo *info) { dipsw_enable = 0; after_power = 1; - subType = (PRG_ROM_SIZE_16K >= (4096 * 1024)) ? 2 : (PRG_ROM_SIZE_16K == (64 * 1024) && CHR_ROM_SIZE_8K == (128 * 1024)) ? 1 : 0; + subType = (PRG_ROM_SIZE >= (4096 * 1024)) ? 2 : (PRG_ROM_SIZE == (64 * 1024) && CHR_ROM_SIZE == (128 * 1024)) ? 1 : 0; if (subType == 2) { CHRRAMSIZE = 256 * 1024; } @@ -549,7 +549,7 @@ void BMCFK23CA_Init(CartInfo *info) { dipsw_enable = 0; after_power = 1; - subType = (PRG_ROM_SIZE_16K >= (2048 * 1024)) ? 2 : 1; + subType = (PRG_ROM_SIZE >= (2048 * 1024)) ? 2 : 1; if (subType == 2) { CHRRAMSIZE = 256 * 1024; } diff --git a/src/mappers/mapper215.c b/src/mappers/mapper215.c index 4fcfd258f..1328645b6 100644 --- a/src/mappers/mapper215.c +++ b/src/mappers/mapper215.c @@ -178,7 +178,7 @@ void Mapper215_Init(CartInfo *info) { AddExState(reg, 4, 0, "EXPR"); - if ((!info->iNES2) && (PRG_ROM_SIZE_16K >= (2048 * 1024))) { /* UNL-8237A */ + if ((!info->iNES2) && (PRG_ROM_SIZE >= (2048 * 1024))) { /* UNL-8237A */ info->submapper = 1; } } diff --git a/src/mappers/mapper226.c b/src/mappers/mapper226.c index 714c2efaa..c0e109505 100644 --- a/src/mappers/mapper226.c +++ b/src/mappers/mapper226.c @@ -40,7 +40,7 @@ static void Sync(void) { uint8 prg = reg[0] & 0x1F; /* 1536KiB PRG roms have different bank order */ - if ((PRG_ROM_SIZE_16K == (1536 * 1024)) && (base > 0)) { + if ((PRG_ROM_SIZE == (1536 * 1024)) && (base > 0)) { base = (base - 1); } diff --git a/src/mappers/mapper228.c b/src/mappers/mapper228.c index cc350dd04..5dc36df33 100644 --- a/src/mappers/mapper228.c +++ b/src/mappers/mapper228.c @@ -46,27 +46,26 @@ static void Sync(void) { void Mapper228_Init(CartInfo *info) { Latch_Init(info, Sync, NULL, FALSE, FALSE); - if (PRG_ROM_SIZE_16K == 0x180000) { + if (PRG_ROM_SIZE == 0x180000) { int i; size_t ssize = 0x200000; uint8 *tmp = (uint8 *)FCEU_malloc(ssize); - for (i = 0; i < (int)PRG_ROM_SIZE_16K; i++) { - tmp[i] = PRG_ROM_DATA[i]; + for (i = 0; i < (int)PRG_ROM_SIZE; i++) { + tmp[i] = PRG_ROM_PTR[i]; } for (i = 0x000000; i < 0x080000; i++) { tmp[0x180000 + i] = tmp[0x100000 + i]; tmp[0x100000 + i] = (i >> 8) & 0xFF; } - PRG_ROM_SIZE_16K = ssize; - if (PRG_ROM_DATA) FCEU_free(PRG_ROM_DATA); - PRG_ROM_DATA = (uint8 *)FCEU_malloc(ssize); - for (i = 0; i < (int)PRG_ROM_SIZE_16K; i++) { - PRG_ROM_DATA[i] = tmp[i]; + if (PRG_ROM_PTR) FCEU_free(PRG_ROM_PTR); + PRG_ROM_PTR = (uint8 *)FCEU_malloc(ssize); + for (i = 0; i < (int)ssize; i++) { + PRG_ROM_PTR[i] = tmp[i]; } FCEU_free(tmp); - SetupCartPRGMapping(0, PRG_ROM_DATA, PRG_ROM_SIZE_16K, 0); + SetupCartPRGMapping(0, PRG_ROM_PTR, ssize, 0); } } diff --git a/src/mappers/mapper235.c b/src/mappers/mapper235.c index 6a0284701..339ce377c 100644 --- a/src/mappers/mapper235.c +++ b/src/mappers/mapper235.c @@ -64,7 +64,7 @@ static DECLFR(M235Read) { } static void M235Reset(void) { - if (PRG_ROM_SIZE_16K & 0x20000) { + if (PRG_ROM_SIZE & 0x20000) { mode = (mode + 1) & 1; } Latch_RegReset(); diff --git a/src/mappers/mapper236.c b/src/mappers/mapper236.c index 456f00a66..c3b613e82 100644 --- a/src/mappers/mapper236.c +++ b/src/mappers/mapper236.c @@ -34,7 +34,7 @@ static void Sync(void) { uint8 prg; uint8 chr; - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { prg = reg[1] & 0x0F; chr = reg[0] & 0x0F; } else { diff --git a/src/mappers/mapper242.c b/src/mappers/mapper242.c index 4298516a9..4369db5d2 100644 --- a/src/mappers/mapper242.c +++ b/src/mappers/mapper242.c @@ -29,7 +29,7 @@ static void Sync(void) { uint32 cpuA14 = latch.addr & 0x01; uint32 nrom = (latch.addr >> 7) & 0x01; uint32 unrom = (latch.addr >> 9) & 0x01; - uint32 M242TwoChips = (PRG_ROM_SIZE_16K & 0x20000) && (PRG_ROM_SIZE_16K > 0x20000); + uint32 M242TwoChips = (PRG_ROM_SIZE & 0x20000) && (PRG_ROM_SIZE > 0x20000); if (M242TwoChips) { if (latch.addr & 0x600) { /* First chip */ @@ -46,7 +46,7 @@ static void Sync(void) { setchr8(0); setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); - if (!iNESCart.battery && (latch.addr & 0x80) == 0x80 && (PRG_ROM_SIZE_16K > (256 * 1024))) { + if (!iNESCart.battery && (latch.addr & 0x80) == 0x80 && (PRG_ROM_SIZE > (256 * 1024))) { /* CHR-RAM write protect hack, needed for some multicarts */ SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); } else { diff --git a/src/mappers/mapper268.c b/src/mappers/mapper268.c index 61b5db0c0..5020bcb32 100644 --- a/src/mappers/mapper268.c +++ b/src/mappers/mapper268.c @@ -178,7 +178,7 @@ static void Common_Init(CartInfo *info) { AddExState(reg, 8, 0, "EXPR"); - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; if (CHRRAMSIZE) { CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); diff --git a/src/mappers/mapper269.c b/src/mappers/mapper269.c index 291cb3a29..ddd344358 100644 --- a/src/mappers/mapper269.c +++ b/src/mappers/mapper269.c @@ -80,16 +80,16 @@ void Mapper269_Init(CartInfo *info) { AddExState(reg, 4, 0, "EXPR"); AddExState(&cmd, 1, 0, "CMD0"); - if (CHR_ROM_SIZE_8K == 0) { + if (CHR_ROM_SIZE == 0) { size_t i; - if (CHR_ROM_DATA) { - FCEU_free(CHR_ROM_DATA); + if (CHR_ROM_PTR) { + FCEU_free(CHR_ROM_PTR); } - CHR_ROM_DATA = (uint8*)FCEU_malloc(PRGsize[0]); + CHR_ROM_PTR = (uint8*)FCEU_malloc(PRGsize[0]); /* unscramble CHR data from PRG */ for (i = 0; i < PRGsize[0]; i++) { - CHR_ROM_DATA[i] = unscrambleCHR(PRG_ROM_DATA[i]); + CHR_ROM_PTR[i] = unscrambleCHR(PRG_ROM_PTR[i]); } - SetupCartCHRMapping(0, CHR_ROM_DATA, PRGsize[0], 0); + SetupCartCHRMapping(0, CHR_ROM_PTR, PRGsize[0], 0); } } diff --git a/src/mappers/mapper283.c b/src/mappers/mapper283.c index 9dee48607..9e8c02eb3 100644 --- a/src/mappers/mapper283.c +++ b/src/mappers/mapper283.c @@ -22,7 +22,7 @@ #include "latch.h" static void Sync(void) { - setprg8(0x6000, (PRG_ROM_SIZE_16K & 0x6000) ? 32 : 31); + setprg8(0x6000, (PRG_ROM_SIZE & 0x6000) ? 32 : 31); setprg32(0x8000, latch.data); setchr8(0); } diff --git a/src/mappers/mapper287.c b/src/mappers/mapper287.c index d074b9cff..4e84a63ba 100644 --- a/src/mappers/mapper287.c +++ b/src/mappers/mapper287.c @@ -53,7 +53,7 @@ static void M287CW(uint16 A, uint16 V) { } static void M287PW(uint16 A, uint16 V) { - uint16 mode = reg & ((dipsw && (PRG_ROM_SIZE_16K <= (512 * 1024))) ? 0x0C : 0x08); + uint16 mode = reg & ((dipsw && (PRG_ROM_SIZE <= (512 * 1024))) ? 0x0C : 0x08); uint16 base = reg & 0x07; if (mode) { diff --git a/src/mappers/mapper342.c b/src/mappers/mapper342.c index 48162fa02..1c2e9fc83 100644 --- a/src/mappers/mapper342.c +++ b/src/mappers/mapper342.c @@ -309,7 +309,7 @@ static void SyncCHR(void) { int chr_shift = ((mapper == 24) && (flags & 2)) ? 1 : 0; /* enable or disable writes to CHR RAM, setup CHR mask */ - SetupCartCHRMapping(0, CHR_ROM_DATA, ((((~chr_mask & 0x3F) + 1) * 0x2000 - 1) & (CHR_SIZE - 1)) + 1, can_write_chr); + SetupCartCHRMapping(0, CHR_ROM_PTR, ((((~chr_mask & 0x3F) + 1) * 0x2000 - 1) & (CHR_SIZE - 1)) + 1, can_write_chr); switch (chr_mode & 0x07) { default: diff --git a/src/mappers/mapper351.c b/src/mappers/mapper351.c index bab223783..5cc411f1a 100644 --- a/src/mappers/mapper351.c +++ b/src/mappers/mapper351.c @@ -256,14 +256,14 @@ void Mapper351_Init(CartInfo *info) { GameStateRestore = StateRestore; AddExState(stateRegs, ~0, 0, 0); - if (CHR_ROM_SIZE_8K) { - uint32 old_prg_size = PRG_ROM_SIZE_16K; + if (CHR_ROM_SIZE) { + uint32 new_prg_size = PRG_ROM_SIZE; /* This crazy thing can map CHR-ROM into CPU address space. Allocate a * combined PRG+CHR address space and treat it a second "chip". */ - PRG_ROM_SIZE_16K = old_prg_size + CHR_ROM_SIZE_8K; - PRG_ROM_DATA = (uint8 *)realloc(PRG_ROM_DATA, PRG_ROM_SIZE_16K); - memcpy(PRG_ROM_DATA + old_prg_size, CHR_ROM_DATA, CHR_ROM_SIZE_8K); - SetupCartPRGMapping(0, PRG_ROM_DATA, PRG_ROM_SIZE_16K, 0); + new_prg_size += CHR_ROM_SIZE; + PRG_ROM_PTR = (uint8 *)realloc(PRG_ROM_PTR, new_prg_size); + memcpy(PRG_ROM_PTR + new_prg_size, CHR_ROM_PTR, CHR_ROM_SIZE); + SetupCartPRGMapping(0, PRG_ROM_PTR, new_prg_size, 0); } if (CHRRAMSIZE) { diff --git a/src/mappers/mapper355.c b/src/mappers/mapper355.c index 33817dbc0..4750768d0 100644 --- a/src/mappers/mapper355.c +++ b/src/mappers/mapper355.c @@ -112,7 +112,7 @@ static void M555Close(void) { void Mapper355_Init(CartInfo *info) { if (MISC_ROM_SIZE && (MISC_ROM_SIZE == 1024)) { - eprom = MISC_ROM_DATA; + eprom = MISC_ROM_PTR; } else { if (info->CRC32 == 0x86DBA660) { /* 3D Block (Hwang Shinwei) [!].nes */ eprom = &eprom_3d_block[0]; diff --git a/src/mappers/mapper359.c b/src/mappers/mapper359.c index 096e7982d..a582fc7f9 100644 --- a/src/mappers/mapper359.c +++ b/src/mappers/mapper359.c @@ -69,7 +69,7 @@ static void Sync(void) { setprg8(0xC000, prgBase | (prg[2] & prgMask)); setprg8(0xE000, prgBase | ( ~0 & prgMask)); - if (!CHR_ROM_SIZE_8K) { + if (!CHR_ROM_SIZE) { setchr8(0); } else { if (iNESCart.mapper == 540) { diff --git a/src/mappers/mapper413.c b/src/mappers/mapper413.c index c9ec72832..0bb80c0dd 100644 --- a/src/mappers/mapper413.c +++ b/src/mappers/mapper413.c @@ -59,9 +59,9 @@ static DECLFR(M413ReadPCM) { return ret; } if (serialControl & 0x02) { - ret = MISC_ROM_DATA[serialAddress++ & (MISC_ROM_SIZE - 1)]; + ret = MISC_ROM_PTR[serialAddress++ & (MISC_ROM_SIZE - 1)]; } else { - ret = MISC_ROM_DATA[serialAddress & (MISC_ROM_SIZE - 1)]; + ret = MISC_ROM_PTR[serialAddress & (MISC_ROM_SIZE - 1)]; } laddr = A; lreset = timestampbase + timestamp; diff --git a/src/mappers/mapper432.c b/src/mappers/mapper432.c index 96bc096bc..7295bc89f 100644 --- a/src/mappers/mapper432.c +++ b/src/mappers/mapper432.c @@ -54,7 +54,7 @@ static void M432PW(uint16 A, uint16 V) { } static DECLFR(M432Read) { - if ((reg[0] & 0x01) || ((reg[1] & 0x20) && (PRG_ROM_SIZE_16K < (1024 * 1024)))) { + if ((reg[0] & 0x01) || ((reg[1] & 0x20) && (PRG_ROM_SIZE < (1024 * 1024)))) { return dipsw; } return CartBR(A); @@ -63,7 +63,7 @@ static DECLFR(M432Read) { static DECLFW(M432Write) { if (MMC3_WramIsWritable()) { reg[A & 0x01] = V; - if (!(A & 0x01) && !(V & 0x01) && (PRG_ROM_SIZE_16K < (1024 * 1024))) { + if (!(A & 0x01) && !(V & 0x01) && (PRG_ROM_SIZE < (1024 * 1024))) { reg[1] &= ~0x20; /* Writing 0 to register 0 clears register 1's DIP bit */ } MMC3_FixPRG(); diff --git a/src/mappers/mapper513.c b/src/mappers/mapper513.c index dffc90119..f12607bdf 100644 --- a/src/mappers/mapper513.c +++ b/src/mappers/mapper513.c @@ -78,7 +78,7 @@ void Mapper513_Init(CartInfo *info) { MMC3_pwrap = M513PW; MMC3_cwrap = M513CW; mmc3.opts |= 2; - info->SaveGame[0] = CHR_ROM_DATA; + info->SaveGame[0] = CHR_ROM_PTR; info->SaveGameLen[0] = info->CHRRamSaveSize; info->Power = M513Power; AddExState(®, 1, 0, "EXPR"); diff --git a/src/mappers/mapper558.c b/src/mappers/mapper558.c index 761ea7181..7e47d344b 100644 --- a/src/mappers/mapper558.c +++ b/src/mappers/mapper558.c @@ -80,7 +80,7 @@ static DECLFW(writeReg) { Sync(); break; case 0x5200: - if ((PRG_ROM_SIZE_16K != (1024 * 1024)) && !(reg[3] & 0x02)) { + if ((PRG_ROM_SIZE != (1024 * 1024)) && !(reg[3] & 0x02)) { V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); } reg[2] = V; diff --git a/src/mappers/mapper561.c b/src/mappers/mapper561.c index 91d6de993..9c3058623 100644 --- a/src/mappers/mapper561.c +++ b/src/mappers/mapper561.c @@ -200,14 +200,14 @@ static void M561Power(void) { uint16 trainerLoadAddr = 0x7000; uint16 trainerInitAddr = 0x7003; uint32 trainerSize = 512; - uint8 *trainerData = MISC_ROM_DATA; + uint8 *trainerData = MISC_ROM_PTR; int i; if (MISC_ROM_SIZE != 512) { - trainerLoadAddr = (MISC_ROM_DATA[1] << 8) | MISC_ROM_DATA[0]; - trainerInitAddr = (MISC_ROM_DATA[3] << 8) | MISC_ROM_DATA[2]; + trainerLoadAddr = (MISC_ROM_PTR[1] << 8) | MISC_ROM_PTR[0]; + trainerInitAddr = (MISC_ROM_PTR[3] << 8) | MISC_ROM_PTR[2]; trainerSize = MISC_ROM_SIZE - 4; - trainerData = MISC_ROM_DATA + 4; + trainerData = MISC_ROM_PTR + 4; } for (i = 0; i < MISC_ROM_SIZE; i++) { @@ -251,6 +251,7 @@ static void M561CPUIRQHook(int a) { void Mapper561_Init(CartInfo *info) { uint32 wramsize = info->PRGRamSize + info->PRGRamSaveSize; + int i, ssize = PRG_ROM_SIZE; info->Power = M561Power; info->Reset = M561Reset; @@ -265,30 +266,28 @@ void Mapper561_Init(CartInfo *info) { AddExState(WRAM, WRAMSIZE, 0, "WRAM"); } - if ((info->submapper == 3) && (PRG_ROM_SIZE_16K < (256 * 1024))) { - uint8 *tmp = (uint8 *)FCEU_malloc(PRG_ROM_SIZE_16K); - int i; + if ((info->submapper == 3) && (PRG_ROM_SIZE < (256 * 1024))) { + uint8 *tmp = (uint8 *)FCEU_malloc(PRG_ROM_SIZE); - for (i = 0; i < PRG_ROM_SIZE_16K; i++) { - tmp[i] = PRG_ROM_DATA[i]; + for (i = 0; i < ssize; i++) { + tmp[i] = PRG_ROM_PTR[i]; } - FCEU_free(PRG_ROM_DATA); - PRG_ROM_SIZE_16K = (256 * 1024); - PRG_ROM_DATA = (uint8 *)FCEU_malloc(PRG_ROM_SIZE_16K); - for (i = 0; i < PRG_ROM_SIZE_16K; i++) { - PRG_ROM_DATA[i] = tmp[i]; + ssize = (256 * 1024); + PRG_ROM_PTR = (uint8 *)realloc(PRG_ROM_PTR, ssize); + for (i = 0; i < ssize; i++) { + PRG_ROM_PTR[i] = tmp[i]; } FCEU_free(tmp); - SetupCartPRGMapping(0, PRG_ROM_DATA, PRG_ROM_SIZE_16K, FALSE); + SetupCartPRGMapping(0, PRG_ROM_PTR, ssize, FALSE); } - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { /* Game Doctor only used CHR RAM, but some .nes files has CHR ROM instead. */ /* Remap CHR as writable. */ - SetupCartCHRMapping(0, CHR_ROM_DATA, CHR_ROM_SIZE_8K, TRUE); - AddExState(CHR_ROM_DATA, CHR_ROM_SIZE_8K, 0, "CHRM"); + SetupCartCHRMapping(0, CHR_ROM_PTR, CHR_ROM_SIZE, TRUE); + AddExState(CHR_ROM_PTR, CHR_ROM_SIZE, 0, "CHRM"); } /* PRG memory can be writable, so add to states */ - AddExState(PRG_ROM_DATA, PRG_ROM_SIZE_16K, 0, "PRGM"); + AddExState(PRG_ROM_PTR, ssize, 0, "PRGM"); } diff --git a/src/mappers/mapper562.c b/src/mappers/mapper562.c index dcd044b3c..39f3752f4 100644 --- a/src/mappers/mapper562.c +++ b/src/mappers/mapper562.c @@ -498,14 +498,14 @@ static void M562Power(void) { uint16 trainerLoadAddr = 0x7000; uint16 trainerInitAddr = 0x7003; uint32 trainerSize = 512; - uint8 *trainerData = MISC_ROM_DATA; + uint8 *trainerData = MISC_ROM_PTR; int i; if (MISC_ROM_SIZE != 512) { - trainerLoadAddr = (MISC_ROM_DATA[1] << 8) | MISC_ROM_DATA[0]; - trainerInitAddr = (MISC_ROM_DATA[3] << 8) | MISC_ROM_DATA[2]; + trainerLoadAddr = (MISC_ROM_PTR[1] << 8) | MISC_ROM_PTR[0]; + trainerInitAddr = (MISC_ROM_PTR[3] << 8) | MISC_ROM_PTR[2]; trainerSize = MISC_ROM_SIZE - 4; - trainerData = MISC_ROM_DATA + 4; + trainerData = MISC_ROM_PTR + 4; FCEU_printf(" load addr : %04x\n", trainerLoadAddr); FCEU_printf(" init addr : %04x\n", trainerInitAddr); @@ -578,13 +578,13 @@ void Mapper562_Init(CartInfo *info) { AddExState(WRAM, WRAMSIZE, 0, "WRAM"); } - if (CHR_ROM_SIZE_8K) { + if (CHR_ROM_SIZE) { /* Game Doctor only used CHR RAM, but some .nes files has CHR ROM instead. */ /* Remap CHR as writable. */ - SetupCartCHRMapping(0, CHR_ROM_DATA, CHR_ROM_SIZE_8K, TRUE); - AddExState(CHR_ROM_DATA, CHR_ROM_SIZE_8K, 0, "CHRM"); + SetupCartCHRMapping(0, CHR_ROM_PTR, CHR_ROM_SIZE, TRUE); + AddExState(CHR_ROM_PTR, CHR_ROM_SIZE, 0, "CHRM"); } /* PRG memory can be writable, so add to states */ - AddExState(PRG_ROM_DATA, PRG_ROM_SIZE_16K, 0, "PRGM"); + AddExState(PRG_ROM_PTR, PRG_ROM_SIZE, 0, "PRGM"); } From 429ab0c07cbcc0f53e89f3f3b96a6c376081d3af Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 13:33:37 +0800 Subject: [PATCH 04/16] Add support for misc roms --- src/cart.h | 3 +- src/ines.c | 83 ++++++++++++++++++++++++++++------------- src/ines.h | 9 +++++ src/mappers/mapinc.h | 9 ----- src/mappers/mapper006.c | 2 +- src/mappers/mapper034.c | 2 +- src/mappers/mapper100.c | 2 +- 7 files changed, 71 insertions(+), 39 deletions(-) diff --git a/src/cart.h b/src/cart.h index 397610eb7..c76688702 100644 --- a/src/cart.h +++ b/src/cart.h @@ -36,7 +36,8 @@ typedef struct { * other code in the future. */ - int trainer; /* TODO */ + int HasTrainer; /* indicated the presence of trainer rom data */ + int HasMisc; /* indicated the presence of misc rom data */ } CartInfo; extern CartInfo iNESCart; diff --git a/src/ines.c b/src/ines.c index 5aa2aa566..2061005f5 100644 --- a/src/ines.c +++ b/src/ines.c @@ -43,7 +43,6 @@ extern SFORMAT FCEUVSUNI_STATEINFO[]; -uint8 *trainerpoo = NULL; uint8 *ROM = NULL; uint8 *VROM = NULL; uint8 *ExtraNTARAM = NULL; @@ -59,18 +58,18 @@ static int CHRRAMSize = -1; static int iNES_Init(int num); static DECLFR(TrainerRead) { - return(trainerpoo[A & 0x1FF]); + return(miscROM[A & 0x1FF]); } static void iNES_ExecPower() { if (iNESCart.Power) iNESCart.Power(); - if (trainerpoo) { + if (iNESCart.HasTrainer) { int x; for (x = 0; x < 512; x++) { - X6502_DMW(0x7000 + x, trainerpoo[x]); - if (X6502_DMR(0x7000 + x) != trainerpoo[x]) { + X6502_DMW(0x7000 + x, miscROM[x]); + if (X6502_DMR(0x7000 + x) != miscROM[x]) { SetReadHandler(0x7000, 0x71FF, TrainerRead); break; } @@ -78,6 +77,30 @@ static void iNES_ExecPower() { } } +static void Cleanup(void) +{ + if (ROM) + { + free(ROM); + ROM = NULL; + } + if (VROM) + { + free(VROM); + VROM = NULL; + } + if (miscROM) + { + free(miscROM); + miscROM = NULL; + } + if (ExtraNTARAM) + { + free(ExtraNTARAM); + ExtraNTARAM = NULL; + } +} + static void iNESGI(int h) { switch (h) { @@ -91,22 +114,7 @@ static void iNESGI(int h) { case GI_CLOSE: if (iNESCart.Close) iNESCart.Close(); - if (ROM) { - free(ROM); - ROM = NULL; - } - if (VROM) { - free(VROM); - VROM = NULL; - } - if (trainerpoo) { - free(trainerpoo); - trainerpoo = NULL; - } - if (ExtraNTARAM) { - free(ExtraNTARAM); - ExtraNTARAM = NULL; - } + Cleanup(); break; } } @@ -1394,6 +1402,7 @@ static void iNES_read_header_info(void) { iNESCart.battery = (head.ROM_type & 2) ? 1 : 0; iNESCart.mapper = iNES_get_mapper_id(); iNESCart.iNES2 = (head.ROM_type2 & 0x0C) == 0x08; + iNESCart.HasTrainer = (head.ROM_type & 0x04) != 0; if (iNESCart.iNES2) { @@ -1405,6 +1414,8 @@ static void iNES_read_header_info(void) { if (head.PRGRAM_size & 0xF0) iNESCart.PRGRamSaveSize = 64 << ((head.PRGRAM_size >> 4) & 0x0F); if (head.CHRRAM_size & 0x0F) iNESCart.CHRRamSize = 64 << ((head.CHRRAM_size >> 0) & 0x0F); if (head.CHRRAM_size & 0xF0) iNESCart.CHRRamSaveSize = 64 << ((head.CHRRAM_size >> 4) & 0x0F); + + iNESCart.HasMisc = head.MiscRoms & 0x03; } } @@ -1453,11 +1464,12 @@ int iNESLoad(const char *name, FCEUFILE *fp) filesize -= 16; /* remove header size from total size */ /* Trainer */ - if (head.ROM_type & 4) + if (iNESCart.HasTrainer) { - trainerpoo = (uint8*)FCEU_gmalloc(512); - FCEU_fread(trainerpoo, 512, 1, fp); - filesize -= 512; + miscROMSIZE = 512; + miscROM = (uint8*)FCEU_gmalloc(512); + FCEU_fread(miscROM, 512, 1, fp); + filesize -= miscROMSIZE; } iNESCart.PRGRomSize = ROM_size >=0xF00? (pow(2, head.ROM_size >>2)*((head.ROM_size &3)*2+1)): (ROM_size*0x4000); @@ -1495,6 +1507,18 @@ int iNESLoad(const char *name, FCEUFILE *fp) FCEU_fread(VROM, 1, iNESCart.CHRRomSize, fp); } + if (iNESCart.HasMisc) + { + miscROMSIZE = filesize - romSize; + if (!(miscROM = (uint8 *)FCEU_malloc(miscROMSIZE))) + { + Cleanup(); + return 0; + } + memset(miscROM, 0xFF, miscROMSIZE); + FCEU_fread(miscROM, 1, miscROMSIZE, fp); + } + iNESCart.PRGCRC32 = CalcCRC32(0, ROM, iNESCart.PRGRomSize); iNESCart.CHRCRC32 = CalcCRC32(0, VROM, iNESCart.CHRRomSize); iNESCart.CRC32 = CalcCRC32(iNESCart.PRGCRC32, VROM, iNESCart.CHRRomSize); @@ -1565,7 +1589,14 @@ int iNESLoad(const char *name, FCEUFILE *fp) FCEU_printf(" PRG RAM: %d KB\n", PRGRAM / 1024); FCEU_printf(" CHR RAM: %d KB\n", CHRRAM / 1024); } - } + } + if (!iNESCart.HasTrainer && miscROMSIZE) { + if (miscROMSIZE / 1024) { + FCEU_printf(" Misc ROM: %-6d KiB\n", miscROMSIZE / 1024); + } else { + FCEU_printf(" Misc ROM: %-6d bytes\n", miscROMSIZE); + } + } } ResetCartMapping(); diff --git a/src/ines.h b/src/ines.h index afd9d0361..93016b71c 100644 --- a/src/ines.h +++ b/src/ines.h @@ -44,6 +44,15 @@ extern uint32 ROM_size; /* prg size in 16K chunks */ extern uint32 VROM_size; /* chr size in 8K chunks */ extern iNES_HEADER head; +extern uint8 *WRAM; +extern uint32 WRAMSIZE; + +extern uint8 *CHRRAM; +extern uint32 CHRRAMSIZE; + +extern uint8 *miscROM; +extern uint32 miscROMSIZE; + void NSFVRC6_Init(void); void NSFMMC5_Init(void); void NSFAY_Init(void); diff --git a/src/mappers/mapinc.h b/src/mappers/mapinc.h index ce1b5067b..187e37863 100644 --- a/src/mappers/mapinc.h +++ b/src/mappers/mapinc.h @@ -17,15 +17,6 @@ #include #include -extern uint8 *WRAM; -extern uint32 WRAMSIZE; - -extern uint8 *CHRRAM; -extern uint32 CHRRAMSIZE; - -extern uint8 *miscROM; -extern uint32 miscROMSIZE; - #define CPU_OPENBUS X.DB #define PRG_PAGE_SIZE (16 * 1024) diff --git a/src/mappers/mapper006.c b/src/mappers/mapper006.c index ff3f5c85b..db8480929 100644 --- a/src/mappers/mapper006.c +++ b/src/mappers/mapper006.c @@ -301,7 +301,7 @@ static void SetTrainer(void) { PRGPAGE_DMW(0xFFFA, 0x32); PRGPAGE_DMW(0xFFFB, 0x50); } - if (iNESCart.trainer && WRAM) { + if (iNESCart.HasTrainer && WRAM) { int i; uint8 *trainerData = 0; uint16 trainerAddr = diff --git a/src/mappers/mapper034.c b/src/mappers/mapper034.c index 2695d12c4..fee51679c 100644 --- a/src/mappers/mapper034.c +++ b/src/mappers/mapper034.c @@ -119,7 +119,7 @@ static void StateRestore(int version) { } void Mapper034_Init(CartInfo *info) { - if (info->trainer) { + if (info->HasTrainer) { type = M034_NESTICLE; WSync = Sync_Nesticle; info->Power = M034Power_Nesticle; diff --git a/src/mappers/mapper100.c b/src/mappers/mapper100.c index 9a07fed29..b330e873d 100644 --- a/src/mappers/mapper100.c +++ b/src/mappers/mapper100.c @@ -150,7 +150,7 @@ static void M100Power(void) { MMC3_Power(); SetWriteHandler(0x8000, 0x9FFF, M100WriteCMD); - if (iNESCart.trainer && MISC_ROM_SIZE) { + if (iNESCart.HasTrainer && MISC_ROM_SIZE) { if (MISC_ROM_PTR[0] == 0x4C) { X6502_SetNewPC(0x7000); } From 0f8dab0235777564c507345548cccd2884349a2e Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 14:13:59 +0800 Subject: [PATCH 05/16] x6502: Allow different starting PC on PowerON Require for some mappers aka Game Doctor, etc --- src/x6502.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/x6502.c b/src/x6502.c index b80afa723..8d21d8659 100644 --- a/src/x6502.c +++ b/src/x6502.c @@ -398,7 +398,20 @@ void X6502_SetNewPC(uint16 newPC) { } void X6502_Reset(void) { - _IRQlow = FCEU_IQRESET; +#ifdef FCEUDEF_DEBUGGER +#define RdMem RdMemHook +#else +#define RdMem RdMemNorm +#endif + _S--; + _S--; + _S--; + _jammed = 0; + _P |= I_FLAG; + _PI = X.P; + _PC = RdMem(0xFFFC); + _PC |= RdMem(0xFFFD) << 8; +#undef RdMem } void X6502_Init(void) { @@ -419,11 +432,12 @@ void X6502_Init(void) { void X6502_Power(void) { _count = _tcount = _IRQlow = _PC = _A = _X = _Y = _P = _PI = _DB = _jammed = 0; - _S = 0xFD; + /*_S = 0xFD;*/ + _P = 0x34; timestamp = sound_timestamp = 0; X6502_Reset(); if (X.newPC) { - X.PC = X.newPC; + _PC = X.newPC; } } From 37c293be646126541fd864642c67d9b95234fdec Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 14:39:40 +0800 Subject: [PATCH 06/16] Add support for multi-channel audio for nsf/snfe --- src/fceu.c | 11 +++++++-- src/fceu.h | 10 --------- src/fds_apu.c | 8 +++---- src/filter.c | 8 +++++-- src/ines.c | 2 +- src/mappers/sound/dripsound.c | 10 ++++----- src/mappers/sound/fdssound.c | 8 +++---- src/mappers/sound/mmc5sound.c | 8 +++---- src/mappers/sound/n163sound.c | 8 +++---- src/mappers/sound/s5bsound.c | 16 ++++++------- src/mappers/sound/vrc6sound.c | 8 +++---- src/mappers/sound/vrc7sound.c | 8 +++---- src/sound.c | 42 +++++++++++++++++++++++++++-------- src/sound.h | 13 ++++++++++- 14 files changed, 98 insertions(+), 62 deletions(-) diff --git a/src/fceu.c b/src/fceu.c index 296011a2c..5026b086d 100644 --- a/src/fceu.c +++ b/src/fceu.c @@ -209,6 +209,8 @@ void FCEUI_CloseGame(void) void ResetGameLoaded(void) { + int i; + if (GameInfo) FCEUI_CloseGame(); @@ -216,8 +218,12 @@ void ResetGameLoaded(void) PPU_hook = NULL; GameHBIRQHook = NULL; - if (GameExpSound.Kill) - GameExpSound.Kill(); + for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { + if (GameExpSound[i].Kill) { + GameExpSound[i].Kill(); + } + } + memset(&GameExpSound, 0, sizeof(GameExpSound)); MapIRQHook = NULL; @@ -236,6 +242,7 @@ FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *databuf, size_t databufs frontend_post_load_init_cb_t frontend_post_load_init_cb) { FCEUFILE *fp; + int i; ResetGameLoaded(); diff --git a/src/fceu.h b/src/fceu.h index 5897ea3b1..8047dc784 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -74,16 +74,6 @@ extern uint8 PAL; #include "driver.h" -enum EXPSOUNDTYPE { - SND_VRC6 = 0, - SND_VRC7 = 1, - SND_FDS = 2, - SND_N163 = 3, - SND_S5B = 4, - SND_MMC5 = 5, - SND_LAST, -}; - typedef struct { int PAL; int SoundVolume; diff --git a/src/fds_apu.c b/src/fds_apu.c index f57d480a2..2268788c7 100644 --- a/src/fds_apu.c +++ b/src/fds_apu.c @@ -276,10 +276,10 @@ static void FDS_ESI(void) { void FDSSoundReset(void) { memset(&fdso, 0, sizeof(fdso)); FDS_ESI(); - GameExpSound.HiSync = HQSync; - GameExpSound.HiFill = RenderSoundHQ; - GameExpSound.Fill = FDSSound; - GameExpSound.RChange = FDS_ESI; + GameExpSound[SND_FDS].HiSync = HQSync; + GameExpSound[SND_FDS].HiFill = RenderSoundHQ; + GameExpSound[SND_FDS].Fill = FDSSound; + GameExpSound[SND_FDS].RChange = FDS_ESI; } uint8 FDSSoundRead(uint32 A) { diff --git a/src/filter.c b/src/filter.c index fcc752e8d..78611162f 100644 --- a/src/filter.c +++ b/src/filter.c @@ -87,6 +87,7 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) { int32 *outsave = out; int32 count = 0; uint32 max = (inlen - 1) << 16; + int i; if (FSettings.soundq == 2) { for (x = mrindex; x < max; x += mrratio) { @@ -132,8 +133,11 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) { *leftover = NCOEFFS + 1; } - if (GameExpSound.NeoFill) - GameExpSound.NeoFill(outsave, count); + for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { + if (GameExpSound[i].NeoFill) { + GameExpSound[i].NeoFill(outsave, count); + } + } SexyFilter(outsave, outsave, count); if (FSettings.lowpass) diff --git a/src/ines.c b/src/ines.c index 2061005f5..2a0dbf156 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1170,7 +1170,7 @@ INES_BOARD_BEGIN() INES_BOARD( "YY860417C", 281, Mapper281_Init ) INES_BOARD( "860224C", 282, Mapper282_Init ) INES_BOARD( "GS-2004/GS-2013", 283, Mapper283_Init ) - INES_BOARD( "DripGame", 284, Mapper284_Init ) +/* INES_BOARD( "DripGame", 284, Mapper284_Init ) */ /* Runs only on newppu */ INES_BOARD( "A65AS", 285, Mapper285_Init ) INES_BOARD( "BS-5", 286, Mapper286_Init ) INES_BOARD( "411120-C, 811120-C", 287, Mapper287_Init ) diff --git a/src/mappers/sound/dripsound.c b/src/mappers/sound/dripsound.c index 72b315e2d..cb6e167af 100644 --- a/src/mappers/sound/dripsound.c +++ b/src/mappers/sound/dripsound.c @@ -207,17 +207,17 @@ DECLFW(DRIPSound_Write) { } static void DRIPSound_SC(void) { - GameExpSound.Fill = DoDripSound; - GameExpSound.HiSync = SyncHQ; - GameExpSound.HiFill = DoDRIPSoundHQ; - GameExpSound.RChange = DRIPSound_SC; + GameExpSound[0].Fill = DoDripSound; + GameExpSound[0].HiSync = SyncHQ; + GameExpSound[0].HiFill = DoDRIPSoundHQ; + GameExpSound[0].RChange = DRIPSound_SC; channel[0].timer = 0; channel[1].timer = 0; cvbc = 0; } void DRIPSound_ESI(void) { - GameExpSound.RChange = DRIPSound_SC; + GameExpSound[0].RChange = DRIPSound_SC; ChannelReset(&channel[0]); ChannelReset(&channel[1]); diff --git a/src/mappers/sound/fdssound.c b/src/mappers/sound/fdssound.c index 28bd3c8d6..9bfc045f0 100644 --- a/src/mappers/sound/fdssound.c +++ b/src/mappers/sound/fdssound.c @@ -353,10 +353,10 @@ static void FDSSound(int c) { } void FDSSound_SC(void) { - GameExpSound.HiSync = HQSync; - GameExpSound.HiFill = RenderSoundHQ; - GameExpSound.Fill = FDSSound; - GameExpSound.RChange = FDSSound_SC; + GameExpSound[SND_FDS].HiSync = HQSync; + GameExpSound[SND_FDS].HiFill = RenderSoundHQ; + GameExpSound[SND_FDS].Fill = FDSSound; + GameExpSound[SND_FDS].RChange = FDSSound_SC; if (FSettings.SndRate) { if (FSettings.soundq >= 1) { diff --git a/src/mappers/sound/mmc5sound.c b/src/mappers/sound/mmc5sound.c index 90e8162f7..0fd26a4c9 100644 --- a/src/mappers/sound/mmc5sound.c +++ b/src/mappers/sound/mmc5sound.c @@ -199,8 +199,8 @@ static void MMC5Square_Write(MMC5SQUARE *channel, uint8 reg, uint8 V) { } DECLFW(MMC5Sound_Write) { - GameExpSound.Fill = MMC5RunSound; - GameExpSound.HiFill = MMC5RunSoundHQ; + GameExpSound[SND_MMC5].Fill = MMC5RunSound; + GameExpSound[SND_MMC5].HiFill = MMC5RunSoundHQ; switch (A) { case 0x5010: @@ -249,7 +249,7 @@ DECLFW(MMC5Sound_Write) { } static void MMC5SC(void) { - GameExpSound.HiSync = MMC5HiSync; + GameExpSound[SND_MMC5].HiSync = MMC5HiSync; MMC5Sound.square[0].vcount = 0; MMC5Sound.square[1].vcount = 0; @@ -274,7 +274,7 @@ static void MMC5SC(void) { void MMC5Sound_ESI(void) { memset(&MMC5Sound, 0, sizeof(MMC5Sound)); - GameExpSound.RChange = MMC5SC; + GameExpSound[SND_MMC5].RChange = MMC5SC; MMC5SC(); } diff --git a/src/mappers/sound/n163sound.c b/src/mappers/sound/n163sound.c index 62aa8e0c4..2ba0b2142 100644 --- a/src/mappers/sound/n163sound.c +++ b/src/mappers/sound/n163sound.c @@ -240,9 +240,9 @@ DECLFW(N163Sound_Write) { if (ramPos & 0x40) { if (FSettings.SndRate) { N163SoundHack(); - GameExpSound.Fill = N163Sound; - GameExpSound.HiFill = DoN163SoundHQ; - GameExpSound.HiSync = SyncHQ; + GameExpSound[SND_N163].Fill = N163Sound; + GameExpSound[SND_N163].HiFill = DoN163SoundHQ; + GameExpSound[SND_N163].HiSync = SyncHQ; } } IRAM[ramPos] = V; @@ -276,7 +276,7 @@ static void N163SC(void) { } void N163Sound_ESI(void) { - GameExpSound.RChange = N163SC; + GameExpSound[SND_N163].RChange = N163SC; N163SC(); if (iNESCart.battery) { diff --git a/src/mappers/sound/s5bsound.c b/src/mappers/sound/s5bsound.c index 34b284320..207fe41f6 100644 --- a/src/mappers/sound/s5bsound.c +++ b/src/mappers/sound/s5bsound.c @@ -70,8 +70,8 @@ DECLFW(S5BSound_Write) { PSG_writeIO(psg_chip, 0, V); break; case 0xE000: - GameExpSound.Fill = UpdatePSG; - GameExpSound.NeoFill = UpdatePSGNEO; + GameExpSound[SND_S5B].Fill = UpdatePSG; + GameExpSound[SND_S5B].NeoFill = UpdatePSGNEO; PSG_writeIO(psg_chip, 1, V); break; } @@ -97,8 +97,8 @@ void S5BSound_ESI(void) { return; } - GameExpSound.RChange = S5BSound_SC; - GameExpSound.Kill = S5BSound_KILL; + GameExpSound[SND_S5B].RChange = S5BSound_SC; + GameExpSound[SND_S5B].Kill = S5BSound_KILL; S5BSound_SC(); } @@ -251,9 +251,9 @@ DECLFW(S5BSound_Write) { sndcmd = V & 0x0F; break; case 0xE000: - GameExpSound.Fill = AYSound; - GameExpSound.HiFill = AYSoundHQ; - GameExpSound.HiSync = AYHiSync; + GameExpSound[SND_S5B].Fill = AYSound; + GameExpSound[SND_S5B].HiFill = AYSoundHQ; + GameExpSound[SND_S5B].HiSync = AYHiSync; switch (sndcmd) { case 0: case 1: @@ -310,7 +310,7 @@ static void S5BSound_SC(void) { } void S5BSound_ESI(void) { - GameExpSound.RChange = S5BSound_SC; + GameExpSound[SND_S5B].RChange = S5BSound_SC; S5BSound_SC(); } diff --git a/src/mappers/sound/vrc6sound.c b/src/mappers/sound/vrc6sound.c index 931d2ae44..d2a6162ed 100644 --- a/src/mappers/sound/vrc6sound.c +++ b/src/mappers/sound/vrc6sound.c @@ -290,9 +290,9 @@ DECLFW(VRC6Sound_Write) { } static void VRC6Sound_SC(void) { - GameExpSound.Fill = VRC6RunSound; - GameExpSound.HiFill = VRC6RunSoundHQ; - GameExpSound.HiSync = VRC6SyncHQ; + GameExpSound[SND_VRC6].Fill = VRC6RunSound; + GameExpSound[SND_VRC6].HiFill = VRC6RunSoundHQ; + GameExpSound[SND_VRC6].HiSync = VRC6SyncHQ; VRC6Sound.square[0].vcount = 1; VRC6Sound.square[1].vcount = 1; @@ -315,7 +315,7 @@ static void VRC6Sound_SC(void) { void VRC6Sound_ESI(void) { memset(&VRC6Sound, 0, sizeof(VRC6Sound)); - GameExpSound.RChange = VRC6Sound_SC; + GameExpSound[SND_VRC6].RChange = VRC6Sound_SC; VRC6Sound_SC(); } diff --git a/src/mappers/sound/vrc7sound.c b/src/mappers/sound/vrc7sound.c index dc416f8e9..1a8f07ac9 100644 --- a/src/mappers/sound/vrc7sound.c +++ b/src/mappers/sound/vrc7sound.c @@ -58,8 +58,8 @@ DECLFW(VRC7Sound_Write) { OPLL_writeIO(chip, 0, V); break; case 0x9030: - GameExpSound.Fill = UpdateOPL; - GameExpSound.NeoFill = UpdateOPLNEO; + GameExpSound[SND_VRC7].Fill = UpdateOPL; + GameExpSound[SND_VRC7].NeoFill = UpdateOPLNEO; OPLL_writeIO(chip, 1, V); break; } @@ -85,8 +85,8 @@ void VRC7Sound_ESI(void) { return; } - GameExpSound.RChange = VRC7SC; - GameExpSound.Kill = VRC7SKill; + GameExpSound[SND_VRC7].RChange = VRC7SC; + GameExpSound[SND_VRC7].Kill = VRC7SKill; VRC7SC(); } diff --git a/src/sound.c b/src/sound.c index f375a5914..b7abdc189 100644 --- a/src/sound.c +++ b/src/sound.c @@ -37,7 +37,16 @@ int32 Wave[2048 + 512]; int32 WaveHi[40000]; int32 WaveFinal[2048 + 512]; -EXPSOUND GameExpSound = { 0, 0, 0, 0, 0, 0 }; +/* FIXME: Very ugly hack and only relevant in multichip NSF playback */ +/* Indexing is based on sound channel enum */ +EXPSOUND GameExpSound[GAMEEXPSOUND_COUNT] = { + { 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0 }, +}; static uint8 TriCount = 0; static uint8 TriMode = 0; @@ -943,7 +952,7 @@ void SetNESSoundMap(void) { static int32 inbuf = 0; int FlushEmulateSound(void) { - int x; + int i, x; int32 end, left; if (!sound_timestamp) return(0); @@ -963,7 +972,11 @@ int FlushEmulateSound(void) { if (FSettings.soundq >= 1) { int32 *tmpo = &WaveHi[soundtsoffs]; - if (GameExpSound.HiFill) GameExpSound.HiFill(); + for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { + if (GameExpSound[i].HiFill) { + GameExpSound[i].HiFill(); + } + } for (x = sound_timestamp; x; x--) { uint32 b = *tmpo; @@ -976,13 +989,21 @@ int FlushEmulateSound(void) { memmove(WaveHi, WaveHi + SOUNDTS - left, left * sizeof(uint32)); memset(WaveHi + left, 0, sizeof(WaveHi) - left * sizeof(uint32)); - if (GameExpSound.HiSync) GameExpSound.HiSync(left); + for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { + if (GameExpSound[i].HiSync) { + GameExpSound[i].HiSync(left); + } + } + for (x = 0; x < 5; x++) ChannelBC[x] = left; } else { end = (SOUNDTS << 16) / soundtsinc; - if (GameExpSound.Fill) - GameExpSound.Fill(end & 0xF); + for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { + if (GameExpSound[i].Fill) { + GameExpSound[i].Fill(end & 0xF); + } + } SexyFilter(Wave, WaveFinal, end >> 4); @@ -1076,7 +1097,7 @@ void FCEUSND_Power(void) { void SetSoundVariables(void) { - int x; + int i, x; fhinc = PAL ? 16626 : 14915; /* *2 CPU clock rate */ fhinc *= 24; @@ -1113,8 +1134,11 @@ void SetSoundVariables(void) { MakeFilters(FSettings.SndRate); - if (GameExpSound.RChange) - GameExpSound.RChange(); + for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { + if (GameExpSound[i].RChange) { + GameExpSound[i].RChange(); + } + } nesincsize = (int64)(((int64)1 << 17) * (double)(PAL ? PAL_CPU : NTSC_CPU) / (FSettings.SndRate * 16)); memset(sqacc, 0, sizeof(sqacc)); diff --git a/src/sound.h b/src/sound.h index 4e749a9a8..c720c41b7 100644 --- a/src/sound.h +++ b/src/sound.h @@ -38,7 +38,18 @@ typedef struct { void (*Kill)(void); } EXPSOUND; -extern EXPSOUND GameExpSound; +enum EXPSOUNDTYPE { + SND_VRC6 = 0, + SND_VRC7 = 1, + SND_FDS = 2, + SND_N163 = 3, + SND_S5B = 4, + SND_MMC5 = 5, + SND_LAST, +}; + +#define GAMEEXPSOUND_COUNT 6 +extern EXPSOUND GameExpSound[GAMEEXPSOUND_COUNT]; extern int32 nesincsize; From fdb7124ac0b621f74e2674804cb2341762d03d5e Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 15:18:35 +0800 Subject: [PATCH 07/16] Replace sound channel on/off switch to percent values, add volume controls for expansion audio --- src/drivers/libretro/libretro.c | 101 ++++- src/drivers/libretro/libretro_core_options.h | 430 ++++++++++++++++--- src/sound.c | 10 +- src/sound.h | 19 +- 4 files changed, 477 insertions(+), 83 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 604090561..9a799078f 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -1464,11 +1464,17 @@ static bool update_option_visibility(void) "fceumm_sndlowpass", "fceumm_sndstereodelay", "fceumm_swapduty", - "fceumm_apu_1", - "fceumm_apu_2", - "fceumm_apu_3", - "fceumm_apu_4", - "fceumm_apu_5" + "fceumm_apu_square_1", + "fceumm_apu_square_2", + "fceumm_apu_triangle", + "fceumm_apu_noise", + "fceumm_apu_dpcm", + "fceumm_apu_fds", + "fceumm_apu_s5b", + "fceumm_apu_n163", + "fceumm_apu_vrc6", + "fceumm_apu_vrc7", + "fceumm_apu_mmc5" }; option_display.visible = opt_showAdvSoundOptions; @@ -1860,11 +1866,77 @@ static void set_apu_channels(int chan) FSettings.PCMVolume = (chan & 5) ? 256 : 0; } +#define VOLUME_MAX 256 + +static void check_variables_volume_levels(void) { + struct { + int channel; + char name[25]; + } apu_channels[] = { + /*{ SND_SQUARE1, "fceumm_apu_square_1" }, + { SND_SQUARE2, "fceumm_apu_square_2" }, + { SND_TRIANGLE, "fceumm_apu_triangle" }, + { SND_NOISE, "fceumm_apu_noise" }, + { SND_DMC, "fceumm_apu_dpcm" },*/ + { SND_FDS, "fceumm_apu_fds" }, + { SND_S5B, "fceumm_apu_s5b" }, + { SND_N163, "fceumm_apu_n163" }, + { SND_VRC6, "fceumm_apu_vrc6" }, + { SND_VRC7, "fceumm_apu_vrc7" }, + { SND_MMC5, "fceumm_apu_mmc5" }, + }; + struct retro_variable var = { 0 }; + int i = 0; + int ssize; + + var.key = "fceumm_apu_square_1"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + FSettings.SquareVolume[1] = atoi(var.value); + } + + var.key = "fceumm_apu_square_2"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + FSettings.SquareVolume[0] = atoi(var.value); + } + + var.key = "fceumm_apu_triangle"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + FSettings.TriangleVolume = atoi(var.value); + } + + var.key = "fceumm_apu_noise"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + FSettings.NoiseVolume = atoi(var.value); + } + + var.key = "fceumm_apu_dpcm"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + FSettings.PCMVolume = atoi(var.value); + } + + ssize = sizeof(apu_channels) / sizeof(apu_channels[0]); + for (i = 0; i < ssize; i++) { + int channel = apu_channels[i].channel; + var.key = apu_channels[i].name; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { + int newval = VOLUME_MAX * atoi(var.value) / 100; + if (FCEUI_GetExpSoundVolume(channel) != newval) { + FCEUI_SetExpSoundVolume(channel, newval); + } + } + } +} + static void check_variables(bool startup) { struct retro_variable var = {0}; char key[256]; - int i, enable_apu; + int i; bool stereo_filter_updated = false; /* 1 = Performs only geometry update: e.g. overscans */ @@ -2298,8 +2370,7 @@ static void check_variables(bool startup) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - int val = (int)(atof(var.value) * 25.6); - sndvolume = val; + sndvolume = (unsigned)((float)VOLUME_MAX * atof(var.value) / 200.0f); FCEUD_SoundToggle(); } @@ -2322,19 +2393,7 @@ static void check_variables(bool startup) swapDuty = newval; } - var.key = key; - - enable_apu = 0xff; - - strcpy(key, "fceumm_apu_x"); - for (i = 0; i < 5; i++) - { - key[strlen("fceumm_apu_")] = '1' + i; - var.value = NULL; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && !strcmp(var.value, "disabled")) - enable_apu &= ~(1 << i); - } - set_apu_channels(enable_apu); + check_variables_volume_levels(); update_dipswitch(); diff --git a/src/drivers/libretro/libretro_core_options.h b/src/drivers/libretro/libretro_core_options.h index f13118b54..c5507ff2b 100644 --- a/src/drivers/libretro/libretro_core_options.h +++ b/src/drivers/libretro/libretro_core_options.h @@ -381,94 +381,418 @@ struct retro_core_option_v2_definition option_defs[] = { "fceumm_sndvolume", "Master Volume", NULL, - "Change master volume level.", + "Change master volume level %.", NULL, "audio", { - { "0", "0%" }, - { "1", "10%" }, - { "2", "20%" }, - { "3", "30%" }, - { "4", "40%" }, - { "5", "50%" }, - { "6", "60%" }, - { "7", "70%" }, - { "8", "80%" }, - { "9", "90%" }, - { "10", "100%" }, + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { "100", NULL }, + { "105", NULL }, + { "110", NULL }, + { "115", NULL }, + { "120", NULL }, + { "125", NULL }, + { "130", NULL }, + { "135", NULL }, + { "140", NULL }, + { "145", NULL }, + { "150", NULL }, + { "155", NULL }, + { "160", NULL }, + { "165", NULL }, + { "170", NULL }, + { "175", NULL }, + { "180", NULL }, + { "185", NULL }, + { "190", NULL }, + { "195", NULL }, + { "200", NULL }, { NULL, NULL }, }, - "7", + "100", }, { - "fceumm_apu_1", - "Audio Channel 1 (Square 1)", - "Channel 1 (Square 1)", - "Enables or disables pulse wave generator audio output 1.", + "fceumm_apu_square_1", + "Channel Volume (Square 1)", + NULL, + "Change pulse wave generator 1 audio output.", NULL, "audio", { - { "enabled", NULL }, - { "disabled", NULL }, - { NULL, NULL }, + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, }, - "enabled", + "100", }, { - "fceumm_apu_2", - "Audio Channel 2 (Square 2)", - "Channel 2 (Square 2)", - "Enables or disables pulse wave generator audio output 2.", + "fceumm_apu_square_2", + "Channel Volume (Square 2)", + NULL, + "Change pulse wave generator 2 audio output.", NULL, "audio", { - { "enabled", NULL }, - { "disabled", NULL }, - { NULL, NULL }, + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, }, - "enabled", + "100", }, { - "fceumm_apu_3", - "Audio Channel 3 (Triangle)", - "Channel 3 (Triangle)", - "Enables or disables triangle wave generator audio output.", + "fceumm_apu_triangle", + "Channel Volume (Triangle)", + NULL, + "Modify triangle wave generator audio output.", NULL, "audio", { - { "enabled", NULL }, - { "disabled", NULL }, - { NULL, NULL }, + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, }, - "enabled", + "100", }, { - "fceumm_apu_4", - "Audio Channel 4 (Noise)", - "Channel 4 (Noise)", - "Enables or disables noise generator audio output.", + "fceumm_apu_noise", + "Channel Volume (Noise)", + NULL, + "Change noise generator audio output.", NULL, "audio", { - { "enabled", NULL }, - { "disabled", NULL }, - { NULL, NULL }, + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, }, - "enabled", + "100", }, { - "fceumm_apu_5", - "Audio Channel 5 (PCM)", - "Channel 5 (PCM)", - "Enables or disables delta modulation channel audio output.", + "fceumm_apu_dpcm", + "Channel Volume (DPCM)", + NULL, + "Change delta modulation channel audio output.", NULL, "audio", { - { "enabled", NULL }, - { "disabled", NULL }, - { NULL, NULL }, + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, }, - "enabled", + "100", + }, + { + "fceumm_apu_fds", + "Channel Volume (FDS)", + NULL, + "Change FDS expansion audio output.", + NULL, + "audio", + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100", + }, + { + "fceumm_apu_s5b", + "Channel Volume (S5B)", + NULL, + "Change Sunsoft S5B expansion audio output.", + NULL, + "audio", + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100", + }, + { + "fceumm_apu_n163", + "Channel Volume (N163)", + NULL, + "Chnage Namco 163 expansion audio output.", + NULL, + "audio", + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100", + }, + { + "fceumm_apu_vrc6", + "Channel Volume (VRC6)", + NULL, + "Change VRC6 expansion audio output.", + NULL, + "audio", + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100", + }, + { + "fceumm_apu_vrc7", + "Channel Volume (VRC7)", + NULL, + "Change VRC7 expansion audio output.", + NULL, + "audio", + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100", + }, + { + "fceumm_apu_mmc5", + "Channel Volume (MMC5)", + NULL, + "Change MMC5 expansion audio output.", + NULL, + "audio", + { + { "0", NULL }, + { "5", NULL }, + { "10", NULL }, + { "15", NULL }, + { "20", NULL }, + { "25", NULL }, + { "30", NULL }, + { "35", NULL }, + { "40", NULL }, + { "45", NULL }, + { "50", NULL }, + { "55", NULL }, + { "60", NULL }, + { "65", NULL }, + { "70", NULL }, + { "75", NULL }, + { "80", NULL }, + { "85", NULL }, + { "90", NULL }, + { "95", NULL }, + { "100", NULL }, + { NULL, NULL }, + }, + "100", }, { "fceumm_turbo_enable", diff --git a/src/sound.c b/src/sound.c index b7abdc189..2e253c6da 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1167,12 +1167,18 @@ void FCEUI_SetSoundVolume(uint32 volume) { FSettings.SoundVolume = volume; } +void FCEUI_SetExpSoundVolume(int ch, uint32 volume) { + FSettings.ExpSoundVolume[ch] = volume; +} + int FCEUI_GetExpSoundVolume(int ch) { - return FSettings.ExpSoundVolume[ch]; + if ((ch >= SND_VRC6) && (ch < SND_LAST)) + return FSettings.ExpSoundVolume[ch]; + return 0; } int32 GetOutput(int ch, int32 in) { - if ((ch >= SND_VRC6) && (ch <= SND_LAST)) + if ((ch >= SND_VRC6) && (ch < SND_LAST)) { int mod = FCEUI_GetExpSoundVolume(ch); diff --git a/src/sound.h b/src/sound.h index c720c41b7..1c2c5cc69 100644 --- a/src/sound.h +++ b/src/sound.h @@ -39,16 +39,17 @@ typedef struct { } EXPSOUND; enum EXPSOUNDTYPE { - SND_VRC6 = 0, - SND_VRC7 = 1, - SND_FDS = 2, - SND_N163 = 3, - SND_S5B = 4, - SND_MMC5 = 5, + SND_NORM = 0, + SND_VRC6, + SND_VRC7, + SND_FDS, + SND_N163, + SND_S5B, + SND_MMC5, SND_LAST, }; -#define GAMEEXPSOUND_COUNT 6 +#define GAMEEXPSOUND_COUNT SND_LAST extern EXPSOUND GameExpSound[GAMEEXPSOUND_COUNT]; extern int32 nesincsize; @@ -75,6 +76,10 @@ void FCEUSND_LoadState(int version); void FASTAPASS(1) FCEU_SoundCPUHook(int); +/* volume levels for mapper-based expansion audio */ +void FCEUI_SetExpSoundVolume(int ch, uint32 volume); +int FCEUI_GetExpSoundVolume(int ch); + /* Modify channel wave volume based on volume modifiers * Note: the formulat x = x * y /256 does not yield exact results, * but is "close enough" and avoids the need for using double values From 30787e0dfc04bea89d2e6e3358d83c25557201d6 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 16:45:56 +0800 Subject: [PATCH 08/16] Backport mapper 468 Adding it as-is --- Makefile.common | 1 + src/ines.c | 3 + src/ines.h | 1 + src/mappers/m468/468.c | 270 ++++++++++++++++++++++++++++++++ src/mappers/m468/468_cnrom.h | 45 ++++++ src/mappers/m468/468_discrete.h | 73 +++++++++ src/mappers/m468/468_fme7.h | 72 +++++++++ src/mappers/m468/468_if12.h | 31 ++++ src/mappers/m468/468_lf36.h | 46 ++++++ src/mappers/m468/468_mmc1.h | 72 +++++++++ src/mappers/m468/468_mmc24.h | 67 ++++++++ src/mappers/m468/468_mmc3.h | 80 ++++++++++ src/mappers/m468/468_nanjing.h | 29 ++++ src/mappers/m468/468_vrc1.h | 25 +++ src/mappers/m468/468_vrc24.h | 92 +++++++++++ src/mappers/m468/468_vrc3.h | 63 ++++++++ src/mappers/m468/468_vrc6.h | 72 +++++++++ src/mappers/m468/468_vrc7.h | 82 ++++++++++ 18 files changed, 1124 insertions(+) create mode 100644 src/mappers/m468/468.c create mode 100644 src/mappers/m468/468_cnrom.h create mode 100644 src/mappers/m468/468_discrete.h create mode 100644 src/mappers/m468/468_fme7.h create mode 100644 src/mappers/m468/468_if12.h create mode 100644 src/mappers/m468/468_lf36.h create mode 100644 src/mappers/m468/468_mmc1.h create mode 100644 src/mappers/m468/468_mmc24.h create mode 100644 src/mappers/m468/468_mmc3.h create mode 100644 src/mappers/m468/468_nanjing.h create mode 100644 src/mappers/m468/468_vrc1.h create mode 100644 src/mappers/m468/468_vrc24.h create mode 100644 src/mappers/m468/468_vrc3.h create mode 100644 src/mappers/m468/468_vrc6.h create mode 100644 src/mappers/m468/468_vrc7.h diff --git a/Makefile.common b/Makefile.common index 2c172acc5..68d3132b0 100644 --- a/Makefile.common +++ b/Makefile.common @@ -21,6 +21,7 @@ COREDEFINES = \ FCEU_SRC_DIRS := \ $(CORE_DIR)/mappers \ + $(CORE_DIR)/mappers/m468 \ $(CORE_DIR)/mappers/hw \ $(CORE_DIR)/mappers/sound \ $(CORE_DIR)/input diff --git a/src/ines.c b/src/ines.c index 2a0dbf156..5e3fc0fd7 100644 --- a/src/ines.c +++ b/src/ines.c @@ -1327,6 +1327,9 @@ INES_BOARD_BEGIN() INES_BOARD( "ET-120", 465, Mapper465_Init ) INES_BOARD( "Keybyte Computer", 466, Mapper466_Init ) INES_BOARD( "47-2", 467, Mapper467_Init ) + /* m468 - untested since i dont have rom to test it, so im adding it here as-is */ + INES_BOARD( "BlazePro CPLD", 468, Mapper468_Init ) + INES_BOARD( "Impact Soft IM1", 471, Mapper471_Init ) INES_BOARD( "Yhc-000", 500, Mapper500_Init ) INES_BOARD( "Yhc-001", 501, Mapper501_Init ) diff --git a/src/ines.h b/src/ines.h index 93016b71c..413cdc9e2 100644 --- a/src/ines.h +++ b/src/ines.h @@ -465,6 +465,7 @@ void Mapper464_Init(CartInfo *); void Mapper465_Init(CartInfo *); void Mapper466_Init(CartInfo *); void Mapper467_Init(CartInfo *); +void Mapper468_Init(CartInfo *); void Mapper471_Init(CartInfo *); void Mapper500_Init(CartInfo *); void Mapper501_Init(CartInfo *); diff --git a/src/mappers/m468/468.c b/src/mappers/m468/468.c new file mode 100644 index 000000000..ee623d024 --- /dev/null +++ b/src/mappers/m468/468.c @@ -0,0 +1,270 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2022 NewRisingSun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* BlazePro CPLD-based multicarts + + Unsolved issue: how is CHR RAM write-protection triggered? + + Known problems: + + Forever Duo of NES 852-in-1 (rev1): + #A370 Time Lord: Hangs with glitchy status bar on NTSC and PAL but not Dendy + #A133 Galactic Crusader: Wrong mirroring + #A249 Mission Cobra: Wrong mirroring + + Legendary Games of NES 509-in-1: + #189 Huang Di Battle of Zhuolu: Wrong mirroring during intro + #227 Kid Niki Niki 2: Title screen animation flickers and looks strange + #234 Klax: Screen in wrong position during options screen + #365 Rocman X: Graphical garbage in waterfall (middle) level + #403 Star Wars: Blank tiles due to lack of CHR RAM write-protection + #404 The Empire Strikes Back: Blank tiles due to lack of CHR RAM write-protection + #460 Twin Dragons: Wrong mirroring + + Unlicensed Collection 142-in-1: + #59 Huang Di: Wrong mirroring during intro + #84 Ms. Pac-Man: Wrong mirroring + #102 Rocman X: Graphical garbage in waterfall (middle) level + #132 Trolls on Treasure Island: Wrong mirroring during map + + Unreleased Collection 73-in-1 (v1.01): + #38 Holy Diver: Wrong mirroring during first scene +*/ + +#include "mapinc.h" +#include "state.h" + +static uint8 submapper; +static uint8 eeprom[16], eep_clock, state, command, output; /* Some strange serial EEPROM */ + +static int prevSFEXINDEX; +extern int SFEXINDEX; +extern SFORMAT SFMDATA[64]; + +static uint8 mapper; /* 5700 MSB >>4 OR'd with submapper <<4 */ +static uint8 mapperFlags; /* 5700 LSB */ +static uint8 misc; /* 5601 */ +static uint8 misc2; /* 5702 */ +static void (*sync)(); + +static uint16 prgOR; +static uint8 prgAND; + +static uint8 regByte[16]; +static int16 regWord[9]; + +#include "468_mmc1.h" +#include "468_mmc24.h" +#include "468_mmc3.h" +#include "468_vrc1.h" +#include "468_vrc24.h" +#include "468_vrc3.h" +#include "468_vrc6.h" +#include "468_vrc7.h" +#include "468_fme7.h" +#include "468_discrete.h" +#include "468_cnrom.h" +#include "468_if12.h" +#include "468_lf36.h" +#include "468_nanjing.h" + +static SFORMAT stateRegs[] = { + { &mapper, 1, "SUP0" }, + { &mapperFlags, 1, "SUP1" }, + { &misc, 1, "SUP2" }, + { &misc2, 1, "SUP3" }, + { &prgOR, 2, "SUP4" }, + { &prgAND, 1, "SUP5" }, + { eeprom, 16,"EEPR" }, + { &eep_clock, 1, "EEP0" }, + { &state, 1, "EEP1" }, + { &command, 1, "EEP2" }, + { &output, 1, "EEP3" }, + { regByte, 16,"REGB" }, + { regWord, 16,"REGW" }, + { 0 } +}; + +static const uint16 lut509[512] ={ /* Strange look-up table, used only by Legendary Games of NES 509-in-1 */ + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 0, 1, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 4, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, + 124, 125, 126, 127, 128, 129, 2, 3, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 5, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 256, 6, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 512, 513, 514, 515, 516, 517 +}; + +void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */ + if (select) + state =0; + else + if (!eep_clock && !!newClock) { + if (state <8) { + command =command <<1 | !!(newData)*1; + if (++state ==8 && (command &0xF0) !=0x50 && (command &0xF0) !=0xA0) state =0; + } else { + int mask =1 <<(15 -state); + int address =command &0x0F; + if ((command &0xF0) ==0xA0) { + eeprom[address] =eeprom[address] &~mask | !!(newData)*mask; + /* The "write" command also silently returns the content of a strange lookup table */ + output =!!(lut509[eeprom[0] | eeprom[1] | eeprom[2] <<8 &0x1FF] >>(address &1? 0: 8) &mask); + } else + if ((command &0xF0) ==0x50) + output =!!(eeprom[address] &mask); + + if (++state ==16) state =0; + } + } + eep_clock =newClock; +} + +static DECLFR(readReg); +static DECLFW(writeReg); +static void setMapper(uint8 clearRegs) { + int i; + if (clearRegs) { + for (i =0; i <16; i++) regByte[i] =0; + for (i =0; i < 8; i++) regWord[i] =0; + X6502_IRQEnd(FCEU_IQEXT); + } + SetReadHandler(0x5000, 0x5FFF, readReg); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, writeReg); + SetWriteHandler(0x6000, 0xFFFF, CartBW); + MapIRQHook = NULL; + PPU_hook = NULL; + GameHBIRQHook = NULL; + setprg8r(0x10, 0x6000, 0); + + switch(mapper) { /* 5700 MSB >>4 OR'd with submapper <<4 */ + case 0x00: case 0x01: case 0x32: MMC1_reset(clearRegs); break; + case 0x0A: MMC2_reset(clearRegs); break; + case 0x10: case 0x11: case 0x12: MMC3_reset(clearRegs); break; + case 0x08: MMC4_reset(clearRegs); break; + case 0x40: VRC1_reset(clearRegs); break; + case 0x20: case 0x21: case 0x22: case 0x23: VRC24_reset(clearRegs); break; + case 0x44: VRC3_reset(clearRegs); break; + case 0x30: case 0x31: VRC6_reset(clearRegs); break; + case 0x41: VRC7_reset(clearRegs); break; + case 0x07: LF36_reset(clearRegs); break; + case 0x50: FME7_reset(clearRegs); break; + case 0x0E: case 0x1E: NANJING_reset(clearRegs); break; + case 0x09: case 0x0B: case 0x17: case 0x37: UNROM_IF12_reset(clearRegs); break; + case 0x04: case 0x06: case 0x14: case 0x16: ANROM_BNROM_reset(clearRegs); break; + case 0x05: case 0x15: CNROM_BF9097_reset(clearRegs); break; + case 0x0C: case 0x0D: case 0x1C: case 0x1D: GNROM_reset(clearRegs); break; + default: break; + } + sync(); +} + +static DECLFR(readReg) { + switch(A) { + case 0x5301: case 0x5601: + return output? 0x80: 0x00; + default: + return 0xFF; + } +} + +static DECLFW(writeReg) { + switch(A) { + case 0x5301: + if (submapper ==0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01)); + break; + case 0x5601: + if (~misc &0x80) { + misc =V; + if (submapper !=1) { + prgOR =prgOR &~0x2000 | V <<9 &0x2000; + sync(); + } + } + if (submapper ==1) setPins(!!(V &0x10), !!(V &0x02), !!(V &0x01)); + break; + case 0x5700: + mapper =V >>4 | submapper <<4; + mapperFlags =V &0xF; + prgOR =prgOR &~0x0010 | V <<4 &0x0010; + setMapper(1); + break; + case 0x5701: + prgOR =prgOR &~0x1FE0 | V <<5 &0x1FE0; + sync(); + break; + case 0x5702: + if (submapper ==1) { + misc2 =V; + prgOR =prgOR &~0x2000 | V <<9 &0x2000; + setMapper(0); /* The misc2 value is required for prgAND by MMC3 and UNROM */ + } + break; + } +} + +static void reset(void) { + mapper =submapper <<4; + mapperFlags =0x0F; + misc =0; + misc2 =0; + prgOR =0x7FF0; + eep_clock =command =output =1; + command =state =0; + setMapper(1); +} + +static void power(void) { + int i; + for (i =0; i <16; i++) eeprom[i] =0; + reset(); +} + +static void close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void stateRestore(int version) { + setMapper(0); +} + +void Mapper468_Init(CartInfo *info) { + submapper =info->submapper; + info->Reset =reset; + info->Power =power; + info->Close =close; + GameStateRestore =stateRestore; + + WRAMSIZE =8192; + WRAM =(uint8*) FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(stateRegs, ~0, 0, 0); + prevSFEXINDEX =SFEXINDEX; +} diff --git a/src/mappers/m468/468_cnrom.h b/src/mappers/m468/468_cnrom.h new file mode 100644 index 000000000..00dc2dcb8 --- /dev/null +++ b/src/mappers/m468/468_cnrom.h @@ -0,0 +1,45 @@ +#define CNROM_reg regByte + +static void CNROM_sync () { + int OR =prgOR >>1; + if (mapperFlags &2) { + setprg16(0x8000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF); + setprg16(0xC000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF); + setchr8(CNROM_reg[0] &0x03); + } else { + OR >>=1; + setprg32(0x8000, CNROM_reg[2] &0x7 | OR &~0x7); + setchr8(CNROM_reg[0] &0x0F); + } + if (mapperFlags &8) + setmirror(mapperFlags &0x04? MI_H: MI_V); + else + setmirror(CNROM_reg[1] &0x10? MI_1: MI_0); +} + +static DECLFW(CNROM_writeReg) { + switch(A &0xE000) { + case 0x8000: case 0xA000: + CNROM_reg[0] =V; + break; + case 0xE000: + CNROM_reg[2] =V; + break; + } + sync(); +} + +static DECLFW(BF9097_writeMirroring) { + CNROM_reg[1] =V; + sync(); +} + +void CNROM_BF9097_reset(uint8 clearRegs) { /* This strange mapper is used for both (C)NROM games and FireHawk. What an absurd combination!*/ + sync =CNROM_sync; + SetWriteHandler(0x8000, 0xFFFF, CNROM_writeReg); + if (~mapperFlags &8) + SetWriteHandler(0x9000, 0x9FFF, BF9097_writeMirroring); + sync(); +} + +#undef CNROM_reg diff --git a/src/mappers/m468/468_discrete.h b/src/mappers/m468/468_discrete.h new file mode 100644 index 000000000..e42c438b4 --- /dev/null +++ b/src/mappers/m468/468_discrete.h @@ -0,0 +1,73 @@ +#define latch regByte[0] + +static void ANROM_sync () { + int AND =prgAND >>2; + int OR =prgOR >>2; + setprg32(0x8000, latch &AND | OR &~AND); + setchr8(0); + setmirror(latch &0x10? MI_1: MI_0); +} + +static void BNROM_sync () { + int AND =prgAND >>2; + int OR =prgOR >>2; + setprg32(0x8000, latch &AND | OR &~AND); + setchr8(0); + setmirror(mapperFlags &4? MI_H: MI_V); +} + +static void GNROM_sync () { + int AND =prgAND >>2; + int OR =prgOR >>2 | (mapperFlags &4? 2: 0); + setprg32(0x8000, latch >>4 &AND | OR &~AND); + setchr8(latch &0x0F); + setmirror(mapper &1? MI_H: MI_V); +} + +static void UNROM_sync () { + int AND =prgAND >>1; + int OR =prgOR >>1; + setprg16(0x8000, latch &AND | OR &~AND); + setprg16(0xC000, 0xFF &AND | OR &~AND); + setchr8(0); + setmirror(mapperFlags &4? MI_H: MI_V); +} + +static DECLFW(DISCRETE_writeLatch) { + latch =V; + sync(); +} + +static DECLFW(Portopia_writeLatch) { + DISCRETE_writeLatch(A, A ==0xA000 && V ==0x00? 0x06: V); /* Strange hack, needed to get #282 "Portopia Serial Murder Case" on 852-in-1 running */ +} + +static DECLFW(ColorDreams_writeLatch) { + DISCRETE_writeLatch(A, V >>4 &0xF | V <<4 &0xF0); /* Sswap nibbles to mimic GNROM */ +} + + +void ANROM_BNROM_reset(uint8 clearRegs) { + sync =mapperFlags &8? BNROM_sync: ANROM_sync; + prgAND =(mapper ==0x06 || mapper ==0x16)? 0x3F: mapperFlags &2? 0x0F: 0x1F; + SetWriteHandler(0x8000, 0xFFFF, DISCRETE_writeLatch); + latch =0; + sync(); +} + +void GNROM_reset(uint8 clearRegs) { + sync =GNROM_sync; + prgAND =mapperFlags &8? 0x07: 0x0F; + SetWriteHandler(0x8000, 0xFFFF, misc &0x10 && mapper &~0x10? DISCRETE_writeLatch: ColorDreams_writeLatch); + latch =0; + sync(); +} + +void UNROM_reset(uint8 clearRegs) { + sync =UNROM_sync; + prgAND =mapper ==0x0B || misc2 &0x10? 0x3F: mapperFlags &2? 0x0F: 0x1F; + SetWriteHandler(0x8000, 0xFFFF, mapper ==0x09 && mapperFlags ==0xE? Portopia_writeLatch: DISCRETE_writeLatch); + sync(); +} + +#undef latch diff --git a/src/mappers/m468/468_fme7.h b/src/mappers/m468/468_fme7.h new file mode 100644 index 000000000..0e3d31166 --- /dev/null +++ b/src/mappers/m468/468_fme7.h @@ -0,0 +1,72 @@ +#define FME7_reg regByte +#define FME7_index regByte[15] +#define FME7_counter regWord[0] + +static void FME7_sync() { + int AND =mapperFlags &8? 0xFF: 0x7F; + switch(FME7_reg[8] &0xC0) { + case 0x00: case 0x80: + setprg8(0x6000, FME7_reg[0x8] &prgAND | prgOR &~prgAND); + break; + case 0x40: + /* Open Bus */ + break; + case 0xC0: + setprg8r(0x10, 0x6000, 0); + break; + } + + setprg8(0x8000, FME7_reg[0x9] &prgAND | prgOR &~prgAND); + setprg8(0xA000, FME7_reg[0xA] &prgAND | prgOR &~prgAND); + setprg8(0xC000, FME7_reg[0xB] &prgAND | prgOR &~prgAND); + setprg8(0xE000, prgAND | prgOR &~prgAND); + setchr1(0x0000, FME7_reg[0x0] &AND); + setchr1(0x0400, FME7_reg[0x1] &AND); + setchr1(0x0800, FME7_reg[0x2] &AND); + setchr1(0x0C00, FME7_reg[0x3] &AND); + setchr1(0x1000, FME7_reg[0x4] &AND); + setchr1(0x1400, FME7_reg[0x5] &AND); + setchr1(0x1800, FME7_reg[0x6] &AND); + setchr1(0x1C00, FME7_reg[0x7] &AND); + setmirror(FME7_reg[0xC] &3 ^(FME7_reg[0xC] &2? 0: 1)); +} + +static DECLFW(FME7_writeIndex) { + FME7_index =V &0xF; +} + +static DECLFW(FME7_writeReg) { + switch(FME7_index) { + case 0xE: + FME7_counter =FME7_counter &0xFF00 |V; + break; + case 0xF: + FME7_counter =FME7_counter &0x00FF |V <<8; + break; + case 0xD: + X6502_IRQEnd(FCEU_IQEXT); + /* Falling through */ + default: + FME7_reg[FME7_index] =V; + sync(); + } +} + +static void FP_FASTAPASS(1) FME7_cpuCycle(int a) { + while (a--) { + if (FME7_reg[0xD] &0x80 && !--FME7_counter && FME7_reg[0xD] &0x01) X6502_IRQBegin(FCEU_IQEXT); + } +} + +void FME7_reset(uint8 clearRegs) { + sync =FME7_sync; + prgAND =mapperFlags &2? 0x0F: 0x1F; + MapIRQHook =FME7_cpuCycle; + SetWriteHandler(0x8000, 0x9FFF, FME7_writeIndex); + SetWriteHandler(0xA000, 0xBFFF, FME7_writeReg); + sync(); +} + +#undef FME7_reg +#undef FME7_index +#undef FME7_counter diff --git a/src/mappers/m468/468_if12.h b/src/mappers/m468/468_if12.h new file mode 100644 index 000000000..12ec1e7fb --- /dev/null +++ b/src/mappers/m468/468_if12.h @@ -0,0 +1,31 @@ +#define IF12_reg regByte + +static void IF12_sync () { + int AND =prgAND >>1; + int OR =prgOR >>1; + setprg16(0x8000, IF12_reg[1] &AND | OR &~AND); + setprg16(0xC000, 0xFF &AND | OR &~AND); + setchr8(IF12_reg[0] >>1 &0xF); + setmirror(IF12_reg[0] &1? MI_H: MI_V); +} + +static DECLFW(IF12_writeReg) { + IF12_reg[A >>14 &1] =V; + sync(); +} + +void IF12_reset(uint8 clearRegs) { + sync =IF12_sync; + prgAND =mapperFlags &2? 0x0F: 0x1F; + SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg); + sync(); +} + +void UNROM_IF12_reset(uint8 clearRegs) { + if (mapperFlags &8) + UNROM_reset(clearRegs); + else + IF12_reset(clearRegs); +} + +#undef IF12_reg diff --git a/src/mappers/m468/468_lf36.h b/src/mappers/m468/468_lf36.h new file mode 100644 index 000000000..73f9407f2 --- /dev/null +++ b/src/mappers/m468/468_lf36.h @@ -0,0 +1,46 @@ +#define LF36_prg regByte[0] +#define LF36_irq regByte[1] +#define LF36_counter regWord[0] + +static void LF36_sync () { + int OR =prgOR | mapperFlags &0x08; + setprg8(0x8000, 0x04 | OR); + setprg8(0xA000, 0x05 | OR); + setprg8(0xC000, LF36_prg &0x07 | OR); + setprg8(0xE000, 0x07 | OR); + setchr8(0); + setmirror(mapperFlags &4? MI_H: MI_V); +} + +static DECLFW(LF36_writeReg) { + switch (A &0xE000) { + case 0x8000: LF36_irq =0; break; + case 0xA000: LF36_irq =1; break; + case 0XE000: LF36_prg =V; sync(); break; + } +} + +static void FP_FASTAPASS(1) LF36_cpuCycle(int a) { + while (a--) { + if (LF36_irq) { + if (++LF36_counter &0x1000) + X6502_IRQBegin(FCEU_IQEXT); + else + X6502_IRQEnd(FCEU_IQEXT); + } else { + X6502_IRQEnd(FCEU_IQEXT); + LF36_counter =0; + } + } +} + +void LF36_reset(uint8 clearRegs) { + sync =LF36_sync; + MapIRQHook =LF36_cpuCycle; + SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg); + sync(); +} + +#undef LF36_prg +#undef LF36_irq +#undef LF36_counter diff --git a/src/mappers/m468/468_mmc1.h b/src/mappers/m468/468_mmc1.h new file mode 100644 index 000000000..b780ce210 --- /dev/null +++ b/src/mappers/m468/468_mmc1.h @@ -0,0 +1,72 @@ +#define MMC1_reg regByte +#define MMC1_control regByte[0] +#define MMC1_chr0 regByte[1] +#define MMC1_chr1 regByte[2] +#define MMC1_prg regByte[3] +#define MMC1_shift regByte[4] +#define MMC1_count regByte[5] +#define MMC1_filter regByte[6] + +static void MMC1_sync () { + int AND =prgAND >>1; + int OR =prgOR >>1 | (mapper &0x01? (MMC1_chr0 &0x10): (mapperFlags &0x06)); + if (MMC1_control &0x08) { /* 16 KiB mode */ + if (MMC1_control &0x04) { /* OR logic */ + setprg16(0x8000, MMC1_prg &AND | OR &~AND); + setprg16(0xC000, 0xFF &AND | OR &~AND); + } else { /* AND logic */ + setprg16(0x8000, 0 &AND | OR &~AND); + setprg16(0xC000, MMC1_prg &AND | OR &~AND); + } + } else + setprg32(0x8000, (MMC1_prg &AND | OR &~AND) >>1); + + AND =mapper &0x01? 0x0F: 0x1F; /* SUROM needs to have the upper PRG bank bit, which is in the CHR registers, masked off */ + if (MMC1_control &0x10) { /* 4 KiB mode */ + setchr4(0x0000, MMC1_chr0 &AND); + setchr4(0x1000, MMC1_chr1 &AND); + } else /* 8 KiB mode */ + setchr8(MMC1_chr0 >>1 &(AND >>1)); + + setmirror(MMC1_control &2? (MMC1_control &1? MI_H: MI_V): (MMC1_control &1? MI_1: MI_0)); +} + +static DECLFW(MMC1_writeReg) { + if (V &0x80) { + MMC1_shift =MMC1_count =0; + MMC1_control |=0x0C; + sync(); + } else + if (!MMC1_filter) { + MMC1_shift |=(V &1) <>13 &3] =MMC1_shift; + MMC1_count =0; + MMC1_shift =0; + sync(); + } + } + MMC1_filter =2; +} + +static void FP_FASTAPASS(1) MMC1_cpuCycle(int a) { + while (a--) if (MMC1_filter) MMC1_filter--; +} + +void MMC1_reset(uint8 clearRegs) { + sync =MMC1_sync; + MapIRQHook =MMC1_cpuCycle; + prgAND =mapperFlags &2? (mapperFlags &8? 0x07: 0x0F): 0x1F; + SetWriteHandler(0x8000, 0xFFFF, MMC1_writeReg); + if (clearRegs) MMC1_control =0x0C; + sync(); +} + +#undef MMC1_reg +#undef MMC1_control +#undef MMC1_chr0 +#undef MMC1_chr1 +#undef MMC1_prg +#undef MMC1_shift +#undef MMC1_count +#undef MMC1_filter diff --git a/src/mappers/m468/468_mmc24.h b/src/mappers/m468/468_mmc24.h new file mode 100644 index 000000000..398fcc09b --- /dev/null +++ b/src/mappers/m468/468_mmc24.h @@ -0,0 +1,67 @@ +#define MMC24_reg regByte + +static void MMC2_sync() { + setprg8(0x8000, MMC24_reg[0] &prgAND | prgOR &~prgAND); + setprg8(0xA000, 0xFD &prgAND | prgOR &~prgAND); + setprg8(0xC000, 0xFE &prgAND | prgOR &~prgAND); + setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); + setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]); + setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]); + setmirror(MMC24_reg[5] &1? MI_H: MI_V); +} + +static void MMC4_sync() { + int AND =prgAND >>1; + int OR =prgOR >>1; + setprg16(0x8000, MMC24_reg[0] &AND | OR &~AND); + setprg16(0xC000, 0xFF &AND | OR &~AND); + setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]); + setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]); + setmirror(MMC24_reg[5] &1? MI_H: MI_V); +} + +static DECLFW(MMC24_writeReg) { + MMC24_reg[(A >>12) -0xA] =V; + sync(); +} + +static void FP_FASTAPASS(1) MMC24_ppuHook(uint32 A) { + uint8 l, h = A >> 8; + if (h >= 0x20 || ((h & 0xF) != 0xF)) return; + l = A & 0xF0; + if (h < 0x10) { + if (l == 0xD0) { + MMC24_reg[6] =0; + sync(); + } else if (l == 0xE0) { + MMC24_reg[6] =1; + sync(); + } + } else { + if (l == 0xD0) { + MMC24_reg[7] =0; + sync(); + } else if (l == 0xE0) { + MMC24_reg[7] =1; + sync(); + } + } +} + +void MMC2_reset(uint8 clearRegs) { + sync =MMC2_sync; + prgAND =0x0F; + PPU_hook =MMC24_ppuHook; + SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg); + sync(); +} + +void MMC4_reset(uint8 clearRegs) { + sync =MMC4_sync; + prgAND =mapperFlags &2? 0x0F: 0x1F; + PPU_hook =MMC24_ppuHook; + SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg); + sync(); +} + +#undef MMC24_reg diff --git a/src/mappers/m468/468_mmc3.h b/src/mappers/m468/468_mmc3.h new file mode 100644 index 000000000..f46c64d7a --- /dev/null +++ b/src/mappers/m468/468_mmc3.h @@ -0,0 +1,80 @@ +#define MMC3_reg regByte +#define MMC3_index regByte[8] +#define MMC3_mirroring regByte[9] +#define MMC3_wram regByte[10] +#define MMC3_reload regByte[11] +#define MMC3_count regByte[12] +#define MMC3_irq regByte[13] +#define MMC3_lastReg regByte[14] + +static void MMC3_sync () { + int chrAND =mapper &0x01? 0xFF: 0x7F; + int OR =prgOR | (misc2 &1? 12: 0); + setprg8(0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | OR &~prgAND); + setprg8(0xA000, MMC3_reg[7] &prgAND | OR &~prgAND); + setprg8(0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | OR &~prgAND); + setprg8(0xE000, 0xFF &prgAND | OR &~prgAND); + setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND); + setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND); + setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND); + setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND); + setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND); + setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND); + setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND); + setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND); + + if (mapper &2) switch(MMC3_mirroring &3) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); break; + case 3: setmirror(MI_1); break; + } else + setmirror(MMC3_mirroring &1? MI_H: MI_V); +} + +static DECLFW(MMC3_writeReg) { + switch(A &0xE001) { + case 0x8000: MMC3_index =V; sync(); break; + case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break; + case 0xA000: MMC3_mirroring =V; sync(); break; + case 0xA001: MMC3_wram =V; sync(); break; + case 0xC000: MMC3_reload =V; break; + case 0xC001: MMC3_count =0; break; + case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xE001: MMC3_irq =1; break; + } +} + +static void MMC3_horizontalBlanking(void) { + MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count; + if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT); +} + +static void FP_FASTAPASS(1) MMC3_ppuHook(uint32 A) { + A &=0x1FFF; + if (MMC3_index &0x80) A ^=0x1000; + if (A <0x1000) + MMC3_lastReg =A >>11; + else + MMC3_lastReg =(A >>10) -2; + if ((MMC3_mirroring &3) ==2) setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); +} + +void MMC3_reset(uint8 clearRegs) { + sync =MMC3_sync; + GameHBIRQHook =MMC3_horizontalBlanking; + if (mapper &2) PPU_hook =MMC3_ppuHook; + prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? (misc2 &2? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; + SetWriteHandler(0x8000, 0xFFFF, MMC3_writeReg); + MMC3_mirroring =1; /* "Legendary Games of NES' 509-in-1"'s menu runs as MMC3 with H mirroring and expects that setting to stay when running a mapper 206 game such as Legend of Valkyrie. */ + sync(); +} + +#undef MMC3_reg +#undef MMC3_index +#undef MMC3_mirroring +#undef MMC3_wram +#undef MMC3_reload +#undef MMC3_count +#undef MMC3_irq +#undef MMC3_lastReg diff --git a/src/mappers/m468/468_nanjing.h b/src/mappers/m468/468_nanjing.h new file mode 100644 index 000000000..fa5f55517 --- /dev/null +++ b/src/mappers/m468/468_nanjing.h @@ -0,0 +1,29 @@ +#define NANJING_reg regByte + +static void NANJING_sync () { + setprg32(0x8000, NANJING_reg[2] <<4 &0x30 | NANJING_reg[0] &0x0F | (NANJING_reg[3] &4? 0x00: 0x03) | prgOR >>2); + setchr8(0); + setmirror(mapperFlags &4? MI_H: MI_V); +} + +static DECLFW(NANJING_writeReg) { + NANJING_reg[A >>8 &3] =V; + sync(); +} + +static void NANJING_horizontalBlanking(void) { + if (NANJING_reg[0] &0x80 && scanline <239) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on PA13 rises. This does not seem possible with the current PPU emulation however. */ + setchr4(0x0000, scanline >=127? 1: 0); + setchr4(0x1000, scanline >=127? 1: 0); + } else + setchr8(0); +} + +void NANJING_reset(uint8 clearRegs) { + sync =NANJING_sync; + GameHBIRQHook = NANJING_horizontalBlanking; + SetWriteHandler(0x5000, 0x53FF, NANJING_writeReg); + sync(); +} + +#undef NANJING_reg diff --git a/src/mappers/m468/468_vrc1.h b/src/mappers/m468/468_vrc1.h new file mode 100644 index 000000000..087e65eac --- /dev/null +++ b/src/mappers/m468/468_vrc1.h @@ -0,0 +1,25 @@ +#define VRC1_reg regByte + +static void VRC1_sync () { + setprg8(0x8000, VRC1_reg[0] &prgAND | prgOR &~prgAND); + setprg8(0xA000, VRC1_reg[2] &prgAND | prgOR &~prgAND); + setprg8(0xC000, VRC1_reg[4] &prgAND | prgOR &~prgAND); + setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); + setchr4(0x0000, VRC1_reg[6] &0x0F | VRC1_reg[1] <<3 &0x10); + setchr4(0x1000, VRC1_reg[7] &0x0F | VRC1_reg[1] <<2 &0x10); + setmirror(VRC1_reg[1] &1? MI_H: MI_V); +} + +static DECLFW(VRC1_writeReg) { + VRC1_reg[A >>12 &7] =V; + sync(); +} + +void VRC1_reset(uint8 clearRegs) { + sync =VRC1_sync; + prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F; + SetWriteHandler(0x8000, 0xFFFF, VRC1_writeReg); + sync(); +} + +#undef VRC1_reg diff --git a/src/mappers/m468/468_vrc24.h b/src/mappers/m468/468_vrc24.h new file mode 100644 index 000000000..9916147bc --- /dev/null +++ b/src/mappers/m468/468_vrc24.h @@ -0,0 +1,92 @@ +#define VRC24_prg regByte +#define VRC24_mirroring regByte[2] +#define VRC24_misc regByte[3] +#define VRC24_chr regWord +#define VRCIRQ_latch regByte[13] +#define VRCIRQ_mode regByte[14] +#define VRCIRQ_count regByte[15] +#define VRCIRQ_cycles regWord[8] + +static void VRC24_sync() { + setprg8(0x8000 ^(VRC24_misc <<13 &0x4000), VRC24_prg[0] &prgAND | prgOR &~prgAND); + setprg8(0xA000, VRC24_prg[1] &prgAND | prgOR &~prgAND); + setprg8(0xC000 ^(VRC24_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND); + setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); + setchr1(0x0000, VRC24_chr[0]); + setchr1(0x0400, VRC24_chr[1]); + setchr1(0x0800, VRC24_chr[2]); + setchr1(0x0C00, VRC24_chr[3]); + setchr1(0x1000, VRC24_chr[4]); + setchr1(0x1400, VRC24_chr[5]); + setchr1(0x1800, VRC24_chr[6]); + setchr1(0x1C00, VRC24_chr[7]); + setmirror(VRC24_mirroring &3 ^(VRC24_mirroring &2? 0: 1)); +} + +static DECLFW(VRC24_writeReg) { + uint8 index; + A =A &0xF000 | (mapper &2? ((A &0xA? 1: 0) | (A &0x5? 2: 0)): ((A &0x5? 1: 0) | (A &0xA? 2: 0))); + switch (A &0xF000) { + case 0x8000: case 0xA000: + VRC24_prg[A >>13 &1] =V; + sync(); + break; + case 0x9000: + if (~A &2) + VRC24_mirroring =V & (mapper &1? 3: 1); + else + if (~A &1 && mapper &1) + VRC24_misc =V; + sync(); + break; + case 0xF000: + if (mapper &1) switch (A &3) { + case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break; + case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break; + case 2: VRCIRQ_mode =V; + if (VRCIRQ_mode &0x02) { + VRCIRQ_count =VRCIRQ_latch; + VRCIRQ_cycles =341; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; + X6502_IRQEnd(FCEU_IQEXT); + break; + } + break; + default: + index =(A -0xB000) >>11 | A >>1 &1; + if (A &1) + VRC24_chr[index] =VRC24_chr[index] & 0x0F | V <<4; + else + VRC24_chr[index] =VRC24_chr[index] &~0x0F | V &0x0F; + sync(); + break; + } +} + +static void FP_FASTAPASS(1) VRCIRQ_cpuCycle(int a) { + while (a--) { + if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) { + if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341; + if (!++VRCIRQ_count) { + VRCIRQ_count =VRCIRQ_latch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +void VRC24_reset(uint8 clearRegs) { + sync =VRC24_sync; + prgAND =mapperFlags &2? 0x0F: 0x1F; + if (mapper &1) MapIRQHook =VRCIRQ_cpuCycle; + SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg); + sync(); +} + +#undef VRC24_prg +#undef VRC24_mirroring +#undef VRC24_misc +#undef VRC24_chr diff --git a/src/mappers/m468/468_vrc3.h b/src/mappers/m468/468_vrc3.h new file mode 100644 index 000000000..5553b2356 --- /dev/null +++ b/src/mappers/m468/468_vrc3.h @@ -0,0 +1,63 @@ +#define VRC3_prg regByte[0] +#define VRC3_latch regWord[0] +#define VRC3_mode regByte[1] +#define VRC3_count regWord[1] + +static void VRC3_sync() { + int AND =prgAND >>1; + int OR =prgOR >>1; + setprg16(0x8000, VRC3_prg &AND | OR &~AND); + setprg16(0xC000, AND | OR &~AND); + setchr8(0); + setmirror(mapperFlags &4? MI_H: MI_V); +} + +static DECLFW(VRC3_writeReg) { + int shift; + switch(A &0xF000) { + case 0x8000: case 0x9000: case 0xA000: case 0xB000: + V &=0xF; + shift =A >>10 &0xC; + VRC3_latch =VRC3_latch &~(0xF <>1; + int OR =prgOR >>1; + setprg16(0x8000, VRC6_prg16 & AND | OR & ~AND); + setprg8(0xC000, VRC6_prg8 &prgAND | prgOR &~prgAND); + setprg8(0xE000, prgAND | prgOR &~prgAND); + setchr1(0x0000, VRC6_chr[0]); + setchr1(0x0400, VRC6_chr[1]); + setchr1(0x0800, VRC6_chr[2]); + setchr1(0x0C00, VRC6_chr[3]); + setchr1(0x1000, VRC6_chr[4]); + setchr1(0x1400, VRC6_chr[5]); + setchr1(0x1800, VRC6_chr[6]); + setchr1(0x1C00, VRC6_chr[7]); + setmirror((VRC6_misc &0xC ^(VRC6_misc &0x8? 0: 0x4)) >>2); +} + +static DECLFW(VRC6_writeReg) { + uint8 index; + switch (A &0xF003) { + case 0x8000: case 0x8001: case 0x8002: case 0x8003: + VRC6_prg16 =V; + sync(); + break; + case 0xB003: + VRC6_misc =V; + sync(); + break; + case 0xC000: case 0xC001: case 0xC002: case 0xC003: + VRC6_prg8 =V; + sync(); + break; + case 0xD000: case 0xD001: case 0xD002: case 0xD003: case 0xE000: case 0xE001: case 0xE002: case 0xE003: + index =(A -0xD000) >>10 | A &3; + VRC6_chr[index] =V; + sync(); + break; + case 0xF000: + VRCIRQ_latch =V; + break; + case 0xF001: + VRCIRQ_mode =V; + if (VRCIRQ_mode &0x02) { + VRCIRQ_count =VRCIRQ_latch; + VRCIRQ_cycles =341; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xF002: + VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +void VRC6_reset(uint8 clearRegs) { + sync =VRC6_sync; + prgAND =mapperFlags &2? 0x0F: 0x1F; + MapIRQHook =VRCIRQ_cpuCycle; + SetWriteHandler(0x8000, 0xFFFF, VRC6_writeReg); + sync(); +} + +#undef VRC6_chr +#undef VRC6_prg16 +#undef VRC6_prg8 +#undef VRC6_misc diff --git a/src/mappers/m468/468_vrc7.h b/src/mappers/m468/468_vrc7.h new file mode 100644 index 000000000..24e5938e7 --- /dev/null +++ b/src/mappers/m468/468_vrc7.h @@ -0,0 +1,82 @@ +#define VRC7_chr regByte +#define VRC7_prg0 regByte[8] +#define VRC7_prg1 regByte[9] +#define VRC7_prg2 regByte[10] +#define VRC7_misc regByte[11] + +static void VRC7_sync() { + setprg8(0x8000, VRC7_prg0 &prgAND | prgOR &~prgAND); + setprg8(0xA000, VRC7_prg1 &prgAND | prgOR &~prgAND); + setprg8(0xC000, VRC7_prg2 &prgAND | prgOR &~prgAND); + setprg8(0xE000, prgAND | prgOR &~prgAND); + setchr1(0x0000, VRC7_chr[0]); + setchr1(0x0400, VRC7_chr[1]); + setchr1(0x0800, VRC7_chr[2]); + setchr1(0x0C00, VRC7_chr[3]); + setchr1(0x1000, VRC7_chr[4]); + setchr1(0x1400, VRC7_chr[5]); + setchr1(0x1800, VRC7_chr[6]); + setchr1(0x1C00, VRC7_chr[7]); + setmirror(VRC7_misc &3 ^(VRC7_misc &2? 0: 1)); +} + +static DECLFW(VRC7_writeReg) { + uint8 index; + A =A &0xF000 | (A &0x18? 1: 0) | (A &0x20? 2: 0); + switch (A &0xF003) { + case 0x8000: + VRC7_prg0 =V; + sync(); + break; + case 0x8001: + VRC7_prg1 =V; + sync(); + break; + case 0x9000: + VRC7_prg2 =V; + sync(); + break; + case 0x9001: case 0x9002: + /* sound */ + break; + case 0xA000: case 0xA001: case 0xB000: case 0xB001: case 0xC000: case 0xC001: case 0xD000: case 0xD001: + index =(A -0xA000) >>11 | A &1; + VRC7_chr[index] =V; + sync(); + break; + case 0xE000: + VRC7_misc =V; + sync(); + break; + case 0xE001: + VRCIRQ_latch =V; + break; + case 0xF000: + VRCIRQ_mode =V; + if (VRCIRQ_mode &0x02) { + VRCIRQ_count =VRCIRQ_latch; + VRCIRQ_cycles =341; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xF001: + VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +void VRC7_reset(uint8 clearRegs) { + sync =VRC7_sync; + prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F; + MapIRQHook =VRCIRQ_cpuCycle; + SetWriteHandler(0x8000, 0xFFFF, VRC7_writeReg); + sync(); +} + +#undef VRC7_chr +#undef VRC7_prg0 +#undef VRC7_prg1 +#undef VRC7_prg2 +#undef VRC7_misc + From 72d0463800cd47302a1fc94ddaa6b23d797ebafb Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 18:00:09 +0800 Subject: [PATCH 09/16] Cleanup volume core options --- src/drivers/libretro/libretro.c | 89 ++++++++++++++++++--------------- src/fceu.h | 3 +- src/sound.c | 3 +- src/sound.h | 3 +- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 9a799078f..49e91b327 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -1857,34 +1857,9 @@ void retro_reset(void) ResetNES(); } -static void set_apu_channels(int chan) -{ - FSettings.SquareVolume[1] = (chan & 1) ? 256 : 0; - FSettings.SquareVolume[0] = (chan & 2) ? 256 : 0; - FSettings.TriangleVolume = (chan & 3) ? 256 : 0; - FSettings.NoiseVolume = (chan & 4) ? 256 : 0; - FSettings.PCMVolume = (chan & 5) ? 256 : 0; -} - #define VOLUME_MAX 256 static void check_variables_volume_levels(void) { - struct { - int channel; - char name[25]; - } apu_channels[] = { - /*{ SND_SQUARE1, "fceumm_apu_square_1" }, - { SND_SQUARE2, "fceumm_apu_square_2" }, - { SND_TRIANGLE, "fceumm_apu_triangle" }, - { SND_NOISE, "fceumm_apu_noise" }, - { SND_DMC, "fceumm_apu_dpcm" },*/ - { SND_FDS, "fceumm_apu_fds" }, - { SND_S5B, "fceumm_apu_s5b" }, - { SND_N163, "fceumm_apu_n163" }, - { SND_VRC6, "fceumm_apu_vrc6" }, - { SND_VRC7, "fceumm_apu_vrc7" }, - { SND_MMC5, "fceumm_apu_mmc5" }, - }; struct retro_variable var = { 0 }; int i = 0; int ssize; @@ -1892,44 +1867,76 @@ static void check_variables_volume_levels(void) { var.key = "fceumm_apu_square_1"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - FSettings.SquareVolume[1] = atoi(var.value); + FSettings.SquareVolume[1] = VOLUME_MAX * atoi(var.value) / 100; } var.key = "fceumm_apu_square_2"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - FSettings.SquareVolume[0] = atoi(var.value); + FSettings.SquareVolume[0] = VOLUME_MAX * atoi(var.value) / 100; } var.key = "fceumm_apu_triangle"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - FSettings.TriangleVolume = atoi(var.value); + FSettings.TriangleVolume = VOLUME_MAX * atoi(var.value) / 100; } var.key = "fceumm_apu_noise"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - FSettings.NoiseVolume = atoi(var.value); + FSettings.NoiseVolume = VOLUME_MAX * atoi(var.value) / 100; } var.key = "fceumm_apu_dpcm"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - FSettings.PCMVolume = atoi(var.value); + FSettings.PCMVolume = VOLUME_MAX * atoi(var.value) / 100; + } + + /* EXPANSION AUDIO VOLUME SETTINGS */ + + var.key = "fceumm_apu_fds"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + int val = VOLUME_MAX * atoi(var.value) / 100; + FCEUI_SetExpSoundVolume(SND_FDS, val); } - ssize = sizeof(apu_channels) / sizeof(apu_channels[0]); - for (i = 0; i < ssize; i++) { - int channel = apu_channels[i].channel; - var.key = apu_channels[i].name; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - int newval = VOLUME_MAX * atoi(var.value) / 100; - if (FCEUI_GetExpSoundVolume(channel) != newval) { - FCEUI_SetExpSoundVolume(channel, newval); - } - } - } + var.key = "fceumm_apu_s5b"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + int val = VOLUME_MAX * atoi(var.value) / 100; + FCEUI_SetExpSoundVolume(SND_S5B, val); + } + + var.key = "fceumm_apu_n163"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + int val = VOLUME_MAX * atoi(var.value) / 100; + FCEUI_SetExpSoundVolume(SND_N163, val); + } + + var.key = "fceumm_apu_vrc6"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + int val = VOLUME_MAX * atoi(var.value) / 100; + FCEUI_SetExpSoundVolume(SND_VRC6, val); + } + + var.key = "fceumm_apu_vrc7"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + int val = VOLUME_MAX * atoi(var.value) / 100; + FCEUI_SetExpSoundVolume(SND_VRC7, val); + } + + var.key = "fceumm_apu_mmc5"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + int val = VOLUME_MAX * atoi(var.value) / 100; + FCEUI_SetExpSoundVolume(SND_MMC5, val); + } } static void check_variables(bool startup) diff --git a/src/fceu.h b/src/fceu.h index 8047dc784..1ffd38627 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -77,11 +77,12 @@ extern uint8 PAL; typedef struct { int PAL; int SoundVolume; - int ExpSoundVolume[6]; int TriangleVolume; int SquareVolume[2]; int NoiseVolume; int PCMVolume; + int ExpSoundVolume[6]; + int GameGenie; /* Current first and last rendered scanlines. */ diff --git a/src/sound.c b/src/sound.c index 2e253c6da..184ba0371 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1168,7 +1168,8 @@ void FCEUI_SetSoundVolume(uint32 volume) { } void FCEUI_SetExpSoundVolume(int ch, uint32 volume) { - FSettings.ExpSoundVolume[ch] = volume; + if ((ch >= SND_VRC6) && (ch < SND_LAST)) + FSettings.ExpSoundVolume[ch] = volume; } int FCEUI_GetExpSoundVolume(int ch) { diff --git a/src/sound.h b/src/sound.h index 1c2c5cc69..8af238ced 100644 --- a/src/sound.h +++ b/src/sound.h @@ -39,8 +39,7 @@ typedef struct { } EXPSOUND; enum EXPSOUNDTYPE { - SND_NORM = 0, - SND_VRC6, + SND_VRC6 = 0, SND_VRC7, SND_FDS, SND_N163, From fc005b0389ebbed1953a42a2e357af88f8b3cb1e Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 18:12:53 +0800 Subject: [PATCH 10/16] Free WRAM upon on PowerOff --- src/ines.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ines.c b/src/ines.c index 5e3fc0fd7..bb9b748d0 100644 --- a/src/ines.c +++ b/src/ines.c @@ -99,6 +99,11 @@ static void Cleanup(void) free(ExtraNTARAM); ExtraNTARAM = NULL; } + if (WRAM) + { + free(WRAM); + WRAM = NULL; + } } static void iNESGI(int h) { From a95ff3e90d9d4268ed21a9416fbb06659fb87d51 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 18:38:58 +0800 Subject: [PATCH 11/16] Update to actions/upload-artifact@v4 --- .github/workflows/compilation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compilation.yml b/.github/workflows/compilation.yml index 02f4cef9e..2b628a16f 100644 --- a/.github/workflows/compilation.yml +++ b/.github/workflows/compilation.yml @@ -27,7 +27,7 @@ jobs: - name: Upload artifacts if: ${{ success() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: fceumm_libretro_ps2-${{ steps.slug.outputs.sha8 }} path: fceumm_libretro_ps2.a From a377f5b46e31fa6089394d212e823c72400e5786 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 18:46:46 +0800 Subject: [PATCH 12/16] Buildfix --- src/mappers/sound/dripsound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mappers/sound/dripsound.c b/src/mappers/sound/dripsound.c index cb6e167af..2dcd7a2d2 100644 --- a/src/mappers/sound/dripsound.c +++ b/src/mappers/sound/dripsound.c @@ -175,7 +175,7 @@ static void DoDRIPSoundHQ(void) { cvbc = SOUNDTS; } -static void DoDripSound(int32 Count) { +static void DoDripSound(int Count) { DRIPSound(); cvbc = Count; } From ebbd29ed813446b51e80ca85428b95227c258611 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 18:52:05 +0800 Subject: [PATCH 13/16] Buildfix2 --- src/mappers/sound/vrc6sound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mappers/sound/vrc6sound.c b/src/mappers/sound/vrc6sound.c index d2a6162ed..bcba274b4 100644 --- a/src/mappers/sound/vrc6sound.c +++ b/src/mappers/sound/vrc6sound.c @@ -187,7 +187,7 @@ static void DoSawVHQ(void) { VRC6Sound.saw.cvbc = SOUNDTS; } -static void VRC6RunSound(int32 Count) { +static void VRC6RunSound(int Count) { DoSQV1(); DoSQV2(); DoSawV(); From f1d7589586c34e3818c84e7514b16ac3b8706128 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Thu, 19 Sep 2024 19:11:44 +0800 Subject: [PATCH 14/16] Fix support for mapper 547 --- src/ppu.c | 14 ++++++++++++-- src/pputile.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/ppu.c b/src/ppu.c index 199cb84b2..a71cac299 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -330,8 +330,12 @@ static DECLFW(B2007) { if (PPUCHRRAM & (1 << (tmp >> 10))) VPage[tmp >> 10][tmp] = V; } else if (tmp < 0x3F00) { - if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) - vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; + if (QTAIHack && (qtaintramreg & 1)) { + QTAINTRAM[((((tmp & 0xF00) >> 10) >> ((qtaintramreg >> 1)) & 1) << 10) | (tmp & 0x3FF)] = V; + } else { + if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) + vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; + } } else { if (!(tmp & 3)) { if (!(tmp & 0xC)) @@ -571,6 +575,12 @@ static void FASTAPASS(1) RefreshLine(int lastpixel) { #include "pputile.h" } #undef PPU_BGFETCH + } else if (QTAIHack) { + #define PPU_VRC5FETCH + for (X1 = firsttile; X1 < lasttile; X1++) { + #include "pputile.h" + } + #undef PPU_VRC5FETCH } else { for (X1 = firsttile; X1 < lasttile; X1++) { #include "pputile.h" diff --git a/src/pputile.h b/src/pputile.h index aca6ae6d2..6633c4cc8 100644 --- a/src/pputile.h +++ b/src/pputile.h @@ -1,6 +1,9 @@ uint8 *C; uint8 cc; uint32 vadr; +#ifdef PPU_VRC5FETCH +uint8 tmpd; +#endif #ifndef PPUT_MMC5SP uint8 zz; @@ -42,6 +45,10 @@ if (X1 >= 2) { #else zz = RefreshAddr & 0x1F; C = vnapage[(RefreshAddr >> 10) & 3]; +#ifdef PPU_VRC5FETCH + tmpd = QTAINTRAM[((((RefreshAddr >> 10) & 3) >> ((qtaintramreg >> 1)) & 1) << 10) | (RefreshAddr & 0x3FF)]; + vofs = ((tmpd & 0x3F) << 12) | ((RefreshAddr >> 12) & 7); /* recalculate VROM offset */ +#endif vadr = (C[RefreshAddr & 0x3ff] << 4) + vofs; /* Fetch name table byte. */ #endif @@ -77,9 +84,22 @@ pshift[1] <<= 8; C += (MMC50x5130 & 0x3) << 18; #elif defined(PPUT_MMC5) C = MMC5BGVRAMADR(vadr); + #else + #ifdef PPU_VRC5FETCH + extern uint8 *VROM; + extern uint32 VROM_size; + if (tmpd & 0x40) { + if ((VROM_size * 8) == 128) { + vadr = ((vadr & 0x07) << 1) | ((vadr & 0x10) >> 4) | ((vadr & 0x3FFE0) >> 1); + } + C = VROM + vadr; + } else { + C = VRAMADR(vadr); + } #else C = VRAMADR(vadr); #endif + #endif #endif #ifdef PPUT_HOOK @@ -95,8 +115,16 @@ pshift[1] <<= 8; pshift[1] |= C[0]; } #else + #ifdef PPU_VRC5FETCH + pshift[0] |= C[0]; + if (tmpd & 0x40) + pshift[1] |= (tmpd & 0x80) ? 0xFF : 0x00; + else + pshift[1] |= C[8]; + #else pshift[0] |= C[0]; pshift[1] |= C[8]; + #endif #endif if ((RefreshAddr & 0x1f) == 0x1f) From 7e7565ec1dad3d8dce2610bb55f12e9ee1104b90 Mon Sep 17 00:00:00 2001 From: libretroadmin Date: Fri, 20 Sep 2024 03:50:41 +0200 Subject: [PATCH 15/16] C89 buildfix --- src/pputile.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pputile.h b/src/pputile.h index 6633c4cc8..0f47e65d7 100644 --- a/src/pputile.h +++ b/src/pputile.h @@ -3,6 +3,8 @@ uint8 cc; uint32 vadr; #ifdef PPU_VRC5FETCH uint8 tmpd; +extern uint8 *VROM; +extern uint32 VROM_size; #endif #ifndef PPUT_MMC5SP @@ -86,12 +88,9 @@ pshift[1] <<= 8; C = MMC5BGVRAMADR(vadr); #else #ifdef PPU_VRC5FETCH - extern uint8 *VROM; - extern uint32 VROM_size; if (tmpd & 0x40) { - if ((VROM_size * 8) == 128) { + if ((VROM_size * 8) == 128) vadr = ((vadr & 0x07) << 1) | ((vadr & 0x10) >> 4) | ((vadr & 0x3FFE0) >> 1); - } C = VROM + vadr; } else { C = VRAMADR(vadr); From bd62855c22e7a25d772d3b8b1f1afeadf8ca7797 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Mon, 23 Sep 2024 05:29:18 +0800 Subject: [PATCH 16/16] Revert commits The recent PR were suppose to be parts of more PR to get the entire codebase complete, or at least where i want it to be and in a better working state for easier update and maintenance. Ive come to the point that it would take a lot of time and effort to get all PRs done since each one has to be modified to suit the current codebase, causing a few minor but suppose to be fixable conversion errors. The repo have diverted too much from the time i made the original fork, causing each merges conflicts and needing manual intervention. The recent incident, the reluctance to accept the changes, the consideration of issue without details, the need for third-party confirmation didnt help in giving motivation to do so and complete this. I have worked a long time not just this repo, but on other cores fixing shit nobody else wanted to take and it still amazes me that my intention are getting questioned in favour of..... I would just rather continue working on my fork rather than starting over. Reverting this would be more beneficial for everyone. History is kept(i hoped), for reference. --- .github/workflows/compilation.yml | 2 +- Makefile.common | 10 +- fceumm_libretro.info | 45 - src/cart.h | 5 - src/drivers/libretro/libretro.c | 124 +- src/drivers/libretro/libretro_core_options.h | 430 +--- src/fceu-types.h | 8 - src/fceu.c | 17 +- src/fceu.h | 2 - src/fds.c | 28 +- src/fds_apu.c | 8 +- src/filter.c | 8 +- src/ines.c | 588 +---- src/ines.h | 333 +-- src/input.c | 4 +- src/mappers/hw/bandai.c | 231 -- src/mappers/hw/bandai.h | 39 - src/mappers/hw/eeprom_93Cx6.c | 173 -- src/mappers/hw/eeprom_93Cx6.h | 28 - src/mappers/hw/eeprom_x24c0x.c | 251 -- src/mappers/hw/eeprom_x24c0x.h | 40 - src/mappers/hw/flashrom.c | 135 - src/mappers/hw/flashrom.h | 30 - src/mappers/hw/fme7.c | 236 -- src/mappers/hw/fme7.h | 47 - src/mappers/hw/jv001.c | 134 - src/mappers/hw/jv001.h | 46 - src/mappers/hw/jyasic.c | 520 ---- src/mappers/hw/jyasic.h | 75 - src/mappers/hw/ks202.c | 137 -- src/mappers/hw/ks202.h | 40 - src/mappers/hw/latch.c | 92 - src/mappers/hw/latch.h | 39 - src/mappers/hw/mmc1.c | 280 --- src/mappers/hw/mmc1.h | 59 - src/mappers/hw/mmc2.c | 150 -- src/mappers/hw/mmc2.h | 48 - src/mappers/hw/mmc3.c | 337 --- src/mappers/hw/mmc3.h | 56 - src/mappers/hw/mmc4.c | 148 -- src/mappers/hw/mmc4.h | 48 - src/mappers/hw/mmc6.c | 285 --- src/mappers/hw/mmc6.h | 26 - src/mappers/hw/n118.c | 127 - src/mappers/hw/n118.h | 44 - src/mappers/hw/pic16c5x.c | 1001 -------- src/mappers/hw/pic16c5x.h | 57 - src/mappers/hw/pic16c5x_ops_00x.inc | 16 - src/mappers/hw/pic16c5x_ops_main.inc | 287 --- src/mappers/hw/txc.c | 138 -- src/mappers/hw/txc.h | 46 - src/mappers/hw/vrc24.c | 277 --- src/mappers/hw/vrc24.h | 74 - src/mappers/hw/vrc6.c | 203 -- src/mappers/hw/vrc6.h | 49 - src/mappers/hw/vrc7.c | 185 -- src/mappers/hw/vrc7.h | 46 - src/mappers/hw/vrcirq.c | 117 - src/mappers/hw/vrcirq.h | 33 - src/mappers/m468/468.c | 270 -- src/mappers/m468/468_cnrom.h | 45 - src/mappers/m468/468_discrete.h | 73 - src/mappers/m468/468_fme7.h | 72 - src/mappers/m468/468_if12.h | 31 - src/mappers/m468/468_lf36.h | 46 - src/mappers/m468/468_mmc1.h | 72 - src/mappers/m468/468_mmc24.h | 67 - src/mappers/m468/468_mmc3.h | 80 - src/mappers/m468/468_nanjing.h | 29 - src/mappers/m468/468_vrc1.h | 25 - src/mappers/m468/468_vrc24.h | 92 - src/mappers/m468/468_vrc3.h | 63 - src/mappers/m468/468_vrc6.h | 72 - src/mappers/m468/468_vrc7.h | 82 - src/mappers/mapinc.h | 37 - src/mappers/mapper.c | 10 - src/mappers/mapper000.c | 73 - src/mappers/mapper001.c | 67 - src/mappers/mapper002.c | 34 - src/mappers/mapper003.c | 33 - src/mappers/mapper004.c | 70 - src/mappers/mapper005.c | 807 ------ src/mappers/mapper006.c | 486 ---- src/mappers/mapper006.h | 262 -- src/mappers/mapper007.c | 33 - src/mappers/mapper009.c | 38 - src/mappers/mapper010.c | 38 - src/mappers/mapper011.c | 32 - src/mappers/mapper012.c | 74 - src/mappers/mapper013.c | 33 - src/mappers/mapper014.c | 107 - src/mappers/mapper015.c | 56 - src/mappers/mapper016.c | 51 - src/mappers/mapper018.c | 163 -- src/mappers/mapper019.c | 252 -- src/mappers/mapper021.c | 31 - src/mappers/mapper022.c | 32 - src/mappers/mapper023.c | 32 - src/mappers/mapper024.c | 44 - src/mappers/mapper025.c | 37 - src/mappers/mapper026.c | 38 - src/mappers/mapper027.c | 34 - src/mappers/mapper028.c | 107 - src/mappers/mapper029.c | 37 - src/mappers/mapper030.c | 144 -- src/mappers/mapper031.c | 74 - src/mappers/mapper032.c | 132 - src/mappers/mapper033.c | 86 - src/mappers/mapper034.c | 149 -- src/mappers/mapper036.c | 55 - src/mappers/mapper037.c | 66 - src/mappers/mapper038.c | 55 - src/mappers/mapper040.c | 113 - src/mappers/mapper041.c | 72 - src/mappers/mapper042.c | 201 -- src/mappers/mapper043.c | 97 - src/mappers/mapper044.c | 63 - src/mappers/mapper045.c | 108 - src/mappers/mapper046.c | 58 - src/mappers/mapper047.c | 65 - src/mappers/mapper048.c | 120 - src/mappers/mapper049.c | 72 - src/mappers/mapper050.c | 90 - src/mappers/mapper051.c | 95 - src/mappers/mapper052.c | 110 - src/mappers/mapper053.c | 79 - src/mappers/mapper055.c | 52 - src/mappers/mapper056.c | 94 - src/mappers/mapper057.c | 90 - src/mappers/mapper058.c | 39 - src/mappers/mapper059.c | 73 - src/mappers/mapper060.c | 52 - src/mappers/mapper061.c | 39 - src/mappers/mapper062.c | 41 - src/mappers/mapper063.c | 55 - src/mappers/mapper064.c | 183 -- src/mappers/mapper065.c | 153 -- src/mappers/mapper066.c | 32 - src/mappers/mapper067.c | 126 - src/mappers/mapper068.c | 150 -- src/mappers/mapper069.c | 37 - src/mappers/mapper070.c | 33 - src/mappers/mapper071.c | 74 - src/mappers/mapper072.c | 80 - src/mappers/mapper073.c | 131 - src/mappers/mapper074.c | 45 - src/mappers/mapper075.c | 91 - src/mappers/mapper076.c | 48 - src/mappers/mapper077.c | 44 - src/mappers/mapper078.c | 43 - src/mappers/mapper079.c | 59 - src/mappers/mapper080.c | 125 - src/mappers/mapper081.c | 32 - src/mappers/mapper082.c | 145 -- src/mappers/mapper083.c | 268 -- src/mappers/mapper085.c | 42 - src/mappers/mapper086.c | 57 - src/mappers/mapper087.c | 55 - src/mappers/mapper088.c | 36 - src/mappers/mapper089.c | 34 - src/mappers/mapper091.c | 162 -- src/mappers/mapper093.c | 33 - src/mappers/mapper094.c | 33 - src/mappers/mapper095.c | 121 - src/mappers/mapper096.c | 71 - src/mappers/mapper097.c | 34 - src/mappers/mapper099.c | 73 - src/mappers/mapper100.c | 167 -- src/mappers/mapper101.c | 55 - src/mappers/mapper103.c | 110 - src/mappers/mapper104.c | 81 - src/mappers/mapper105.c | 74 - src/mappers/mapper106.c | 124 - src/mappers/mapper107.c | 32 - src/mappers/mapper108.c | 98 - src/mappers/mapper111.c | 178 -- src/mappers/mapper112.c | 111 - src/mappers/mapper113.c | 58 - src/mappers/mapper114.c | 117 - src/mappers/mapper115.c | 67 - src/mappers/mapper116.c | 208 -- src/mappers/mapper117.c | 123 - src/mappers/mapper118.c | 75 - src/mappers/mapper119.c | 44 - src/mappers/mapper120.c | 62 - src/mappers/mapper121.c | 129 - src/mappers/mapper123.c | 73 - src/mappers/mapper124.c | 234 -- src/mappers/mapper125.c | 76 - src/mappers/mapper126.c | 201 -- src/mappers/mapper127.c | 116 - src/mappers/mapper128.c | 61 - src/mappers/mapper132.c | 98 - src/mappers/mapper133.c | 59 - src/mappers/mapper134.c | 112 - src/mappers/mapper136.c | 48 - src/mappers/mapper137.c | 77 - src/mappers/mapper138.c | 76 - src/mappers/mapper139.c | 76 - src/mappers/mapper140.c | 55 - src/mappers/mapper141.c | 80 - src/mappers/mapper142.c | 37 - src/mappers/mapper143.c | 41 - src/mappers/mapper144.c | 44 - src/mappers/mapper145.c | 54 - src/mappers/mapper147.c | 49 - src/mappers/mapper148.c | 33 - src/mappers/mapper149.c | 33 - src/mappers/mapper150.c | 102 - src/mappers/mapper152.c | 34 - src/mappers/mapper153.c | 91 - src/mappers/mapper154.c | 73 - src/mappers/mapper155.c | 33 - src/mappers/mapper156.c | 128 - src/mappers/mapper157.c | 290 --- src/mappers/mapper159.c | 37 - src/mappers/mapper160.c | 59 - src/mappers/mapper162.c | 108 - src/mappers/mapper163.c | 114 - src/mappers/mapper164.c | 146 -- src/mappers/mapper165.c | 87 - src/mappers/mapper166.c | 88 - src/mappers/mapper167.c | 88 - src/mappers/mapper168.c | 75 - src/mappers/mapper170.c | 52 - src/mappers/mapper171.c | 58 - src/mappers/mapper172.c | 54 - src/mappers/mapper173.c | 52 - src/mappers/mapper174.c | 37 - src/mappers/mapper175.c | 78 - src/mappers/mapper176.c | 599 ----- src/mappers/mapper177.c | 37 - src/mappers/mapper178.c | 107 - src/mappers/mapper180.c | 33 - src/mappers/mapper183.c | 87 - src/mappers/mapper184.c | 56 - src/mappers/mapper185.c | 63 - src/mappers/mapper186.c | 95 - src/mappers/mapper187.c | 78 - src/mappers/mapper188.c | 47 - src/mappers/mapper189.c | 57 - src/mappers/mapper190.c | 86 - src/mappers/mapper191.c | 45 - src/mappers/mapper192.c | 46 - src/mappers/mapper193.c | 68 - src/mappers/mapper194.c | 45 - src/mappers/mapper195.c | 103 - src/mappers/mapper196.c | 68 - src/mappers/mapper197.c | 121 - src/mappers/mapper198.c | 42 - src/mappers/mapper199.c | 40 - src/mappers/mapper200.c | 38 - src/mappers/mapper201.c | 33 - src/mappers/mapper202.c | 38 - src/mappers/mapper203.c | 33 - src/mappers/mapper204.c | 39 - src/mappers/mapper205.c | 78 - src/mappers/mapper206.c | 37 - src/mappers/mapper208.c | 132 - src/mappers/mapper209.c | 62 - src/mappers/mapper210.c | 146 -- src/mappers/mapper212.c | 48 - src/mappers/mapper214.c | 33 - src/mappers/mapper215.c | 184 -- src/mappers/mapper216.c | 32 - src/mappers/mapper217.c | 33 - src/mappers/mapper218.c | 57 - src/mappers/mapper219.c | 113 - src/mappers/mapper221.c | 92 - src/mappers/mapper222.c | 76 - src/mappers/mapper225.c | 86 - src/mappers/mapper226.c | 85 - src/mappers/mapper227.c | 69 - src/mappers/mapper228.c | 71 - src/mappers/mapper229.c | 38 - src/mappers/mapper230.c | 68 - src/mappers/mapper231.c | 43 - src/mappers/mapper232.c | 62 - src/mappers/mapper233.c | 72 - src/mappers/mapper234.c | 95 - src/mappers/mapper235.c | 78 - src/mappers/mapper236.c | 102 - src/mappers/mapper237.c | 88 - src/mappers/mapper238.c | 54 - src/mappers/mapper240.c | 71 - src/mappers/mapper241.c | 37 - src/mappers/mapper242.c | 79 - src/mappers/mapper244.c | 77 - src/mappers/mapper245.c | 61 - src/mappers/mapper246.c | 99 - src/mappers/mapper249.c | 89 - src/mappers/mapper250.c | 36 - src/mappers/mapper252.c | 93 - src/mappers/mapper254.c | 58 - src/mappers/mapper256.c | 418 ---- src/mappers/mapper257.c | 123 - src/mappers/mapper259.c | 70 - src/mappers/mapper260.c | 119 - src/mappers/mapper261.c | 40 - src/mappers/mapper262.c | 89 - src/mappers/mapper263.c | 47 - src/mappers/mapper265.c | 65 - src/mappers/mapper266.c | 67 - src/mappers/mapper267.c | 69 - src/mappers/mapper268.c | 210 -- src/mappers/mapper269.c | 95 - src/mappers/mapper271.c | 33 - src/mappers/mapper272.c | 162 -- src/mappers/mapper274.c | 84 - src/mappers/mapper277.c | 67 - src/mappers/mapper281.c | 37 - src/mappers/mapper282.c | 41 - src/mappers/mapper283.c | 32 - src/mappers/mapper284.c | 228 -- src/mappers/mapper285.c | 58 - src/mappers/mapper286.c | 98 - src/mappers/mapper287.c | 98 - src/mappers/mapper288.c | 55 - src/mappers/mapper289.c | 81 - src/mappers/mapper290.c | 44 - src/mappers/mapper291.c | 68 - src/mappers/mapper292.c | 80 - src/mappers/mapper293.c | 87 - src/mappers/mapper294.c | 63 - src/mappers/mapper295.c | 44 - src/mappers/mapper297.c | 94 - src/mappers/mapper298.c | 30 - src/mappers/mapper299.c | 37 - src/mappers/mapper300.c | 36 - src/mappers/mapper301.c | 68 - src/mappers/mapper302.c | 54 - src/mappers/mapper303.c | 144 -- src/mappers/mapper304.c | 99 - src/mappers/mapper305.c | 86 - src/mappers/mapper306.c | 75 - src/mappers/mapper307.c | 55 - src/mappers/mapper308.c | 76 - src/mappers/mapper309.c | 83 - src/mappers/mapper310.c | 93 - src/mappers/mapper312.c | 60 - src/mappers/mapper313.c | 78 - src/mappers/mapper314.c | 81 - src/mappers/mapper315.c | 81 - src/mappers/mapper319.c | 92 - src/mappers/mapper320.c | 58 - src/mappers/mapper322.c | 97 - src/mappers/mapper323.c | 74 - src/mappers/mapper324.c | 54 - src/mappers/mapper325.c | 51 - src/mappers/mapper326.c | 89 - src/mappers/mapper327.c | 108 - src/mappers/mapper328.c | 51 - src/mappers/mapper329.c | 37 - src/mappers/mapper330.c | 135 - src/mappers/mapper331.c | 84 - src/mappers/mapper332.c | 89 - src/mappers/mapper333.c | 72 - src/mappers/mapper334.c | 73 - src/mappers/mapper335.c | 77 - src/mappers/mapper336.c | 50 - src/mappers/mapper337.c | 79 - src/mappers/mapper338.c | 39 - src/mappers/mapper339.c | 77 - src/mappers/mapper340.c | 50 - src/mappers/mapper341.c | 39 - src/mappers/mapper342.c | 2304 ------------------ src/mappers/mapper343.c | 54 - src/mappers/mapper344.c | 78 - src/mappers/mapper345.c | 76 - src/mappers/mapper346.c | 84 - src/mappers/mapper347.c | 193 -- src/mappers/mapper348.c | 77 - src/mappers/mapper349.c | 45 - src/mappers/mapper350.c | 88 - src/mappers/mapper351.c | 274 --- src/mappers/mapper352.c | 62 - src/mappers/mapper353.c | 163 -- src/mappers/mapper354.c | 87 - src/mappers/mapper355.c | 135 - src/mappers/mapper355.h | 140 -- src/mappers/mapper356.c | 107 - src/mappers/mapper357.c | 125 - src/mappers/mapper358.c | 41 - src/mappers/mapper359.c | 226 -- src/mappers/mapper360.c | 67 - src/mappers/mapper361.c | 70 - src/mappers/mapper362.c | 92 - src/mappers/mapper364.c | 62 - src/mappers/mapper366.c | 67 - src/mappers/mapper368.c | 123 - src/mappers/mapper369.c | 165 -- src/mappers/mapper370.c | 136 -- src/mappers/mapper372.c | 95 - src/mappers/mapper374.c | 55 - src/mappers/mapper375.c | 65 - src/mappers/mapper376.c | 71 - src/mappers/mapper377.c | 74 - src/mappers/mapper380.c | 64 - src/mappers/mapper381.c | 44 - src/mappers/mapper382.c | 65 - src/mappers/mapper383.c | 121 - src/mappers/mapper385.c | 34 - src/mappers/mapper386.c | 41 - src/mappers/mapper387.c | 41 - src/mappers/mapper388.c | 41 - src/mappers/mapper389.c | 84 - src/mappers/mapper390.c | 90 - src/mappers/mapper391.c | 90 - src/mappers/mapper393.c | 106 - src/mappers/mapper394.c | 140 -- src/mappers/mapper395.c | 78 - src/mappers/mapper396.c | 56 - src/mappers/mapper397.c | 44 - src/mappers/mapper398.c | 92 - src/mappers/mapper399.c | 86 - src/mappers/mapper400.c | 70 - src/mappers/mapper401.c | 97 - src/mappers/mapper402.c | 47 - src/mappers/mapper403.c | 86 - src/mappers/mapper404.c | 65 - src/mappers/mapper406.c | 87 - src/mappers/mapper409.c | 33 - src/mappers/mapper410.c | 96 - src/mappers/mapper411.c | 89 - src/mappers/mapper412.c | 93 - src/mappers/mapper413.c | 147 -- src/mappers/mapper414.c | 60 - src/mappers/mapper415.c | 40 - src/mappers/mapper416.c | 110 - src/mappers/mapper417.c | 115 - src/mappers/mapper418.c | 39 - src/mappers/mapper420.c | 70 - src/mappers/mapper421.c | 41 - src/mappers/mapper428.c | 84 - src/mappers/mapper429.c | 40 - src/mappers/mapper430.c | 77 - src/mappers/mapper431.c | 64 - src/mappers/mapper432.c | 98 - src/mappers/mapper433.c | 44 - src/mappers/mapper434.c | 58 - src/mappers/mapper435.c | 53 - src/mappers/mapper436.c | 66 - src/mappers/mapper437.c | 58 - src/mappers/mapper438.c | 46 - src/mappers/mapper439.c | 66 - src/mappers/mapper441.c | 77 - src/mappers/mapper443.c | 84 - src/mappers/mapper444.c | 92 - src/mappers/mapper445.c | 120 - src/mappers/mapper446.c | 475 ---- src/mappers/mapper447.c | 94 - src/mappers/mapper448.c | 98 - src/mappers/mapper449.c | 59 - src/mappers/mapper450.c | 39 - src/mappers/mapper451.c | 111 - src/mappers/mapper452.c | 80 - src/mappers/mapper453.c | 59 - src/mappers/mapper454.c | 63 - src/mappers/mapper455.c | 79 - src/mappers/mapper456.c | 61 - src/mappers/mapper457.c | 67 - src/mappers/mapper458.c | 82 - src/mappers/mapper459.c | 42 - src/mappers/mapper460.c | 112 - src/mappers/mapper461.c | 40 - src/mappers/mapper463.c | 77 - src/mappers/mapper464.c | 42 - src/mappers/mapper465.c | 62 - src/mappers/mapper466.c | 108 - src/mappers/mapper467.c | 102 - src/mappers/mapper471.c | 52 - src/mappers/mapper500.c | 58 - src/mappers/mapper501.c | 57 - src/mappers/mapper502.c | 68 - src/mappers/mapper512.c | 85 - src/mappers/mapper513.c | 85 - src/mappers/mapper514.c | 95 - src/mappers/mapper516.c | 61 - src/mappers/mapper517.c | 101 - src/mappers/mapper518.c | 109 - src/mappers/mapper519.c | 86 - src/mappers/mapper520.c | 57 - src/mappers/mapper521.c | 52 - src/mappers/mapper522.c | 83 - src/mappers/mapper524.c | 74 - src/mappers/mapper525.c | 87 - src/mappers/mapper526.c | 123 - src/mappers/mapper527.c | 40 - src/mappers/mapper528.c | 98 - src/mappers/mapper529.c | 72 - src/mappers/mapper530.c | 55 - src/mappers/mapper533.c | 48 - src/mappers/mapper535.c | 99 - src/mappers/mapper538.c | 80 - src/mappers/mapper539.c | 115 - src/mappers/mapper541.c | 54 - src/mappers/mapper543.c | 90 - src/mappers/mapper544.c | 119 - src/mappers/mapper547.c | 220 -- src/mappers/mapper548.c | 107 - src/mappers/mapper549.c | 52 - src/mappers/mapper550.c | 89 - src/mappers/mapper553.c | 38 - src/mappers/mapper554.c | 85 - src/mappers/mapper555.c | 133 - src/mappers/mapper556.c | 180 -- src/mappers/mapper557.c | 43 - src/mappers/mapper558.c | 144 -- src/mappers/mapper559.c | 91 - src/mappers/mapper561.c | 293 --- src/mappers/mapper562.c | 590 ----- src/mappers/nsf.c | 858 ------- src/mappers/nsf.h | 84 - src/mappers/nsfe.c | 283 --- src/mappers/nsfe.h | 6 - src/mappers/sound/dripsound.c | 250 -- src/mappers/sound/dripsound.h | 29 - src/mappers/sound/emu2149.c | 431 ---- src/mappers/sound/emu2149.h | 94 - src/mappers/sound/emu2413.c | 1507 ------------ src/mappers/sound/emu2413.h | 237 -- src/mappers/sound/fdssound.c | 417 ---- src/mappers/sound/fdssound.h | 96 - src/mappers/sound/mmc5sound.c | 301 --- src/mappers/sound/mmc5sound.h | 28 - src/mappers/sound/n163sound.c | 326 --- src/mappers/sound/n163sound.h | 32 - src/mappers/sound/s5bsound.c | 324 --- src/mappers/sound/s5bsound.h | 28 - src/mappers/sound/vrc6sound.c | 351 --- src/mappers/sound/vrc6sound.h | 28 - src/mappers/sound/vrc7sound.c | 150 -- src/mappers/sound/vrc7sound.h | 28 - src/mappers/unif3Dblock.c | 109 - src/mappers/unifEt4320.c | 154 -- src/mappers/unifFamicombox.c | 115 - src/mappers/unifKG256.c | 111 - src/mappers/unifT2271.c | 101 - src/mappers/unifTransformer.c | 103 - src/ppu.c | 21 +- src/ppu.h | 15 - src/pputile.h | 27 - src/sound.c | 69 +- src/sound.h | 24 +- src/unif.c | 243 +- src/unif.h | 2 +- src/x6502.c | 25 +- src/x6502.h | 19 +- src/x6502struct.h | 1 - 549 files changed, 248 insertions(+), 56172 deletions(-) delete mode 100644 fceumm_libretro.info delete mode 100644 src/mappers/hw/bandai.c delete mode 100644 src/mappers/hw/bandai.h delete mode 100644 src/mappers/hw/eeprom_93Cx6.c delete mode 100644 src/mappers/hw/eeprom_93Cx6.h delete mode 100644 src/mappers/hw/eeprom_x24c0x.c delete mode 100644 src/mappers/hw/eeprom_x24c0x.h delete mode 100644 src/mappers/hw/flashrom.c delete mode 100644 src/mappers/hw/flashrom.h delete mode 100644 src/mappers/hw/fme7.c delete mode 100644 src/mappers/hw/fme7.h delete mode 100644 src/mappers/hw/jv001.c delete mode 100644 src/mappers/hw/jv001.h delete mode 100644 src/mappers/hw/jyasic.c delete mode 100644 src/mappers/hw/jyasic.h delete mode 100644 src/mappers/hw/ks202.c delete mode 100644 src/mappers/hw/ks202.h delete mode 100644 src/mappers/hw/latch.c delete mode 100644 src/mappers/hw/latch.h delete mode 100644 src/mappers/hw/mmc1.c delete mode 100644 src/mappers/hw/mmc1.h delete mode 100644 src/mappers/hw/mmc2.c delete mode 100644 src/mappers/hw/mmc2.h delete mode 100644 src/mappers/hw/mmc3.c delete mode 100644 src/mappers/hw/mmc3.h delete mode 100644 src/mappers/hw/mmc4.c delete mode 100644 src/mappers/hw/mmc4.h delete mode 100644 src/mappers/hw/mmc6.c delete mode 100644 src/mappers/hw/mmc6.h delete mode 100644 src/mappers/hw/n118.c delete mode 100644 src/mappers/hw/n118.h delete mode 100644 src/mappers/hw/pic16c5x.c delete mode 100644 src/mappers/hw/pic16c5x.h delete mode 100644 src/mappers/hw/pic16c5x_ops_00x.inc delete mode 100644 src/mappers/hw/pic16c5x_ops_main.inc delete mode 100644 src/mappers/hw/txc.c delete mode 100644 src/mappers/hw/txc.h delete mode 100644 src/mappers/hw/vrc24.c delete mode 100644 src/mappers/hw/vrc24.h delete mode 100644 src/mappers/hw/vrc6.c delete mode 100644 src/mappers/hw/vrc6.h delete mode 100644 src/mappers/hw/vrc7.c delete mode 100644 src/mappers/hw/vrc7.h delete mode 100644 src/mappers/hw/vrcirq.c delete mode 100644 src/mappers/hw/vrcirq.h delete mode 100644 src/mappers/m468/468.c delete mode 100644 src/mappers/m468/468_cnrom.h delete mode 100644 src/mappers/m468/468_discrete.h delete mode 100644 src/mappers/m468/468_fme7.h delete mode 100644 src/mappers/m468/468_if12.h delete mode 100644 src/mappers/m468/468_lf36.h delete mode 100644 src/mappers/m468/468_mmc1.h delete mode 100644 src/mappers/m468/468_mmc24.h delete mode 100644 src/mappers/m468/468_mmc3.h delete mode 100644 src/mappers/m468/468_nanjing.h delete mode 100644 src/mappers/m468/468_vrc1.h delete mode 100644 src/mappers/m468/468_vrc24.h delete mode 100644 src/mappers/m468/468_vrc3.h delete mode 100644 src/mappers/m468/468_vrc6.h delete mode 100644 src/mappers/m468/468_vrc7.h delete mode 100644 src/mappers/mapinc.h delete mode 100644 src/mappers/mapper.c delete mode 100644 src/mappers/mapper000.c delete mode 100644 src/mappers/mapper001.c delete mode 100644 src/mappers/mapper002.c delete mode 100644 src/mappers/mapper003.c delete mode 100644 src/mappers/mapper004.c delete mode 100644 src/mappers/mapper005.c delete mode 100644 src/mappers/mapper006.c delete mode 100644 src/mappers/mapper006.h delete mode 100644 src/mappers/mapper007.c delete mode 100644 src/mappers/mapper009.c delete mode 100644 src/mappers/mapper010.c delete mode 100644 src/mappers/mapper011.c delete mode 100644 src/mappers/mapper012.c delete mode 100644 src/mappers/mapper013.c delete mode 100644 src/mappers/mapper014.c delete mode 100644 src/mappers/mapper015.c delete mode 100644 src/mappers/mapper016.c delete mode 100644 src/mappers/mapper018.c delete mode 100644 src/mappers/mapper019.c delete mode 100644 src/mappers/mapper021.c delete mode 100644 src/mappers/mapper022.c delete mode 100644 src/mappers/mapper023.c delete mode 100644 src/mappers/mapper024.c delete mode 100644 src/mappers/mapper025.c delete mode 100644 src/mappers/mapper026.c delete mode 100644 src/mappers/mapper027.c delete mode 100644 src/mappers/mapper028.c delete mode 100644 src/mappers/mapper029.c delete mode 100644 src/mappers/mapper030.c delete mode 100644 src/mappers/mapper031.c delete mode 100644 src/mappers/mapper032.c delete mode 100644 src/mappers/mapper033.c delete mode 100644 src/mappers/mapper034.c delete mode 100644 src/mappers/mapper036.c delete mode 100644 src/mappers/mapper037.c delete mode 100644 src/mappers/mapper038.c delete mode 100644 src/mappers/mapper040.c delete mode 100644 src/mappers/mapper041.c delete mode 100644 src/mappers/mapper042.c delete mode 100644 src/mappers/mapper043.c delete mode 100644 src/mappers/mapper044.c delete mode 100644 src/mappers/mapper045.c delete mode 100644 src/mappers/mapper046.c delete mode 100644 src/mappers/mapper047.c delete mode 100644 src/mappers/mapper048.c delete mode 100644 src/mappers/mapper049.c delete mode 100644 src/mappers/mapper050.c delete mode 100644 src/mappers/mapper051.c delete mode 100644 src/mappers/mapper052.c delete mode 100644 src/mappers/mapper053.c delete mode 100644 src/mappers/mapper055.c delete mode 100644 src/mappers/mapper056.c delete mode 100644 src/mappers/mapper057.c delete mode 100644 src/mappers/mapper058.c delete mode 100644 src/mappers/mapper059.c delete mode 100644 src/mappers/mapper060.c delete mode 100644 src/mappers/mapper061.c delete mode 100644 src/mappers/mapper062.c delete mode 100644 src/mappers/mapper063.c delete mode 100644 src/mappers/mapper064.c delete mode 100644 src/mappers/mapper065.c delete mode 100644 src/mappers/mapper066.c delete mode 100644 src/mappers/mapper067.c delete mode 100644 src/mappers/mapper068.c delete mode 100644 src/mappers/mapper069.c delete mode 100644 src/mappers/mapper070.c delete mode 100644 src/mappers/mapper071.c delete mode 100644 src/mappers/mapper072.c delete mode 100644 src/mappers/mapper073.c delete mode 100644 src/mappers/mapper074.c delete mode 100644 src/mappers/mapper075.c delete mode 100644 src/mappers/mapper076.c delete mode 100644 src/mappers/mapper077.c delete mode 100644 src/mappers/mapper078.c delete mode 100644 src/mappers/mapper079.c delete mode 100644 src/mappers/mapper080.c delete mode 100644 src/mappers/mapper081.c delete mode 100644 src/mappers/mapper082.c delete mode 100644 src/mappers/mapper083.c delete mode 100644 src/mappers/mapper085.c delete mode 100644 src/mappers/mapper086.c delete mode 100644 src/mappers/mapper087.c delete mode 100644 src/mappers/mapper088.c delete mode 100644 src/mappers/mapper089.c delete mode 100644 src/mappers/mapper091.c delete mode 100644 src/mappers/mapper093.c delete mode 100644 src/mappers/mapper094.c delete mode 100644 src/mappers/mapper095.c delete mode 100644 src/mappers/mapper096.c delete mode 100644 src/mappers/mapper097.c delete mode 100644 src/mappers/mapper099.c delete mode 100644 src/mappers/mapper100.c delete mode 100644 src/mappers/mapper101.c delete mode 100644 src/mappers/mapper103.c delete mode 100644 src/mappers/mapper104.c delete mode 100644 src/mappers/mapper105.c delete mode 100644 src/mappers/mapper106.c delete mode 100644 src/mappers/mapper107.c delete mode 100644 src/mappers/mapper108.c delete mode 100644 src/mappers/mapper111.c delete mode 100644 src/mappers/mapper112.c delete mode 100644 src/mappers/mapper113.c delete mode 100644 src/mappers/mapper114.c delete mode 100644 src/mappers/mapper115.c delete mode 100644 src/mappers/mapper116.c delete mode 100644 src/mappers/mapper117.c delete mode 100644 src/mappers/mapper118.c delete mode 100644 src/mappers/mapper119.c delete mode 100644 src/mappers/mapper120.c delete mode 100644 src/mappers/mapper121.c delete mode 100644 src/mappers/mapper123.c delete mode 100644 src/mappers/mapper124.c delete mode 100644 src/mappers/mapper125.c delete mode 100644 src/mappers/mapper126.c delete mode 100644 src/mappers/mapper127.c delete mode 100644 src/mappers/mapper128.c delete mode 100644 src/mappers/mapper132.c delete mode 100644 src/mappers/mapper133.c delete mode 100644 src/mappers/mapper134.c delete mode 100644 src/mappers/mapper136.c delete mode 100644 src/mappers/mapper137.c delete mode 100644 src/mappers/mapper138.c delete mode 100644 src/mappers/mapper139.c delete mode 100644 src/mappers/mapper140.c delete mode 100644 src/mappers/mapper141.c delete mode 100644 src/mappers/mapper142.c delete mode 100644 src/mappers/mapper143.c delete mode 100644 src/mappers/mapper144.c delete mode 100644 src/mappers/mapper145.c delete mode 100644 src/mappers/mapper147.c delete mode 100644 src/mappers/mapper148.c delete mode 100644 src/mappers/mapper149.c delete mode 100644 src/mappers/mapper150.c delete mode 100644 src/mappers/mapper152.c delete mode 100644 src/mappers/mapper153.c delete mode 100644 src/mappers/mapper154.c delete mode 100644 src/mappers/mapper155.c delete mode 100644 src/mappers/mapper156.c delete mode 100644 src/mappers/mapper157.c delete mode 100644 src/mappers/mapper159.c delete mode 100644 src/mappers/mapper160.c delete mode 100644 src/mappers/mapper162.c delete mode 100644 src/mappers/mapper163.c delete mode 100644 src/mappers/mapper164.c delete mode 100644 src/mappers/mapper165.c delete mode 100644 src/mappers/mapper166.c delete mode 100644 src/mappers/mapper167.c delete mode 100644 src/mappers/mapper168.c delete mode 100644 src/mappers/mapper170.c delete mode 100644 src/mappers/mapper171.c delete mode 100644 src/mappers/mapper172.c delete mode 100644 src/mappers/mapper173.c delete mode 100644 src/mappers/mapper174.c delete mode 100644 src/mappers/mapper175.c delete mode 100644 src/mappers/mapper176.c delete mode 100644 src/mappers/mapper177.c delete mode 100644 src/mappers/mapper178.c delete mode 100644 src/mappers/mapper180.c delete mode 100644 src/mappers/mapper183.c delete mode 100644 src/mappers/mapper184.c delete mode 100644 src/mappers/mapper185.c delete mode 100644 src/mappers/mapper186.c delete mode 100644 src/mappers/mapper187.c delete mode 100644 src/mappers/mapper188.c delete mode 100644 src/mappers/mapper189.c delete mode 100644 src/mappers/mapper190.c delete mode 100644 src/mappers/mapper191.c delete mode 100644 src/mappers/mapper192.c delete mode 100644 src/mappers/mapper193.c delete mode 100644 src/mappers/mapper194.c delete mode 100644 src/mappers/mapper195.c delete mode 100644 src/mappers/mapper196.c delete mode 100644 src/mappers/mapper197.c delete mode 100644 src/mappers/mapper198.c delete mode 100644 src/mappers/mapper199.c delete mode 100644 src/mappers/mapper200.c delete mode 100644 src/mappers/mapper201.c delete mode 100644 src/mappers/mapper202.c delete mode 100644 src/mappers/mapper203.c delete mode 100644 src/mappers/mapper204.c delete mode 100644 src/mappers/mapper205.c delete mode 100644 src/mappers/mapper206.c delete mode 100644 src/mappers/mapper208.c delete mode 100644 src/mappers/mapper209.c delete mode 100644 src/mappers/mapper210.c delete mode 100644 src/mappers/mapper212.c delete mode 100644 src/mappers/mapper214.c delete mode 100644 src/mappers/mapper215.c delete mode 100644 src/mappers/mapper216.c delete mode 100644 src/mappers/mapper217.c delete mode 100644 src/mappers/mapper218.c delete mode 100644 src/mappers/mapper219.c delete mode 100644 src/mappers/mapper221.c delete mode 100644 src/mappers/mapper222.c delete mode 100644 src/mappers/mapper225.c delete mode 100644 src/mappers/mapper226.c delete mode 100644 src/mappers/mapper227.c delete mode 100644 src/mappers/mapper228.c delete mode 100644 src/mappers/mapper229.c delete mode 100644 src/mappers/mapper230.c delete mode 100644 src/mappers/mapper231.c delete mode 100644 src/mappers/mapper232.c delete mode 100644 src/mappers/mapper233.c delete mode 100644 src/mappers/mapper234.c delete mode 100644 src/mappers/mapper235.c delete mode 100644 src/mappers/mapper236.c delete mode 100644 src/mappers/mapper237.c delete mode 100644 src/mappers/mapper238.c delete mode 100644 src/mappers/mapper240.c delete mode 100644 src/mappers/mapper241.c delete mode 100644 src/mappers/mapper242.c delete mode 100644 src/mappers/mapper244.c delete mode 100644 src/mappers/mapper245.c delete mode 100644 src/mappers/mapper246.c delete mode 100644 src/mappers/mapper249.c delete mode 100644 src/mappers/mapper250.c delete mode 100644 src/mappers/mapper252.c delete mode 100644 src/mappers/mapper254.c delete mode 100644 src/mappers/mapper256.c delete mode 100644 src/mappers/mapper257.c delete mode 100644 src/mappers/mapper259.c delete mode 100644 src/mappers/mapper260.c delete mode 100644 src/mappers/mapper261.c delete mode 100644 src/mappers/mapper262.c delete mode 100644 src/mappers/mapper263.c delete mode 100644 src/mappers/mapper265.c delete mode 100644 src/mappers/mapper266.c delete mode 100644 src/mappers/mapper267.c delete mode 100644 src/mappers/mapper268.c delete mode 100644 src/mappers/mapper269.c delete mode 100644 src/mappers/mapper271.c delete mode 100644 src/mappers/mapper272.c delete mode 100644 src/mappers/mapper274.c delete mode 100644 src/mappers/mapper277.c delete mode 100644 src/mappers/mapper281.c delete mode 100644 src/mappers/mapper282.c delete mode 100644 src/mappers/mapper283.c delete mode 100644 src/mappers/mapper284.c delete mode 100644 src/mappers/mapper285.c delete mode 100644 src/mappers/mapper286.c delete mode 100644 src/mappers/mapper287.c delete mode 100644 src/mappers/mapper288.c delete mode 100644 src/mappers/mapper289.c delete mode 100644 src/mappers/mapper290.c delete mode 100644 src/mappers/mapper291.c delete mode 100644 src/mappers/mapper292.c delete mode 100644 src/mappers/mapper293.c delete mode 100644 src/mappers/mapper294.c delete mode 100644 src/mappers/mapper295.c delete mode 100644 src/mappers/mapper297.c delete mode 100644 src/mappers/mapper298.c delete mode 100644 src/mappers/mapper299.c delete mode 100644 src/mappers/mapper300.c delete mode 100644 src/mappers/mapper301.c delete mode 100644 src/mappers/mapper302.c delete mode 100644 src/mappers/mapper303.c delete mode 100644 src/mappers/mapper304.c delete mode 100644 src/mappers/mapper305.c delete mode 100644 src/mappers/mapper306.c delete mode 100644 src/mappers/mapper307.c delete mode 100644 src/mappers/mapper308.c delete mode 100644 src/mappers/mapper309.c delete mode 100644 src/mappers/mapper310.c delete mode 100644 src/mappers/mapper312.c delete mode 100644 src/mappers/mapper313.c delete mode 100644 src/mappers/mapper314.c delete mode 100644 src/mappers/mapper315.c delete mode 100644 src/mappers/mapper319.c delete mode 100644 src/mappers/mapper320.c delete mode 100644 src/mappers/mapper322.c delete mode 100644 src/mappers/mapper323.c delete mode 100644 src/mappers/mapper324.c delete mode 100644 src/mappers/mapper325.c delete mode 100644 src/mappers/mapper326.c delete mode 100644 src/mappers/mapper327.c delete mode 100644 src/mappers/mapper328.c delete mode 100644 src/mappers/mapper329.c delete mode 100644 src/mappers/mapper330.c delete mode 100644 src/mappers/mapper331.c delete mode 100644 src/mappers/mapper332.c delete mode 100644 src/mappers/mapper333.c delete mode 100644 src/mappers/mapper334.c delete mode 100644 src/mappers/mapper335.c delete mode 100644 src/mappers/mapper336.c delete mode 100644 src/mappers/mapper337.c delete mode 100644 src/mappers/mapper338.c delete mode 100644 src/mappers/mapper339.c delete mode 100644 src/mappers/mapper340.c delete mode 100644 src/mappers/mapper341.c delete mode 100644 src/mappers/mapper342.c delete mode 100644 src/mappers/mapper343.c delete mode 100644 src/mappers/mapper344.c delete mode 100644 src/mappers/mapper345.c delete mode 100644 src/mappers/mapper346.c delete mode 100644 src/mappers/mapper347.c delete mode 100644 src/mappers/mapper348.c delete mode 100644 src/mappers/mapper349.c delete mode 100644 src/mappers/mapper350.c delete mode 100644 src/mappers/mapper351.c delete mode 100644 src/mappers/mapper352.c delete mode 100644 src/mappers/mapper353.c delete mode 100644 src/mappers/mapper354.c delete mode 100644 src/mappers/mapper355.c delete mode 100644 src/mappers/mapper355.h delete mode 100644 src/mappers/mapper356.c delete mode 100644 src/mappers/mapper357.c delete mode 100644 src/mappers/mapper358.c delete mode 100644 src/mappers/mapper359.c delete mode 100644 src/mappers/mapper360.c delete mode 100644 src/mappers/mapper361.c delete mode 100644 src/mappers/mapper362.c delete mode 100644 src/mappers/mapper364.c delete mode 100644 src/mappers/mapper366.c delete mode 100644 src/mappers/mapper368.c delete mode 100644 src/mappers/mapper369.c delete mode 100644 src/mappers/mapper370.c delete mode 100644 src/mappers/mapper372.c delete mode 100644 src/mappers/mapper374.c delete mode 100644 src/mappers/mapper375.c delete mode 100644 src/mappers/mapper376.c delete mode 100644 src/mappers/mapper377.c delete mode 100644 src/mappers/mapper380.c delete mode 100644 src/mappers/mapper381.c delete mode 100644 src/mappers/mapper382.c delete mode 100644 src/mappers/mapper383.c delete mode 100644 src/mappers/mapper385.c delete mode 100644 src/mappers/mapper386.c delete mode 100644 src/mappers/mapper387.c delete mode 100644 src/mappers/mapper388.c delete mode 100644 src/mappers/mapper389.c delete mode 100644 src/mappers/mapper390.c delete mode 100644 src/mappers/mapper391.c delete mode 100644 src/mappers/mapper393.c delete mode 100644 src/mappers/mapper394.c delete mode 100644 src/mappers/mapper395.c delete mode 100644 src/mappers/mapper396.c delete mode 100644 src/mappers/mapper397.c delete mode 100644 src/mappers/mapper398.c delete mode 100644 src/mappers/mapper399.c delete mode 100644 src/mappers/mapper400.c delete mode 100644 src/mappers/mapper401.c delete mode 100644 src/mappers/mapper402.c delete mode 100644 src/mappers/mapper403.c delete mode 100644 src/mappers/mapper404.c delete mode 100644 src/mappers/mapper406.c delete mode 100644 src/mappers/mapper409.c delete mode 100644 src/mappers/mapper410.c delete mode 100644 src/mappers/mapper411.c delete mode 100644 src/mappers/mapper412.c delete mode 100644 src/mappers/mapper413.c delete mode 100644 src/mappers/mapper414.c delete mode 100644 src/mappers/mapper415.c delete mode 100644 src/mappers/mapper416.c delete mode 100644 src/mappers/mapper417.c delete mode 100644 src/mappers/mapper418.c delete mode 100644 src/mappers/mapper420.c delete mode 100644 src/mappers/mapper421.c delete mode 100644 src/mappers/mapper428.c delete mode 100644 src/mappers/mapper429.c delete mode 100644 src/mappers/mapper430.c delete mode 100644 src/mappers/mapper431.c delete mode 100644 src/mappers/mapper432.c delete mode 100644 src/mappers/mapper433.c delete mode 100644 src/mappers/mapper434.c delete mode 100644 src/mappers/mapper435.c delete mode 100644 src/mappers/mapper436.c delete mode 100644 src/mappers/mapper437.c delete mode 100644 src/mappers/mapper438.c delete mode 100644 src/mappers/mapper439.c delete mode 100644 src/mappers/mapper441.c delete mode 100644 src/mappers/mapper443.c delete mode 100644 src/mappers/mapper444.c delete mode 100644 src/mappers/mapper445.c delete mode 100644 src/mappers/mapper446.c delete mode 100644 src/mappers/mapper447.c delete mode 100644 src/mappers/mapper448.c delete mode 100644 src/mappers/mapper449.c delete mode 100644 src/mappers/mapper450.c delete mode 100644 src/mappers/mapper451.c delete mode 100644 src/mappers/mapper452.c delete mode 100644 src/mappers/mapper453.c delete mode 100644 src/mappers/mapper454.c delete mode 100644 src/mappers/mapper455.c delete mode 100644 src/mappers/mapper456.c delete mode 100644 src/mappers/mapper457.c delete mode 100644 src/mappers/mapper458.c delete mode 100644 src/mappers/mapper459.c delete mode 100644 src/mappers/mapper460.c delete mode 100644 src/mappers/mapper461.c delete mode 100644 src/mappers/mapper463.c delete mode 100644 src/mappers/mapper464.c delete mode 100644 src/mappers/mapper465.c delete mode 100644 src/mappers/mapper466.c delete mode 100644 src/mappers/mapper467.c delete mode 100644 src/mappers/mapper471.c delete mode 100644 src/mappers/mapper500.c delete mode 100644 src/mappers/mapper501.c delete mode 100644 src/mappers/mapper502.c delete mode 100644 src/mappers/mapper512.c delete mode 100644 src/mappers/mapper513.c delete mode 100644 src/mappers/mapper514.c delete mode 100644 src/mappers/mapper516.c delete mode 100644 src/mappers/mapper517.c delete mode 100644 src/mappers/mapper518.c delete mode 100644 src/mappers/mapper519.c delete mode 100644 src/mappers/mapper520.c delete mode 100644 src/mappers/mapper521.c delete mode 100644 src/mappers/mapper522.c delete mode 100644 src/mappers/mapper524.c delete mode 100644 src/mappers/mapper525.c delete mode 100644 src/mappers/mapper526.c delete mode 100644 src/mappers/mapper527.c delete mode 100644 src/mappers/mapper528.c delete mode 100644 src/mappers/mapper529.c delete mode 100644 src/mappers/mapper530.c delete mode 100644 src/mappers/mapper533.c delete mode 100644 src/mappers/mapper535.c delete mode 100644 src/mappers/mapper538.c delete mode 100644 src/mappers/mapper539.c delete mode 100644 src/mappers/mapper541.c delete mode 100644 src/mappers/mapper543.c delete mode 100644 src/mappers/mapper544.c delete mode 100644 src/mappers/mapper547.c delete mode 100644 src/mappers/mapper548.c delete mode 100644 src/mappers/mapper549.c delete mode 100644 src/mappers/mapper550.c delete mode 100644 src/mappers/mapper553.c delete mode 100644 src/mappers/mapper554.c delete mode 100644 src/mappers/mapper555.c delete mode 100644 src/mappers/mapper556.c delete mode 100644 src/mappers/mapper557.c delete mode 100644 src/mappers/mapper558.c delete mode 100644 src/mappers/mapper559.c delete mode 100644 src/mappers/mapper561.c delete mode 100644 src/mappers/mapper562.c delete mode 100644 src/mappers/nsf.c delete mode 100644 src/mappers/nsf.h delete mode 100644 src/mappers/nsfe.c delete mode 100644 src/mappers/nsfe.h delete mode 100644 src/mappers/sound/dripsound.c delete mode 100644 src/mappers/sound/dripsound.h delete mode 100644 src/mappers/sound/emu2149.c delete mode 100644 src/mappers/sound/emu2149.h delete mode 100644 src/mappers/sound/emu2413.c delete mode 100644 src/mappers/sound/emu2413.h delete mode 100644 src/mappers/sound/fdssound.c delete mode 100644 src/mappers/sound/fdssound.h delete mode 100644 src/mappers/sound/mmc5sound.c delete mode 100644 src/mappers/sound/mmc5sound.h delete mode 100644 src/mappers/sound/n163sound.c delete mode 100644 src/mappers/sound/n163sound.h delete mode 100644 src/mappers/sound/s5bsound.c delete mode 100644 src/mappers/sound/s5bsound.h delete mode 100644 src/mappers/sound/vrc6sound.c delete mode 100644 src/mappers/sound/vrc6sound.h delete mode 100644 src/mappers/sound/vrc7sound.c delete mode 100644 src/mappers/sound/vrc7sound.h delete mode 100644 src/mappers/unif3Dblock.c delete mode 100644 src/mappers/unifEt4320.c delete mode 100644 src/mappers/unifFamicombox.c delete mode 100644 src/mappers/unifKG256.c delete mode 100644 src/mappers/unifT2271.c delete mode 100644 src/mappers/unifTransformer.c diff --git a/.github/workflows/compilation.yml b/.github/workflows/compilation.yml index 2b628a16f..02f4cef9e 100644 --- a/.github/workflows/compilation.yml +++ b/.github/workflows/compilation.yml @@ -27,7 +27,7 @@ jobs: - name: Upload artifacts if: ${{ success() }} - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v2 with: name: fceumm_libretro_ps2-${{ steps.slug.outputs.sha8 }} path: fceumm_libretro_ps2.a diff --git a/Makefile.common b/Makefile.common index 68d3132b0..d0ca21d0a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -5,9 +5,7 @@ INCFLAGS := \ -I$(LIBRETRO_COMM_DIR)/include \ -I$(CORE_DIR) \ -I$(CORE_DIR)/input \ - -I$(CORE_DIR)/mappers \ - -I$(CORE_DIR)/mappers/hw \ - -I$(CORE_DIR)/mappers/sound + -I$(CORE_DIR)/boards ifneq (,$(findstring msvc2003,$(platform))) INCFLAGS += -I$(LIBRETRO_COMM_DIR)/include/compat/msvc @@ -20,10 +18,7 @@ COREDEFINES = \ -DFRONTEND_SUPPORTS_RGB565 FCEU_SRC_DIRS := \ - $(CORE_DIR)/mappers \ - $(CORE_DIR)/mappers/m468 \ - $(CORE_DIR)/mappers/hw \ - $(CORE_DIR)/mappers/sound \ + $(CORE_DIR)/boards \ $(CORE_DIR)/input SOURCES_C := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c)) @@ -51,6 +46,7 @@ SOURCES_C += \ $(CORE_DIR)/general.c \ $(CORE_DIR)/input.c \ $(CORE_DIR)/md5.c \ + $(CORE_DIR)/nsf.c \ $(CORE_DIR)/palette.c \ $(CORE_DIR)/ppu.c \ $(CORE_DIR)/sound.c \ diff --git a/fceumm_libretro.info b/fceumm_libretro.info deleted file mode 100644 index 7dfd3e40b..000000000 --- a/fceumm_libretro.info +++ /dev/null @@ -1,45 +0,0 @@ -# Software Information -display_name = "Nintendo - NES / Famicom (FCEUmm)" -authors = "FCEU Team|CaH4e3" -supported_extensions = "fds|nes|unif|unf|nsf|nsfe" -corename = "FCEUmm" -license = "GPLv2" -permissions = "" -display_version = "SVN" -categories = "Emulator" - -# Hardware Information -manufacturer = "Nintendo" -systemname = "Nintendo Entertainment System" -systemid = "nes" - -# Libretro Features -supports_no_game = "false" -savestate = "true" -savestate_features = "deterministic" -cheats = "true" -input_descriptors = "true" -memory_descriptors = "true" -libretro_saves = "true" -core_options = "true" -core_options_version = "1.0" -load_subsystem = "false" -hw_render = "false" -needs_fullpath = "false" -disk_control = "false" -database = "Nintendo - Nintendo Entertainment System|Nintendo - Family Computer Disk System" - -# BIOS / Firmware -firmware_count = 3 -firmware0_desc = "disksys.rom (Family Computer Disk System BIOS)" -firmware0_path = "disksys.rom" -firmware0_opt = "true" -firmware1_desc = "nes.pal (custom NES Palette)" -firmware1_path = "nes.pal" -firmware1_opt = "true" -firmware2_desc = "gamegenie.nes (Game Genie add-on cartridge)" -firmware2_path = "gamegenie.nes" -firmware2_opt = "true" -notes = "(!) disksys.rom (md5): ca30b50f880eb660a320674ed365ef7a|(!) gamegenie.nes (md5): 7f98d77d7a094ad7d069b74bd553ec98|(!) nes.pal must be located in system directory." - -description = "FCEUmm libretro is based on the FCEUmm (mappers modified) fork of the FCEU emulator. It is very fast and supports many mappers, including those for weird, obscure bootleg carts. It is tightly integrated with libretro features, which makes it a good choice for users seeking advanced frontend functionality, such as runahead and rollback netplay. While most NES emulators are lightweight, FCEUmm's particularly low resource requirements make it a good option for mobile, low-power/embedded and console targets." diff --git a/src/cart.h b/src/cart.h index c76688702..457340364 100644 --- a/src/cart.h +++ b/src/cart.h @@ -35,13 +35,8 @@ typedef struct { * code, used by mapper/board code, maybe * other code in the future. */ - - int HasTrainer; /* indicated the presence of trainer rom data */ - int HasMisc; /* indicated the presence of misc rom data */ } CartInfo; -extern CartInfo iNESCart; - extern uint8 *Page[32], *VPage[8], *MMC5SPRVPage[8], *MMC5BGVPage[8]; void ResetCartMapping(void); diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c index 49e91b327..843661063 100644 --- a/src/drivers/libretro/libretro.c +++ b/src/drivers/libretro/libretro.c @@ -1464,17 +1464,11 @@ static bool update_option_visibility(void) "fceumm_sndlowpass", "fceumm_sndstereodelay", "fceumm_swapduty", - "fceumm_apu_square_1", - "fceumm_apu_square_2", - "fceumm_apu_triangle", - "fceumm_apu_noise", - "fceumm_apu_dpcm", - "fceumm_apu_fds", - "fceumm_apu_s5b", - "fceumm_apu_n163", - "fceumm_apu_vrc6", - "fceumm_apu_vrc7", - "fceumm_apu_mmc5" + "fceumm_apu_1", + "fceumm_apu_2", + "fceumm_apu_3", + "fceumm_apu_4", + "fceumm_apu_5" }; option_display.visible = opt_showAdvSoundOptions; @@ -1677,7 +1671,7 @@ void retro_set_environment(retro_environment_t cb) void retro_get_system_info(struct retro_system_info *info) { info->need_fullpath = true; - info->valid_extensions = "fds|nes|unf|unif|nsf|nsfe"; + info->valid_extensions = "fds|nes|unf|unif"; #ifdef GIT_VERSION info->library_version = "(SVN)" GIT_VERSION; #else @@ -1857,93 +1851,20 @@ void retro_reset(void) ResetNES(); } -#define VOLUME_MAX 256 - -static void check_variables_volume_levels(void) { - struct retro_variable var = { 0 }; - int i = 0; - int ssize; - - var.key = "fceumm_apu_square_1"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - FSettings.SquareVolume[1] = VOLUME_MAX * atoi(var.value) / 100; - } - - var.key = "fceumm_apu_square_2"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - FSettings.SquareVolume[0] = VOLUME_MAX * atoi(var.value) / 100; - } - - var.key = "fceumm_apu_triangle"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - FSettings.TriangleVolume = VOLUME_MAX * atoi(var.value) / 100; - } - - var.key = "fceumm_apu_noise"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - FSettings.NoiseVolume = VOLUME_MAX * atoi(var.value) / 100; - } - - var.key = "fceumm_apu_dpcm"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - FSettings.PCMVolume = VOLUME_MAX * atoi(var.value) / 100; - } - - /* EXPANSION AUDIO VOLUME SETTINGS */ - - var.key = "fceumm_apu_fds"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - int val = VOLUME_MAX * atoi(var.value) / 100; - FCEUI_SetExpSoundVolume(SND_FDS, val); - } - - var.key = "fceumm_apu_s5b"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - int val = VOLUME_MAX * atoi(var.value) / 100; - FCEUI_SetExpSoundVolume(SND_S5B, val); - } - - var.key = "fceumm_apu_n163"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - int val = VOLUME_MAX * atoi(var.value) / 100; - FCEUI_SetExpSoundVolume(SND_N163, val); - } - - var.key = "fceumm_apu_vrc6"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - int val = VOLUME_MAX * atoi(var.value) / 100; - FCEUI_SetExpSoundVolume(SND_VRC6, val); - } - - var.key = "fceumm_apu_vrc7"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - int val = VOLUME_MAX * atoi(var.value) / 100; - FCEUI_SetExpSoundVolume(SND_VRC7, val); - } - - var.key = "fceumm_apu_mmc5"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - int val = VOLUME_MAX * atoi(var.value) / 100; - FCEUI_SetExpSoundVolume(SND_MMC5, val); - } +static void set_apu_channels(int chan) +{ + FSettings.SquareVolume[1] = (chan & 1) ? 256 : 0; + FSettings.SquareVolume[0] = (chan & 2) ? 256 : 0; + FSettings.TriangleVolume = (chan & 3) ? 256 : 0; + FSettings.NoiseVolume = (chan & 4) ? 256 : 0; + FSettings.PCMVolume = (chan & 5) ? 256 : 0; } static void check_variables(bool startup) { struct retro_variable var = {0}; char key[256]; - int i; + int i, enable_apu; bool stereo_filter_updated = false; /* 1 = Performs only geometry update: e.g. overscans */ @@ -2377,7 +2298,8 @@ static void check_variables(bool startup) if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - sndvolume = (unsigned)((float)VOLUME_MAX * atof(var.value) / 200.0f); + int val = (int)(atof(var.value) * 25.6); + sndvolume = val; FCEUD_SoundToggle(); } @@ -2400,7 +2322,19 @@ static void check_variables(bool startup) swapDuty = newval; } - check_variables_volume_levels(); + var.key = key; + + enable_apu = 0xff; + + strcpy(key, "fceumm_apu_x"); + for (i = 0; i < 5; i++) + { + key[strlen("fceumm_apu_")] = '1' + i; + var.value = NULL; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && !strcmp(var.value, "disabled")) + enable_apu &= ~(1 << i); + } + set_apu_channels(enable_apu); update_dipswitch(); diff --git a/src/drivers/libretro/libretro_core_options.h b/src/drivers/libretro/libretro_core_options.h index c5507ff2b..f13118b54 100644 --- a/src/drivers/libretro/libretro_core_options.h +++ b/src/drivers/libretro/libretro_core_options.h @@ -381,418 +381,94 @@ struct retro_core_option_v2_definition option_defs[] = { "fceumm_sndvolume", "Master Volume", NULL, - "Change master volume level %.", + "Change master volume level.", NULL, "audio", { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { "100", NULL }, - { "105", NULL }, - { "110", NULL }, - { "115", NULL }, - { "120", NULL }, - { "125", NULL }, - { "130", NULL }, - { "135", NULL }, - { "140", NULL }, - { "145", NULL }, - { "150", NULL }, - { "155", NULL }, - { "160", NULL }, - { "165", NULL }, - { "170", NULL }, - { "175", NULL }, - { "180", NULL }, - { "185", NULL }, - { "190", NULL }, - { "195", NULL }, - { "200", NULL }, + { "0", "0%" }, + { "1", "10%" }, + { "2", "20%" }, + { "3", "30%" }, + { "4", "40%" }, + { "5", "50%" }, + { "6", "60%" }, + { "7", "70%" }, + { "8", "80%" }, + { "9", "90%" }, + { "10", "100%" }, { NULL, NULL }, }, - "100", - }, - { - "fceumm_apu_square_1", - "Channel Volume (Square 1)", - NULL, - "Change pulse wave generator 1 audio output.", - NULL, - "audio", - { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, - }, - "100", - }, - { - "fceumm_apu_square_2", - "Channel Volume (Square 2)", - NULL, - "Change pulse wave generator 2 audio output.", - NULL, - "audio", - { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, - }, - "100", - }, - { - "fceumm_apu_triangle", - "Channel Volume (Triangle)", - NULL, - "Modify triangle wave generator audio output.", - NULL, - "audio", - { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, - }, - "100", - }, - { - "fceumm_apu_noise", - "Channel Volume (Noise)", - NULL, - "Change noise generator audio output.", - NULL, - "audio", - { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, - }, - "100", - }, - { - "fceumm_apu_dpcm", - "Channel Volume (DPCM)", - NULL, - "Change delta modulation channel audio output.", - NULL, - "audio", - { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, - }, - "100", - }, - { - "fceumm_apu_fds", - "Channel Volume (FDS)", - NULL, - "Change FDS expansion audio output.", - NULL, - "audio", - { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, - }, - "100", + "7", }, { - "fceumm_apu_s5b", - "Channel Volume (S5B)", - NULL, - "Change Sunsoft S5B expansion audio output.", + "fceumm_apu_1", + "Audio Channel 1 (Square 1)", + "Channel 1 (Square 1)", + "Enables or disables pulse wave generator audio output 1.", NULL, "audio", { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL }, }, - "100", + "enabled", }, { - "fceumm_apu_n163", - "Channel Volume (N163)", - NULL, - "Chnage Namco 163 expansion audio output.", + "fceumm_apu_2", + "Audio Channel 2 (Square 2)", + "Channel 2 (Square 2)", + "Enables or disables pulse wave generator audio output 2.", NULL, "audio", { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL }, }, - "100", + "enabled", }, { - "fceumm_apu_vrc6", - "Channel Volume (VRC6)", - NULL, - "Change VRC6 expansion audio output.", + "fceumm_apu_3", + "Audio Channel 3 (Triangle)", + "Channel 3 (Triangle)", + "Enables or disables triangle wave generator audio output.", NULL, "audio", { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL }, }, - "100", + "enabled", }, { - "fceumm_apu_vrc7", - "Channel Volume (VRC7)", - NULL, - "Change VRC7 expansion audio output.", + "fceumm_apu_4", + "Audio Channel 4 (Noise)", + "Channel 4 (Noise)", + "Enables or disables noise generator audio output.", NULL, "audio", { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL }, }, - "100", + "enabled", }, { - "fceumm_apu_mmc5", - "Channel Volume (MMC5)", - NULL, - "Change MMC5 expansion audio output.", + "fceumm_apu_5", + "Audio Channel 5 (PCM)", + "Channel 5 (PCM)", + "Enables or disables delta modulation channel audio output.", NULL, "audio", { - { "0", NULL }, - { "5", NULL }, - { "10", NULL }, - { "15", NULL }, - { "20", NULL }, - { "25", NULL }, - { "30", NULL }, - { "35", NULL }, - { "40", NULL }, - { "45", NULL }, - { "50", NULL }, - { "55", NULL }, - { "60", NULL }, - { "65", NULL }, - { "70", NULL }, - { "75", NULL }, - { "80", NULL }, - { "85", NULL }, - { "90", NULL }, - { "95", NULL }, - { "100", NULL }, - { NULL, NULL }, + { "enabled", NULL }, + { "disabled", NULL }, + { NULL, NULL }, }, - "100", + "enabled", }, { "fceumm_turbo_enable", diff --git a/src/fceu-types.h b/src/fceu-types.h index ef70b8de8..0ea2f4b56 100644 --- a/src/fceu-types.h +++ b/src/fceu-types.h @@ -75,14 +75,6 @@ typedef long long int64; #define FASTAPASS(x) #endif -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - typedef void (FP_FASTAPASS(2) *writefunc)(uint32 A, uint8 V); typedef uint8 (FP_FASTAPASS(1) *readfunc)(uint32 A); diff --git a/src/fceu.c b/src/fceu.c index 5026b086d..35c172b4a 100644 --- a/src/fceu.c +++ b/src/fceu.c @@ -209,8 +209,6 @@ void FCEUI_CloseGame(void) void ResetGameLoaded(void) { - int i; - if (GameInfo) FCEUI_CloseGame(); @@ -218,12 +216,8 @@ void ResetGameLoaded(void) PPU_hook = NULL; GameHBIRQHook = NULL; - for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { - if (GameExpSound[i].Kill) { - GameExpSound[i].Kill(); - } - } - + if (GameExpSound.Kill) + GameExpSound.Kill(); memset(&GameExpSound, 0, sizeof(GameExpSound)); MapIRQHook = NULL; @@ -242,7 +236,6 @@ FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *databuf, size_t databufs frontend_post_load_init_cb_t frontend_post_load_init_cb) { FCEUFILE *fp; - int i; ResetGameLoaded(); @@ -321,12 +314,6 @@ int FCEUI_Initialize(void) { FSettings.UsrLastSLine[0] = 231; FSettings.UsrLastSLine[1] = 239; FSettings.SoundVolume = 100; - FSettings.ExpSoundVolume[0] = 256; - FSettings.ExpSoundVolume[1] = 256; - FSettings.ExpSoundVolume[2] = 256; - FSettings.ExpSoundVolume[3] = 256; - FSettings.ExpSoundVolume[4] = 256; - FSettings.ExpSoundVolume[5] = 256; FCEUPPU_Init(); X6502_Init(); return 1; diff --git a/src/fceu.h b/src/fceu.h index 1ffd38627..7588e7747 100644 --- a/src/fceu.h +++ b/src/fceu.h @@ -81,8 +81,6 @@ typedef struct { int SquareVolume[2]; int NoiseVolume; int PCMVolume; - int ExpSoundVolume[6]; - int GameGenie; /* Current first and last rendered scanlines. */ diff --git a/src/fds.c b/src/fds.c index 171e46f07..196fbd043 100644 --- a/src/fds.c +++ b/src/fds.c @@ -38,8 +38,6 @@ #include "cart.h" #include "md5.h" -#include "mappers/sound/fdssound.h" - /* TODO: Add code to put a delay in between the time a disk is inserted * and the when it can be successfully read/written to. This should * prevent writes to wrong places OR add code to prevent disk ejects @@ -156,27 +154,7 @@ static void FDSInit(void) { IRQCount = IRQLatch = IRQa = 0; - /* FDSSoundReset(); */ - - FDSSoundRegReset(); - FDSSound_SC(); - - SetReadHandler(0x4040, 0x407F, FDSWaveRead); - SetReadHandler(0x4090, 0x4090, FDSEnvVolumeRead); - SetReadHandler(0x4092, 0x4092, FDSEnvModRead); - - SetWriteHandler(0x4040, 0x407F, FDSWaveWrite); - SetWriteHandler(0x4080, 0x4080, FDSSReg0Write); - SetWriteHandler(0x4082, 0x4082, FDSSReg1Write); - SetWriteHandler(0x4083, 0x4083, FDSSReg2Write); - SetWriteHandler(0x4084, 0x4084, FDSSReg3Write); - SetWriteHandler(0x4085, 0x4085, FDSSReg4Write); - SetWriteHandler(0x4086, 0x4086, FDSSReg5Write); - SetWriteHandler(0x4087, 0x4087, FDSSReg6Write); - SetWriteHandler(0x4088, 0x4088, FDSSReg7Write); - SetWriteHandler(0x4089, 0x4089, FDSSReg8Write); - SetWriteHandler(0x408A, 0x408A, FDSSReg9Write); - + FDSSoundReset(); InDisk = 0; SelectDisk = 0; @@ -713,7 +691,7 @@ int FDSLoad(const char *name, FCEUFILE *fp) { InDisk = 255; ResetExState(PreSave, PostSave); - /* FDSSoundStateAdd(); */ + FDSSoundStateAdd(); for (x = 0; x < TotalSides; x++) { char temp[5]; @@ -745,8 +723,6 @@ int FDSLoad(const char *name, FCEUFILE *fp) { AddExState(&mapperFDS_diskaddr, 2 | FCEUSTATE_RLSB, 1, "DADR"); AddExState(&mapperFDS_diskaccess, 1, 0, "DACC"); - FDSSound_AddStateInfo(); - CHRRAMSize = 8192; CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1); diff --git a/src/fds_apu.c b/src/fds_apu.c index 2268788c7..f57d480a2 100644 --- a/src/fds_apu.c +++ b/src/fds_apu.c @@ -276,10 +276,10 @@ static void FDS_ESI(void) { void FDSSoundReset(void) { memset(&fdso, 0, sizeof(fdso)); FDS_ESI(); - GameExpSound[SND_FDS].HiSync = HQSync; - GameExpSound[SND_FDS].HiFill = RenderSoundHQ; - GameExpSound[SND_FDS].Fill = FDSSound; - GameExpSound[SND_FDS].RChange = FDS_ESI; + GameExpSound.HiSync = HQSync; + GameExpSound.HiFill = RenderSoundHQ; + GameExpSound.Fill = FDSSound; + GameExpSound.RChange = FDS_ESI; } uint8 FDSSoundRead(uint32 A) { diff --git a/src/filter.c b/src/filter.c index 78611162f..fcc752e8d 100644 --- a/src/filter.c +++ b/src/filter.c @@ -87,7 +87,6 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) { int32 *outsave = out; int32 count = 0; uint32 max = (inlen - 1) << 16; - int i; if (FSettings.soundq == 2) { for (x = mrindex; x < max; x += mrratio) { @@ -133,11 +132,8 @@ int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover) { *leftover = NCOEFFS + 1; } - for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { - if (GameExpSound[i].NeoFill) { - GameExpSound[i].NeoFill(outsave, count); - } - } + if (GameExpSound.NeoFill) + GameExpSound.NeoFill(outsave, count); SexyFilter(outsave, outsave, count); if (FSettings.lowpass) diff --git a/src/ines.c b/src/ines.c index bb9b748d0..01e7901af 100644 --- a/src/ines.c +++ b/src/ines.c @@ -43,6 +43,7 @@ extern SFORMAT FCEUVSUNI_STATEINFO[]; +uint8 *trainerpoo = NULL; uint8 *ROM = NULL; uint8 *VROM = NULL; uint8 *ExtraNTARAM = NULL; @@ -58,18 +59,18 @@ static int CHRRAMSize = -1; static int iNES_Init(int num); static DECLFR(TrainerRead) { - return(miscROM[A & 0x1FF]); + return(trainerpoo[A & 0x1FF]); } static void iNES_ExecPower() { if (iNESCart.Power) iNESCart.Power(); - if (iNESCart.HasTrainer) { + if (trainerpoo) { int x; for (x = 0; x < 512; x++) { - X6502_DMW(0x7000 + x, miscROM[x]); - if (X6502_DMR(0x7000 + x) != miscROM[x]) { + X6502_DMW(0x7000 + x, trainerpoo[x]); + if (X6502_DMR(0x7000 + x) != trainerpoo[x]) { SetReadHandler(0x7000, 0x71FF, TrainerRead); break; } @@ -77,35 +78,6 @@ static void iNES_ExecPower() { } } -static void Cleanup(void) -{ - if (ROM) - { - free(ROM); - ROM = NULL; - } - if (VROM) - { - free(VROM); - VROM = NULL; - } - if (miscROM) - { - free(miscROM); - miscROM = NULL; - } - if (ExtraNTARAM) - { - free(ExtraNTARAM); - ExtraNTARAM = NULL; - } - if (WRAM) - { - free(WRAM); - WRAM = NULL; - } -} - static void iNESGI(int h) { switch (h) { @@ -119,7 +91,22 @@ static void iNESGI(int h) { case GI_CLOSE: if (iNESCart.Close) iNESCart.Close(); - Cleanup(); + if (ROM) { + free(ROM); + ROM = NULL; + } + if (VROM) { + free(VROM); + VROM = NULL; + } + if (trainerpoo) { + free(trainerpoo); + trainerpoo = NULL; + } + if (ExtraNTARAM) { + free(ExtraNTARAM); + ExtraNTARAM = NULL; + } break; } } @@ -433,7 +420,6 @@ typedef struct { #define INES_BOARD_END() { (uint8_t*)"", 0, NULL} }; #define INES_BOARD(a, b, c) { (uint8_t*)a, b, c }, -#if 0 INES_BOARD_BEGIN() INES_BOARD( "NROM", 0, NROM_Init ) INES_BOARD( "MMC1", 1, Mapper1_Init ) @@ -893,495 +879,6 @@ INES_BOARD_BEGIN() INES_BOARD( "", 550, Mapper550_Init ) INES_BOARD( "YC-03-09", 558, Mapper558_Init ) INES_BOARD_END() -#endif - -INES_BOARD_BEGIN() - INES_BOARD( "NROM", 0, Mapper000_Init ) - INES_BOARD( "MMC1", 1, Mapper001_Init ) - INES_BOARD( "UNROM", 2, Mapper002_Init ) - INES_BOARD( "CNROM", 3, Mapper003_Init ) - INES_BOARD( "MMC3", 4, Mapper004_Init ) - INES_BOARD( "MMC5", 5, Mapper005_Init ) - INES_BOARD( "FFE Magic Card 1M/2M", 6, Mapper006_Init ) - INES_BOARD( "ANROM", 7, Mapper007_Init ) - INES_BOARD( "FFE Magic Card 1M/2M", 8, Mapper006_Init ) /* mapper 6, submapper 4 */ - INES_BOARD( "MMC2", 9, Mapper009_Init ) - INES_BOARD( "MMC4", 10, Mapper010_Init ) - INES_BOARD( "Color Dreams", 11, Mapper011_Init ) - INES_BOARD( "REX DBZ 5/ FFE Magic Cart 4M", 12, Mapper012_Init ) - INES_BOARD( "CPROM", 13, Mapper013_Init ) - INES_BOARD( "REX SL-1632", 14, Mapper014_Init ) - INES_BOARD( "100-in-1", 15, Mapper015_Init ) - INES_BOARD( "BANDAI 24C02", 16, Mapper016_Init ) - INES_BOARD( "FFE Magic Card", 17, Mapper006_Init ) - INES_BOARD( "JALECO SS880006", 18, Mapper018_Init ) /* JF-NNX (EB89018-30007) boards */ - INES_BOARD( "Namco 129/163", 19, Mapper019_Init ) -/* INES_BOARD( "", 20, Mapper20_Init ) */ - INES_BOARD( "Konami VRC2/VRC4 A", 21, Mapper021_Init ) - INES_BOARD( "Konami VRC2/VRC4 B", 22, Mapper022_Init ) - INES_BOARD( "Konami VRC2/VRC4 C", 23, Mapper023_Init ) - INES_BOARD( "Konami VRC6 Rev. A", 24, Mapper024_Init ) - INES_BOARD( "Konami VRC2/VRC4 D", 25, Mapper025_Init ) - INES_BOARD( "Konami VRC6 Rev. B", 26, Mapper026_Init ) - INES_BOARD( "CC-21 MI HUN CHE", 27, Mapper027_Init ) /* Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards */ - INES_BOARD( "Action 53", 28, Mapper028_Init ) - INES_BOARD( "RET-CUFROM", 29, Mapper029_Init ) - INES_BOARD( "UNROM 512", 30, Mapper030_Init ) - INES_BOARD( "infineteNesLives-NSF", 31, Mapper031_Init ) - INES_BOARD( "IREM G-101", 32, Mapper032_Init ) - INES_BOARD( "Taito TC0190FMC/TC0350FMR", 33, Mapper033_Init ) - INES_BOARD( "BNROM/NINA-001", 34, Mapper034_Init ) - INES_BOARD( "EL870914C", 35, Mapper035_Init ) - INES_BOARD( "TXC Policeman", 36, Mapper036_Init ) - INES_BOARD( "PAL-ZZ SMB/TETRIS/NWC", 37, Mapper037_Init ) - INES_BOARD( "Bit Corp.", 38, Mapper038_Init ) /* Crime Busters */ -/* INES_BOARD( "", 39, Mapper39_Init ) */ - INES_BOARD( "SMB2j FDS", 40, Mapper040_Init ) - INES_BOARD( "CALTRON 6-in-1", 41, Mapper041_Init ) - INES_BOARD( "BIO MIRACLE FDS", 42, Mapper042_Init ) - INES_BOARD( "FDS SMB2j LF36", 43, Mapper043_Init ) - INES_BOARD( "MMC3 BMC PIRATE A", 44, Mapper044_Init ) - INES_BOARD( "MMC3 BMC PIRATE B", 45, Mapper045_Init ) - INES_BOARD( "RUMBLESTATION 15-in-1", 46, Mapper046_Init ) - INES_BOARD( "NES-QJ SSVB/NWC", 47, Mapper047_Init ) - INES_BOARD( "Taito TC0690/TC190+PAL16R4", 48, Mapper048_Init ) - INES_BOARD( "MMC3 BMC PIRATE C", 49, Mapper049_Init ) - INES_BOARD( "SMB2j FDS Rev. A", 50, Mapper050_Init ) - INES_BOARD( "11-in-1 BALL SERIES", 51, Mapper051_Init ) /* 1993 year version */ - INES_BOARD( "MMC3 BMC PIRATE D", 52, Mapper052_Init ) - INES_BOARD( "SUPERVISION 16-in-1", 53, Mapper053_Init ) -/* INES_BOARD( "", 54, Mapper54_Init ) */ - INES_BOARD( "MARIO1-MALEE2", 55, Mapper055_Init ) - INES_BOARD( "UNLKS202", 56, Mapper056_Init ) - INES_BOARD( "SIMBPLE BMC PIRATE A", 57, Mapper057_Init ) - INES_BOARD( "SIMBPLE BMC PIRATE B", 58, Mapper058_Init ) - INES_BOARD( "BMC T3H53/D1038", 59, Mapper059_Init ) - INES_BOARD( "Reset-based NROM-128 ", 60, Mapper060_Init ) - INES_BOARD( "20-in-1 KAISER Rev. A", 61, Mapper061_Init ) - INES_BOARD( "700-in-1", 62, Mapper062_Init ) - INES_BOARD( "Powerful 250-in-1 (NTDEC TH2291)", 63, Mapper063_Init ) - INES_BOARD( "TENGEN RAMBO1", 64, Mapper064_Init ) - INES_BOARD( "IREM-H3001", 65, Mapper065_Init ) - INES_BOARD( "GNROM / MHROM", 66, Mapper066_Init ) - INES_BOARD( "SUNSOFT-FZII", 67, Mapper067_Init ) - INES_BOARD( "Sunsoft Mapper #4", 68, Mapper068_Init ) - INES_BOARD( "SUNSOFT-5/FME-7", 69, Mapper069_Init ) - INES_BOARD( "BA KAMEN DISCRETE", 70, Mapper070_Init ) - INES_BOARD( "CAMERICA BF9093", 71, Mapper071_Init ) - INES_BOARD( "JALECO JF-17", 72, Mapper072_Init ) - INES_BOARD( "KONAMI VRC3", 73, Mapper073_Init ) - INES_BOARD( "TW MMC3+VRAM Rev. A", 74, Mapper074_Init ) - INES_BOARD( "KONAMI VRC1", 75, Mapper075_Init ) - INES_BOARD( "NAMCOT 108 Rev. A", 76, Mapper076_Init ) - INES_BOARD( "IREM LROG017", 77, Mapper077_Init ) - INES_BOARD( "Irem 74HC161/32", 78, Mapper078_Init ) - INES_BOARD( "AVE/C&E/TXC BOARD", 79, Mapper079_Init ) - INES_BOARD( "TAITO X1-005 Rev. A", 80, Mapper080_Init ) - INES_BOARD( "Super Gun (NTDEC N715021)", 81, Mapper081_Init ) - INES_BOARD( "TAITO X1-017", 82, Mapper082_Init ) - INES_BOARD( "YOKO VRC Rev. B", 83, Mapper083_Init ) -/* INES_BOARD( "", 84, Mapper84_Init ) */ - INES_BOARD( "KONAMI VRC7", 85, Mapper085_Init ) - INES_BOARD( "JALECO JF-13", 86, Mapper086_Init ) - INES_BOARD( "74*139/74 DISCRETE", 87, Mapper087_Init ) - INES_BOARD( "NAMCO 3433", 88, Mapper088_Init ) - INES_BOARD( "SUNSOFT-3", 89, Mapper089_Init ) /* SUNSOFT-2 mapper */ - INES_BOARD( "HUMMER/JY BOARD", 90, Mapper090_Init ) - INES_BOARD( "JY830623C/YY840238C/EJ-006-1", 91, Mapper091_Init ) - INES_BOARD( "JALECO JF-19", 92, Mapper072_Init ) - INES_BOARD( "SUNSOFT-3R", 93, Mapper093_Init ) /* SUNSOFT-2 mapper with VRAM, different wiring */ - INES_BOARD( "HVC-UN1ROM", 94, Mapper094_Init ) - INES_BOARD( "NAMCOT 108 Rev. B", 95, Mapper095_Init ) - INES_BOARD( "BANDAI OEKAKIDS", 96, Mapper096_Init ) - INES_BOARD( "IREM TAM-S1", 97, Mapper097_Init ) -/* INES_BOARD( "", 98, Mapper98_Init ) */ - INES_BOARD( "Vs. System", 99, Mapper099_Init ) - INES_BOARD( "Nesticle MMC3", 100, Mapper100_Init ) - INES_BOARD( "", 101, Mapper101_Init ) -/* INES_BOARD( "", 102, Mapper102_Init ) */ - INES_BOARD( "FDS DOKIDOKI FULL", 103, Mapper103_Init ) - INES_BOARD( "CAMERICA GOLDENFIVE", 104, Mapper104_Init ) - INES_BOARD( "NES-EVENT NWC1990", 105, Mapper105_Init ) - INES_BOARD( "SMB3 PIRATE A", 106, Mapper106_Init ) - INES_BOARD( "MAGIC CORP A", 107, Mapper107_Init ) - INES_BOARD( "FDS UNROM BOARD", 108, Mapper108_Init ) -/* INES_BOARD( "", 109, Mapper109_Init ) */ -/* INES_BOARD( "", 110, Mapper110_Init ) */ - INES_BOARD( "Cheapocabra", 111, Mapper111_Init ) - INES_BOARD( "ASDER/NTDEC BOARD", 112, Mapper112_Init ) - INES_BOARD( "HACKER/SACHEN BOARD", 113, Mapper113_Init ) - INES_BOARD( "MMC3 SG PROT. A", 114, Mapper114_Init ) - INES_BOARD( "MMC3 PIRATE A", 115, Mapper115_Init ) - INES_BOARD( "MMC1/MMC3/VRC PIRATE", 116, Mapper116_Init ) - INES_BOARD( "FUTURE MEDIA BOARD", 117, Mapper117_Init ) - INES_BOARD( "TSKROM", 118, Mapper118_Init ) - INES_BOARD( "TQROM", 119, Mapper119_Init ) - INES_BOARD( "FDS TOBIDASE", 120, Mapper120_Init ) - INES_BOARD( "MMC3 PIRATE PROT. A", 121, Mapper121_Init ) -/* INES_BOARD( "", 122, Mapper122_Init ) */ - INES_BOARD( "MMC3 PIRATE H2288", 123, Mapper123_Init ) - INES_BOARD( "Super Game Mega Type III", 124, Mapper124_Init ) - INES_BOARD( "FDS LH32", 125, Mapper125_Init ) - INES_BOARD( "PowerJoy 84-in-1 PJ-008", 126, Mapper126_Init ) - INES_BOARD( "Double Dragon II (Pirate)", 127, Mapper127_Init ) - INES_BOARD( "1994 Super HiK 4-in-1", 128, Mapper128_Init ) -/* INES_BOARD( "", 129, Mapper129_Init ) */ -/* INES_BOARD( "", 130, Mapper130_Init ) */ -/* INES_BOARD( "", 131, Mapper131_Init ) */ - INES_BOARD( "TXC/UNL-22211", 132, Mapper132_Init ) - INES_BOARD( "SA72008", 133, Mapper133_Init ) - INES_BOARD( "MMC3 BMC PIRATE", 134, Mapper134_Init ) -/* INES_BOARD( "", 135, Mapper135_Init ) */ /* Duplicate of 135 */ - INES_BOARD( "Sachen 3011", 136, Mapper136_Init ) - INES_BOARD( "S8259D", 137, Mapper137_Init ) - INES_BOARD( "S8259B", 138, Mapper138_Init ) - INES_BOARD( "S8259C", 139, Mapper139_Init ) - INES_BOARD( "JALECO JF-11/14", 140, Mapper140_Init ) - INES_BOARD( "S8259A", 141, Mapper141_Init ) - INES_BOARD( "UNLKS7032", 142, Mapper142_Init ) - INES_BOARD( "TCA01", 143, Mapper143_Init ) - INES_BOARD( "AGCI 50282", 144, Mapper144_Init ) - INES_BOARD( "SA72007", 145, Mapper145_Init ) -/* INES_BOARD( "", 146, SA0161M_Init ) */ /* moved to mapper 79 */ - INES_BOARD( "Sachen 3018 board", 147, Mapper147_Init ) - INES_BOARD( "SA0037", 148, Mapper148_Init ) - INES_BOARD( "SA0036", 149, Mapper149_Init ) - INES_BOARD( "SA-015/SA-630", 150, Mapper150_Init ) - INES_BOARD( "Vs. Unisystem (Konami)", 151, Mapper151_Init ) /* legacy support. all fixed roms should be using mapper 75 */ - INES_BOARD( "", 152, Mapper152_Init ) - INES_BOARD( "BANDAI SRAM", 153, Mapper153_Init ) /* Bandai board 16 with SRAM instead of EEPROM */ - INES_BOARD( "", 154, Mapper154_Init ) - INES_BOARD( "", 155, Mapper155_Init ) - INES_BOARD( "", 156, Mapper156_Init ) - INES_BOARD( "BANDAI BARCODE", 157, Mapper157_Init ) - INES_BOARD( "TENGEN 800037", 158, Mapper064_Init ) - INES_BOARD( "BANDAI 24C01", 159, Mapper159_Init ) /* Different type of EEPROM on the bandai board */ -/* INES_BOARD( "SA009", 160, Mapper160_Init ) */ -/* INES_BOARD( "", 161, Mapper161_Init ) */ - INES_BOARD( "", 162, Mapper162_Init ) - INES_BOARD( "", 163, Mapper163_Init ) - INES_BOARD( "", 164, Mapper164_Init ) - INES_BOARD( "", 165, Mapper165_Init ) - INES_BOARD( "SUBOR Rev. A", 166, Mapper166_Init ) - INES_BOARD( "SUBOR Rev. B", 167, Mapper167_Init ) - INES_BOARD( "", 168, Mapper168_Init ) -/* INES_BOARD( "", 169, Mapper169_Init ) */ - INES_BOARD( "", 170, Mapper170_Init ) - INES_BOARD( "Kaiser 7058", 171, Mapper171_Init ) - INES_BOARD( "Super Mega P-4070", 172, Mapper172_Init ) - INES_BOARD( "Idea-Tek ET.xx", 173, Mapper173_Init ) - INES_BOARD( "NTDec 5-in-1", 174, Mapper174_Init ) - INES_BOARD( "", 175, Mapper175_Init ) - INES_BOARD( "BMCFK23C", 176, Mapper176_Init ) - INES_BOARD( "Hénggé Diànzǐ", 177, Mapper177_Init ) - INES_BOARD( "FS305/NJ0430", 178, Mapper178_Init ) -/* INES_BOARD( "", 179, Mapper179_Init ) */ - INES_BOARD( "", 180, Mapper180_Init ) -/* INES_BOARD( "", 181, Mapper181_Init ) */ /* fceux' exclusive mapper to handle Seicross V2, now moved to Mapper 185,sub 4 */ -/* INES_BOARD( "", 182, Mapper182_Init ) */ /* Deprecated, dupe of Mapper 114 */ - INES_BOARD( "", 183, Mapper183_Init ) - INES_BOARD( "", 184, Mapper184_Init ) - INES_BOARD( "CNROM+CopyProtection", 185, Mapper185_Init ) - INES_BOARD( "", 186, Mapper186_Init ) - INES_BOARD( "", 187, Mapper187_Init ) - INES_BOARD( "", 188, Mapper188_Init ) - INES_BOARD( "", 189, Mapper189_Init ) - INES_BOARD( "", 190, Mapper190_Init ) - INES_BOARD( "", 191, Mapper191_Init ) - INES_BOARD( "TW MMC3+VRAM Rev. B", 192, Mapper192_Init ) - INES_BOARD( "NTDEC TC-112", 193, Mapper193_Init ) /* War in the Gulf */ - INES_BOARD( "TW MMC3+VRAM Rev. C", 194, Mapper194_Init ) - INES_BOARD( "TW MMC3+VRAM Rev. D", 195, Mapper195_Init ) - INES_BOARD( "", 196, Mapper196_Init ) - INES_BOARD( "", 197, Mapper197_Init ) - INES_BOARD( "TW MMC3+VRAM Rev. E", 198, Mapper198_Init ) - INES_BOARD( "", 199, Mapper199_Init ) - INES_BOARD( "", 200, Mapper200_Init ) - INES_BOARD( "21-in-1", 201, Mapper201_Init ) - INES_BOARD( "", 202, Mapper202_Init ) - INES_BOARD( "", 203, Mapper203_Init ) - INES_BOARD( "", 204, Mapper204_Init ) - INES_BOARD( "BMC 15-in-1/3-in-1", 205, Mapper205_Init ) - INES_BOARD( "NAMCOT 108 Rev. C", 206, Mapper206_Init ) /* Deprecated, Used to be "DEIROM" whatever it means, but actually simple version of MMC3 */ - INES_BOARD( "TAITO X1-005 Rev. B", 207, Mapper207_Init ) - INES_BOARD( "", 208, Mapper208_Init ) - INES_BOARD( "HUMMER/JY BOARD", 209, Mapper209_Init ) - INES_BOARD( "", 210, Mapper210_Init ) - INES_BOARD( "HUMMER/JY BOARD", 211, Mapper211_Init ) - INES_BOARD( "", 212, Mapper212_Init ) - INES_BOARD( "", 213, Mapper058_Init ) /* in mapper 58 */ - INES_BOARD( "", 214, Mapper214_Init ) - INES_BOARD( "UNL-8237", 215, Mapper215_Init ) - INES_BOARD( "Bonza", 216, Mapper216_Init ) - INES_BOARD( "", 217, Mapper217_Init ) /* Redefined to a new Discrete BMC mapper */ - INES_BOARD( "Magic Floor", 218, Mapper218_Init ) - INES_BOARD( "A9746", 219, Mapper219_Init ) -/* INES_BOARD( "Debug Mapper", 220, Mapper220_Init ) */ - INES_BOARD( "UNLN625092", 221, Mapper221_Init ) - INES_BOARD( "", 222, Mapper222_Init ) -/* INES_BOARD( "", 223, Mapper223_Init ) */ - INES_BOARD( "KT-008", 224, MINDKIDS_Init ) /* The KT-008 board contains the MINDKIDS chipset */ - INES_BOARD( "", 225, Mapper225_Init ) - INES_BOARD( "BMC 22+20-in-1", 226, Mapper226_Init ) - INES_BOARD( "", 227, Mapper227_Init ) - INES_BOARD( "", 228, Mapper228_Init ) - INES_BOARD( "", 229, Mapper229_Init ) - INES_BOARD( "BMC Contra+22-in-1", 230, Mapper230_Init ) - INES_BOARD( "20-in-1", 231, Mapper231_Init ) - INES_BOARD( "BMC QUATTRO", 232, Mapper232_Init ) - INES_BOARD( "BMC 22+20-in-1 RST", 233, Mapper233_Init ) - INES_BOARD( "BMC MAXI", 234, Mapper234_Init ) - INES_BOARD( "Golden Game", 235, Mapper235_Init ) - INES_BOARD( "Realtec 8031/8155/8099/8106", 236, Mapper236_Init ) - INES_BOARD( "Teletubbies / Y2K", 237, Mapper237_Init ) - INES_BOARD( "UNL6035052", 238, Mapper238_Init ) -/* INES_BOARD( "", 239, Mapper239_Init ) */ - INES_BOARD( "", 240, Mapper240_Init ) - INES_BOARD( "BxROM+WRAM", 241, Mapper241_Init ) - INES_BOARD( "43272", 242, Mapper242_Init ) - INES_BOARD( "SA-020A", 243, Mapper150_Init ) - INES_BOARD( "DECATHLON", 244, Mapper244_Init ) - INES_BOARD( "", 245, Mapper245_Init ) - INES_BOARD( "FONG SHEN BANG", 246, Mapper246_Init ) -/* INES_BOARD( "", 247, Mapper247_Init ) */ -/* INES_BOARD( "", 248, Mapper248_Init ) */ - INES_BOARD( "", 249, Mapper249_Init ) - INES_BOARD( "", 250, Mapper250_Init ) -/* INES_BOARD( "", 251, Mapper251_Init ) */ /* No good dumps for this mapper, use UNIF version */ - INES_BOARD( "SAN GUO ZHI PIRATE", 252, Mapper252_Init ) - INES_BOARD( "DRAGON BALL PIRATE", 253, Mapper252_Init ) - INES_BOARD( "", 254, Mapper254_Init ) - INES_BOARD( "", 255, Mapper255_Init ) /* Duplicate of M225? */ - - /* NES 2.0 MAPPERS */ - - INES_BOARD( "OneBus", 256, Mapper256_Init ) - INES_BOARD( "158B", 258, Mapper215_Init ) - INES_BOARD( "F-15", 259, Mapper259_Init ) - INES_BOARD( "HPxx / HP2018-A", 260, Mapper260_Init ) - INES_BOARD( "810544-C-A1", 261, Mapper261_Init ) - INES_BOARD( "SHERO", 262, Mapper262_Init ) - INES_BOARD( "KOF97", 263, Mapper263_Init ) - INES_BOARD( "YOKO", 264, Mapper264_Init ) - INES_BOARD( "T-262", 265, Mapper265_Init ) - INES_BOARD( "CITYFIGHT", 266, Mapper266_Init ) - INES_BOARD( "8-in-1 JY-119", 267, Mapper267_Init ) - INES_BOARD( "COOLBOY/MINDKIDS", 268, Mapper268_Init ) /* Submapper distinguishes between COOLBOY and MINDKIDS */ - INES_BOARD( "Games Xplosion 121-in-1", 269, Mapper269_Init ) - INES_BOARD( "MGC-026", 271, Mapper271_Init ) - INES_BOARD( "Akumajō Special: Boku Dracula-kun", 272, Mapper272_Init ) - INES_BOARD( "80013-B", 274, Mapper274_Init ) - INES_BOARD( "", 277, Mapper277_Init ) - INES_BOARD( "YY860417C", 281, Mapper281_Init ) - INES_BOARD( "860224C", 282, Mapper282_Init ) - INES_BOARD( "GS-2004/GS-2013", 283, Mapper283_Init ) -/* INES_BOARD( "DripGame", 284, Mapper284_Init ) */ /* Runs only on newppu */ - INES_BOARD( "A65AS", 285, Mapper285_Init ) - INES_BOARD( "BS-5", 286, Mapper286_Init ) - INES_BOARD( "411120-C, 811120-C", 287, Mapper287_Init ) - INES_BOARD( "GKCX1", 288, Mapper288_Init ) - INES_BOARD( "60311C", 289, Mapper289_Init ) - INES_BOARD( "NTD-03", 290, Mapper290_Init ) - INES_BOARD( "Kasheng 2-in-1 ", 291, Mapper291_Init ) - INES_BOARD( "BMW8544", 292, Mapper292_Init ) - INES_BOARD( "NewStar 12-in-1/7-in-1", 293, Mapper293_Init ) - INES_BOARD( "63-1601 ", 294, Mapper294_Init ) - INES_BOARD( "YY860216C", 295, Mapper295_Init ) - INES_BOARD( "TXC 01-22110-000", 297, Mapper297_Init ) - INES_BOARD( "TF1201", 298, Mapper298_Init ) - INES_BOARD( "11160", 299, Mapper299_Init ) - INES_BOARD( "190in1", 300, Mapper300_Init ) - INES_BOARD( "8157", 301, Mapper301_Init ) - INES_BOARD( "KS7057", 302, Mapper302_Init ) - INES_BOARD( "KS7017", 303, Mapper303_Init ) - INES_BOARD( "SMB2J", 304, Mapper304_Init ) - INES_BOARD( "KS7031", 305, Mapper305_Init ) - INES_BOARD( "KS7016", 306, Mapper306_Init ) - INES_BOARD( "KS7037", 307, Mapper307_Init ) - INES_BOARD( "TH2131-1", 308, Mapper308_Init ) - INES_BOARD( "LH51", 309, Mapper309_Init ) - INES_BOARD( "K-1053", 310, Mapper310_Init ) - INES_BOARD( "KS7013B", 312, Mapper312_Init ) - INES_BOARD( "RESET-TXROM", 313, Mapper313_Init ) - INES_BOARD( "64in1NoRepeat", 314, Mapper314_Init ) - INES_BOARD( "830134C", 315, Mapper315_Init ) - INES_BOARD( "HP898F", 319, Mapper319_Init ) - INES_BOARD( "830425C-4391T", 320, Mapper320_Init ) - INES_BOARD( "K-3033", 322, Mapper322_Init ) - INES_BOARD( "FARID_SLROM_8-IN-1", 323, Mapper323_Init ) - INES_BOARD( "FARID_UNROM_8-IN-1", 324, Mapper324_Init ) - INES_BOARD( "MALISB", 325, Mapper325_Init ) - INES_BOARD( "Contra/Gryzor", 326, Mapper326_Init ) - INES_BOARD( "10-24-C-A1", 327, Mapper327_Init ) - INES_BOARD( "RT-01", 328, Mapper328_Init ) - INES_BOARD( "EDU2000", 329, Mapper329_Init ) - INES_BOARD( "Sangokushi II: Haō no Tairiku", 330, Mapper330_Init ) - INES_BOARD( "12-IN-1", 331, Mapper331_Init ) - INES_BOARD( "WS", 332, Mapper332_Init ) - INES_BOARD( "NEWSTAR-GRM070-8IN1", 333, Mapper333_Init ) - INES_BOARD( "821202C", 334, Mapper334_Init ) - INES_BOARD( "CTC-09", 335, Mapper335_Init ) - INES_BOARD( "K-3046", 336, Mapper336_Init ) - INES_BOARD( "CTC-12IN1", 337, Mapper337_Init ) - INES_BOARD( "SA005-A", 338, Mapper338_Init ) - INES_BOARD( "K-3006", 339, Mapper339_Init ) - INES_BOARD( "K-3036", 340, Mapper340_Init ) - INES_BOARD( "TJ-03", 341, Mapper341_Init ) - INES_BOARD( "COOLGIRL", 342, Mapper342_Init ) - INES_BOARD( "RESETNROM-XIN1", 343, Mapper343_Init ) - INES_BOARD( "GN-26", 344, Mapper344_Init ) - INES_BOARD( "L6IN1", 345, Mapper345_Init ) - INES_BOARD( "KS7012", 346, Mapper346_Init ) - INES_BOARD( "KS7030", 347, Mapper347_Init ) - INES_BOARD( "830118C", 348, Mapper348_Init ) - INES_BOARD( "G-146", 349, Mapper349_Init ) - INES_BOARD( "891227", 350, Mapper350_Init ) - INES_BOARD( "Techline XB", 351, Mapper351_Init ) - INES_BOARD( "KS106C", 352, Mapper352_Init ) - INES_BOARD( "Super Mario Family", 353, Mapper353_Init ) - INES_BOARD( "FAM250/810139C/810331C/SCHI-24", 354, Mapper354_Init ) - INES_BOARD( "3D-BLOCK", 355, Mapper355_Init ) - INES_BOARD( "7-in-1 Rockman (JY-208)", 356, Mapper356_Init ) - INES_BOARD( "Bit Corp 4-in-1", 357, Mapper357_Init ) - INES_BOARD( "YY860606C", 358, Mapper358_Init ) - INES_BOARD( "SB-5013/GCL8050/841242C", 359, Mapper359_Init ) - INES_BOARD( "Bitcorp 31-in-1", 360, Mapper360_Init ) - INES_BOARD( "YY841101C (OK-411)", 361, Mapper361_Init ) - INES_BOARD( "830506C", 362, Mapper362_Init ) - INES_BOARD( "JY830832C", 364, Mapper364_Init ) - INES_BOARD( "GN-45", 366, Mapper366_Init ) - INES_BOARD( "Yung-08", 368, Mapper368_Init ) - INES_BOARD( "N49C-300", 369, Mapper369_Init ) - INES_BOARD( "Golden Mario Party II - Around the World 6-in-1", 370, Mapper370_Init ) - INES_BOARD( "MMC3 PIRATE SFC-12", 372, Mapper372_Init ) - INES_BOARD( "95/96 Super HiK 4-in-1", 374, Mapper374_Init ) - INES_BOARD( "135-in-1", 375, Mapper375_Init ) - INES_BOARD( "YY841155C", 376, Mapper376_Init ) - INES_BOARD( "JY-111/JY-112", 377, Mapper377_Init ) - INES_BOARD( "42 to 80,000 (970630C)", 380, Mapper380_Init ) - INES_BOARD( "KN-42", 381, Mapper381_Init ) - INES_BOARD( "830928C", 382, Mapper382_Init ) - INES_BOARD( "YY840708C", 383, Mapper383_Init ) - INES_BOARD( "NTDEC 2779", 385, Mapper385_Init ) - INES_BOARD( "YY860729C", 386, Mapper386_Init ) - INES_BOARD( "YY850735C", 387, Mapper387_Init ) - INES_BOARD( "YY850835C", 388, Mapper388_Init ) - INES_BOARD( "Caltron 9-in-1", 389, Mapper389_Init ) - INES_BOARD( "Realtec 8031", 390, Mapper390_Init ) - INES_BOARD( "BS-110", 391, Mapper391_Init ) - INES_BOARD( "820720C", 393, Mapper393_Init ) - INES_BOARD( "HSK007", 394, Mapper394_Init ) - INES_BOARD( "Realtec 8210", 395, Mapper395_Init ) - INES_BOARD( "YY850437C", 396, Mapper396_Init ) - INES_BOARD( "YY850439C", 397, Mapper397_Init ) - INES_BOARD( "YY840820C", 398, Mapper398_Init ) - INES_BOARD( "Star Versus", 399, Mapper399_Init ) - INES_BOARD( "8-BIT XMAS", 400, Mapper400_Init ) - INES_BOARD( "BMC Super 19-in-1 (VIP19)",401, Mapper401_Init ) - INES_BOARD( "J-2282", 402, Mapper402_Init ) - INES_BOARD( "89433", 403, Mapper403_Init ) - INES_BOARD( "JY012005", 404, Mapper404_Init ) - INES_BOARD( "Haradius Zero", 406, Mapper406_Init ) - INES_BOARD( "retroUSB DPCMcart", 409, Mapper409_Init ) - INES_BOARD( "JY-302", 410, Mapper410_Init ) - INES_BOARD( "A88S-1", 411, Mapper411_Init ) - INES_BOARD( "Intellivision 10-in-1 PnP 2nd Ed.", 412, Mapper412_Init ) - INES_BOARD( "Super Russian Roulette", 413, Mapper413_Init ) - INES_BOARD( "9999999-in-1", 414, Mapper414_Init ) - INES_BOARD( "0353", 415, Mapper415_Init ) - INES_BOARD( "4-in-1/N-32", 416, Mapper416_Init ) - INES_BOARD( "", 417, Mapper417_Init ) - INES_BOARD( "820106-C/821007C/LH42", 418, Mapper418_Init ) - INES_BOARD( "A971210", 420, Mapper420_Init ) - INES_BOARD( "SC871115C", 421, Mapper421_Init ) - INES_BOARD( "BS-400R/BS-4040", 422, Mapper422_Init ) - INES_BOARD( "AB-G1L/WELL-NO-DG450", 428, Mapper428_Init ) - INES_BOARD( "LIKO BBG-235-8-1B", 429, Mapper429_Init ) - INES_BOARD( "831031C/T-308", 430, Mapper430_Init ) - INES_BOARD( "Realtek GN-91B", 431, Mapper431_Init ) - INES_BOARD( "Realtec 8090", 432, Mapper432_Init ) - INES_BOARD( "NC-20MB", 433, Mapper433_Init ) - INES_BOARD( "S-009", 434, Mapper434_Init ) - INES_BOARD( "F-1002", 435, Mapper435_Init ) - INES_BOARD( "820401/T-217", 436, Mapper436_Init ) - INES_BOARD( "NTDEC TH2348", 437, Mapper437_Init ) - INES_BOARD( "K-3071", 438, Mapper438_Init ) - INES_BOARD( "YS2309", 439, Mapper439_Init ) - INES_BOARD( "841026C/850335C ", 441, Mapper441_Init ) - INES_BOARD( "NC-3000M", 443, Mapper443_Init ) - INES_BOARD( "NC-7000M/NC-8000M", 444, Mapper444_Init ) - INES_BOARD( "DG574B", 445, Mapper445_Init ) - INES_BOARD( "SMD172B_FPGA", 446, Mapper446_Init ) - INES_BOARD( "KL-06 multicart", 447, Mapper447_Init ) - INES_BOARD( "830768C", 448, Mapper448_Init ) - INES_BOARD( "Super Games King", 449, Mapper449_Init ) - INES_BOARD( "YY841157C", 450, Mapper450_Init ) - INES_BOARD( "Haratyler HP/MP", 451, Mapper451_Init ) - INES_BOARD( "DS-9-27", 452, Mapper452_Init ) - INES_BOARD( "Realtec 8042", 453, Mapper453_Init ) - INES_BOARD( "100-in-1", 454, Mapper454_Init ) - INES_BOARD( "N625836", 455, Mapper455_Init ) - INES_BOARD( "K6C3001A", 456, Mapper456_Init ) - INES_BOARD( "810431C", 457, Mapper457_Init ) - INES_BOARD( "", 458, Mapper458_Init ) - INES_BOARD( "8-in-1", 459, Mapper459_Init ) - INES_BOARD( "FC-29-40/K-3101", 460, Mapper460_Init ) - INES_BOARD( "0324", 461, Mapper461_Init ) - INES_BOARD( "YH810X1", 463, Mapper463_Init ) - INES_BOARD( "NTDEC 9012", 464, Mapper464_Init ) - INES_BOARD( "ET-120", 465, Mapper465_Init ) - INES_BOARD( "Keybyte Computer", 466, Mapper466_Init ) - INES_BOARD( "47-2", 467, Mapper467_Init ) - /* m468 - untested since i dont have rom to test it, so im adding it here as-is */ - INES_BOARD( "BlazePro CPLD", 468, Mapper468_Init ) - - INES_BOARD( "Impact Soft IM1", 471, Mapper471_Init ) - INES_BOARD( "Yhc-000", 500, Mapper500_Init ) - INES_BOARD( "Yhc-001", 501, Mapper501_Init ) - INES_BOARD( "Yhc-002", 502, Mapper502_Init ) - INES_BOARD( "", 512, Mapper512_Init ) - INES_BOARD( "SA-9602B", 513, Mapper513_Init ) - INES_BOARD( "Subor Karaoke", 514, Mapper514_Init ) - INES_BOARD( "Brilliant Com Cocoma Pack", 516, Mapper516_Init ) - INES_BOARD( "Kkachi-wa Nolae Chingu", 517, Mapper517_Init ) /* Korean Karaoke */ - INES_BOARD( "DANCE2000", 518, Mapper518_Init ) - INES_BOARD( "EH8813A", 519, Mapper519_Init ) - INES_BOARD( "Datach DBZ/Yu Yu Hakusho", 520, Mapper520_Init ) - INES_BOARD( "DREAMTECH01", 521, Mapper521_Init ) - INES_BOARD( "LH10", 522, Mapper522_Init ) - INES_BOARD( "Jncota KT-???", 523, Mapper523_Init ) - INES_BOARD( "900218", 524, Mapper524_Init ) - INES_BOARD( "KS7021A", 525, Mapper525_Init ) - INES_BOARD( "BJ-56", 526, Mapper526_Init ) - INES_BOARD( "AX-40G", 527, Mapper527_Init ) - INES_BOARD( "831128C", 528, Mapper528_Init ) - INES_BOARD( "YY0807/J-2148/T-230", 529, Mapper529_Init ) - INES_BOARD( "AX5705", 530, Mapper530_Init ) - INES_BOARD( "Sachen 3014", 533, Mapper533_Init ) - INES_BOARD( "NJ064", 534, Mapper534_Init ) - INES_BOARD( "LH53", 535, Mapper535_Init ) - INES_BOARD( "60-1064-16L (FDS)", 538, Mapper538_Init ) - INES_BOARD( "Kid Ikarus (FDS)", 539, Mapper539_Init ) - INES_BOARD( "82112C", 540, Mapper540_Init ) - INES_BOARD( "LittleCom 160-in-1", 541, Mapper541_Init ) - INES_BOARD( "5-in-1 (CH-501)", 543, Mapper543_Init ) - INES_BOARD( "Waixing FS306", 544, Mapper544_Init ) - INES_BOARD( "KONAMI-QTAI", 547, Mapper547_Init ) - INES_BOARD( "CTC-15", 548, Mapper548_Init ) - INES_BOARD( "KS-701B (Kaiser FDS)", 549, Mapper549_Init ) - INES_BOARD( "", 551, Mapper178_Init ) - INES_BOARD( "TAITO X1-017", 552, Mapper552_Init ) - INES_BOARD( "SACHEN 3013", 553, Mapper553_Init ) - INES_BOARD( "KS-7010", 554, Mapper554_Init ) - INES_BOARD( "JY-215", 556, Mapper556_Init ) - INES_BOARD( "JY820845C", 550, Mapper550_Init ) - INES_BOARD( "NES-EVENT2", 555, Mapper555_Init ) - INES_BOARD( "", 557, Mapper557_Init ) - INES_BOARD( "YC-03-09", 558, Mapper558_Init ) - INES_BOARD( "Subor 0102", 559, Mapper559_Init ) - INES_BOARD( "Bung Super Game Doctor 2M/4M", 561, Mapper561_Init ) - INES_BOARD( "Venus Turbo Game Doctor 4+/6+/6M", 562, Mapper562_Init ) -INES_BOARD_END() static uint32 iNES_get_mapper_id(void) { @@ -1410,7 +907,6 @@ static void iNES_read_header_info(void) { iNESCart.battery = (head.ROM_type & 2) ? 1 : 0; iNESCart.mapper = iNES_get_mapper_id(); iNESCart.iNES2 = (head.ROM_type2 & 0x0C) == 0x08; - iNESCart.HasTrainer = (head.ROM_type & 0x04) != 0; if (iNESCart.iNES2) { @@ -1422,8 +918,6 @@ static void iNES_read_header_info(void) { if (head.PRGRAM_size & 0xF0) iNESCart.PRGRamSaveSize = 64 << ((head.PRGRAM_size >> 4) & 0x0F); if (head.CHRRAM_size & 0x0F) iNESCart.CHRRamSize = 64 << ((head.CHRRAM_size >> 0) & 0x0F); if (head.CHRRAM_size & 0xF0) iNESCart.CHRRamSaveSize = 64 << ((head.CHRRAM_size >> 4) & 0x0F); - - iNESCart.HasMisc = head.MiscRoms & 0x03; } } @@ -1431,8 +925,10 @@ int iNESLoad(const char *name, FCEUFILE *fp) { const char *tv_region[] = { "NTSC", "PAL", "Multi-region", "Dendy" }; struct md5_context md5; +#ifdef DEBUG char* mappername = NULL; uint32 mappertest = 0; +#endif uint64 filesize = FCEU_fgetsize(fp); /* size of file including header */ uint64 romSize = 0; /* size of PRG + CHR rom */ /* used for malloc and cart mapping */ @@ -1472,12 +968,11 @@ int iNESLoad(const char *name, FCEUFILE *fp) filesize -= 16; /* remove header size from total size */ /* Trainer */ - if (iNESCart.HasTrainer) + if (head.ROM_type & 4) { - miscROMSIZE = 512; - miscROM = (uint8*)FCEU_gmalloc(512); - FCEU_fread(miscROM, 512, 1, fp); - filesize -= miscROMSIZE; + trainerpoo = (uint8*)FCEU_gmalloc(512); + FCEU_fread(trainerpoo, 512, 1, fp); + filesize -= 512; } iNESCart.PRGRomSize = ROM_size >=0xF00? (pow(2, head.ROM_size >>2)*((head.ROM_size &3)*2+1)): (ROM_size*0x4000); @@ -1515,18 +1010,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) FCEU_fread(VROM, 1, iNESCart.CHRRomSize, fp); } - if (iNESCart.HasMisc) - { - miscROMSIZE = filesize - romSize; - if (!(miscROM = (uint8 *)FCEU_malloc(miscROMSIZE))) - { - Cleanup(); - return 0; - } - memset(miscROM, 0xFF, miscROMSIZE); - FCEU_fread(miscROM, 1, miscROMSIZE, fp); - } - iNESCart.PRGCRC32 = CalcCRC32(0, ROM, iNESCart.PRGRomSize); iNESCart.CHRCRC32 = CalcCRC32(0, VROM, iNESCart.CHRRomSize); iNESCart.CRC32 = CalcCRC32(iNESCart.PRGCRC32, VROM, iNESCart.CHRRomSize); @@ -1539,6 +1022,7 @@ int iNESLoad(const char *name, FCEUFILE *fp) memcpy(&GameInfo->MD5, &iNESCart.MD5, sizeof(iNESCart.MD5)); +#ifdef DEBUG mappername = "Not Listed"; for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) @@ -1549,6 +1033,7 @@ int iNESLoad(const char *name, FCEUFILE *fp) break; } } +#endif if (iNESCart.iNES2 == 0) { if (strstr(name, "(E)") || strstr(name, "(e)") || @@ -1566,6 +1051,7 @@ int iNESLoad(const char *name, FCEUFILE *fp) } } +#ifdef DEBUG FCEU_printf(" PRG-ROM CRC32: 0x%08X\n", iNESCart.PRGCRC32); FCEU_printf(" PRG+CHR CRC32: 0x%08X\n", iNESCart.CRC32); FCEU_printf(" PRG+CHR MD5: 0x%s\n", md5_asciistr(iNESCart.MD5)); @@ -1597,15 +1083,9 @@ int iNESLoad(const char *name, FCEUFILE *fp) FCEU_printf(" PRG RAM: %d KB\n", PRGRAM / 1024); FCEU_printf(" CHR RAM: %d KB\n", CHRRAM / 1024); } - } - if (!iNESCart.HasTrainer && miscROMSIZE) { - if (miscROMSIZE / 1024) { - FCEU_printf(" Misc ROM: %-6d KiB\n", miscROMSIZE / 1024); - } else { - FCEU_printf(" Misc ROM: %-6d bytes\n", miscROMSIZE); - } - } + } } +#endif ResetCartMapping(); ResetExState(0, 0); @@ -1648,10 +1128,6 @@ int iNESLoad(const char *name, FCEUFILE *fp) if (VROM_size) SetupCartCHRMapping(0, VROM, vrom_size_pow2, 0); - /* VS mapper uses 4-screen mirroring */ - if (iNESCart.mapper == 151 && iNESCart.mirror != 2) - iNESCart.mirror = 2; - if (iNESCart.mirror == 2) { ExtraNTARAM = (uint8*)FCEU_gmalloc(2048); diff --git a/src/ines.h b/src/ines.h index 413cdc9e2..a5e72e932 100644 --- a/src/ines.h +++ b/src/ines.h @@ -44,117 +44,95 @@ extern uint32 ROM_size; /* prg size in 16K chunks */ extern uint32 VROM_size; /* chr size in 8K chunks */ extern iNES_HEADER head; -extern uint8 *WRAM; -extern uint32 WRAMSIZE; - -extern uint8 *CHRRAM; -extern uint32 CHRRAMSIZE; - -extern uint8 *miscROM; -extern uint32 miscROMSIZE; - void NSFVRC6_Init(void); void NSFMMC5_Init(void); void NSFAY_Init(void); void NSFN106_Init(void); void NSFVRC7_Init(void); -void Mapper000_Init(CartInfo *); -void Mapper001_Init(CartInfo *); -void Mapper002_Init(CartInfo *); -void Mapper003_Init(CartInfo *); -void Mapper004_Init(CartInfo *); -void Mapper005_Init(CartInfo *); -void Mapper006_Init(CartInfo *); -void Mapper007_Init(CartInfo *); -/* void Mapper008_Init(CartInfo *);*/ -void Mapper009_Init(CartInfo *); -void Mapper010_Init(CartInfo *); -void Mapper011_Init(CartInfo *); -void Mapper012_Init(CartInfo *); -void Mapper013_Init(CartInfo *); -void Mapper014_Init(CartInfo *); -void Mapper015_Init(CartInfo *); -void Mapper016_Init(CartInfo *); -/* void Mapper017_Init(CartInfo *); */ -void Mapper018_Init(CartInfo *); -void Mapper019_Init(CartInfo *); -void Mapper021_Init(CartInfo *); -void Mapper022_Init(CartInfo *); -void Mapper023_Init(CartInfo *); -void Mapper024_Init(CartInfo *); -void Mapper025_Init(CartInfo *); -void Mapper026_Init(CartInfo *); -void Mapper027_Init(CartInfo *); -void Mapper028_Init(CartInfo *); -void Mapper029_Init(CartInfo *); -void Mapper030_Init(CartInfo *); -void Mapper031_Init(CartInfo *); -void Mapper032_Init(CartInfo *); -void Mapper033_Init(CartInfo *); -void Mapper034_Init(CartInfo *); -void Mapper035_Init(CartInfo *); -void Mapper036_Init(CartInfo *); -void Mapper037_Init(CartInfo *); -void Mapper038_Init(CartInfo *); -void Mapper040_Init(CartInfo *); -void Mapper041_Init(CartInfo *); -void Mapper042_Init(CartInfo *); -void Mapper043_Init(CartInfo *); -void Mapper044_Init(CartInfo *); -void Mapper045_Init(CartInfo *); -void Mapper046_Init(CartInfo *); -void Mapper047_Init(CartInfo *); -void Mapper048_Init(CartInfo *); -void Mapper049_Init(CartInfo *); -void Mapper050_Init(CartInfo *); -void Mapper051_Init(CartInfo *); -void Mapper052_Init(CartInfo *); -void Mapper053_Init(CartInfo *); -void Mapper055_Init(CartInfo *); -void Mapper056_Init(CartInfo *); -void Mapper057_Init(CartInfo *); -void Mapper058_Init(CartInfo *); -void Mapper059_Init(CartInfo *); -void Mapper060_Init(CartInfo *); -void Mapper061_Init(CartInfo *); -void Mapper062_Init(CartInfo *); -void Mapper063_Init(CartInfo *); -void Mapper064_Init(CartInfo *); -void Mapper065_Init(CartInfo *); -void Mapper066_Init(CartInfo *); -void Mapper067_Init(CartInfo *); -void Mapper068_Init(CartInfo *); -void Mapper069_Init(CartInfo *); -void Mapper070_Init(CartInfo *); -void Mapper071_Init(CartInfo *); -void Mapper072_Init(CartInfo *); -void Mapper073_Init(CartInfo *); -void Mapper074_Init(CartInfo *); -void Mapper075_Init(CartInfo *); -void Mapper076_Init(CartInfo *); -void Mapper077_Init(CartInfo *); -void Mapper078_Init(CartInfo *); -void Mapper079_Init(CartInfo *); -void Mapper080_Init(CartInfo *); -void Mapper081_Init(CartInfo *); -void Mapper082_Init(CartInfo *); -void Mapper083_Init(CartInfo *); -void Mapper085_Init(CartInfo *); -void Mapper086_Init(CartInfo *); -void Mapper087_Init(CartInfo *); -void Mapper088_Init(CartInfo *); -void Mapper089_Init(CartInfo *); -void Mapper090_Init(CartInfo *); -void Mapper091_Init(CartInfo *); -/* void Mapper092_Init(CartInfo *); */ -void Mapper093_Init(CartInfo *); -void Mapper094_Init(CartInfo *); -void Mapper095_Init(CartInfo *); -void Mapper096_Init(CartInfo *); -void Mapper097_Init(CartInfo *); -void Mapper099_Init(CartInfo *); -void Mapper100_Init(CartInfo *); +void Mapper1_Init(CartInfo *); +void Mapper4_Init(CartInfo *); +void Mapper5_Init(CartInfo *); +void Mapper6_Init(CartInfo *); +void Mapper8_Init(CartInfo *); +void Mapper9_Init(CartInfo *); +void Mapper10_Init(CartInfo *); +void Mapper11_Init(CartInfo *); +void Mapper12_Init(CartInfo *); +void Mapper15_Init(CartInfo *); +void Mapper16_Init(CartInfo *); +void Mapper17_Init(CartInfo *); +void Mapper18_Init(CartInfo *); +void Mapper19_Init(CartInfo *); +void Mapper21_Init(CartInfo *); +void Mapper22_Init(CartInfo *); +void Mapper23_Init(CartInfo *); +void Mapper24_Init(CartInfo *); +void Mapper25_Init(CartInfo *); +void Mapper26_Init(CartInfo *); +void Mapper28_Init(CartInfo *); +void Mapper29_Init(CartInfo *); +void Mapper31_Init(CartInfo *); +void Mapper32_Init(CartInfo *); +void Mapper33_Init(CartInfo *); +void Mapper34_Init(CartInfo *); +void Mapper35_Init(CartInfo *); +void Mapper36_Init(CartInfo *); +void Mapper37_Init(CartInfo *); +void Mapper38_Init(CartInfo *); +void Mapper40_Init(CartInfo *); +void Mapper41_Init(CartInfo *); +void Mapper42_Init(CartInfo *); +void Mapper43_Init(CartInfo *); +void Mapper44_Init(CartInfo *); +void Mapper45_Init(CartInfo *); +void Mapper46_Init(CartInfo *); +void Mapper47_Init(CartInfo *); +void Mapper48_Init(CartInfo *); +void Mapper49_Init(CartInfo *); +void Mapper50_Init(CartInfo *); +void Mapper51_Init(CartInfo *); +void Mapper52_Init(CartInfo *); +void Mapper57_Init(CartInfo *); +void Mapper58_Init(CartInfo *); +void Mapper59_Init(CartInfo *); +void Mapper60_Init(CartInfo *); +void Mapper61_Init(CartInfo *); +void Mapper62_Init(CartInfo *); +void Mapper63_Init(CartInfo *); +void Mapper64_Init(CartInfo *); +void Mapper65_Init(CartInfo *); +void Mapper67_Init(CartInfo *); +void Mapper68_Init(CartInfo *); +void Mapper69_Init(CartInfo *); +void Mapper70_Init(CartInfo *); +void Mapper71_Init(CartInfo *); +void Mapper72_Init(CartInfo *); +void Mapper73_Init(CartInfo *); +void Mapper74_Init(CartInfo *); +void Mapper75_Init(CartInfo *); +void Mapper76_Init(CartInfo *); +void Mapper77_Init(CartInfo *); +void Mapper78_Init(CartInfo *); +void Mapper79_Init(CartInfo *); +void Mapper80_Init(CartInfo *); +void Mapper81_Init(CartInfo *); +void Mapper82_Init(CartInfo *); +void Mapper83_Init(CartInfo *); +void Mapper85_Init(CartInfo *); +void Mapper86_Init(CartInfo *); +void Mapper87_Init(CartInfo *); +void Mapper88_Init(CartInfo *); +void Mapper89_Init(CartInfo *); +void Mapper90_Init(CartInfo *); +void Mapper91_Init(CartInfo *); +void Mapper92_Init(CartInfo *); +void Mapper93_Init(CartInfo *); +void Mapper94_Init(CartInfo *); +void Mapper95_Init(CartInfo *); +void Mapper96_Init(CartInfo *); +void Mapper97_Init(CartInfo *); +void Mapper99_Init(CartInfo *); void Mapper101_Init(CartInfo *); void Mapper103_Init(CartInfo *); void Mapper104_Init(CartInfo *); @@ -169,33 +147,18 @@ void Mapper114_Init(CartInfo *); void Mapper115_Init(CartInfo *); void Mapper116_Init(CartInfo *); void Mapper117_Init(CartInfo *); -void Mapper118_Init(CartInfo *); void Mapper119_Init(CartInfo *); void Mapper120_Init(CartInfo *); void Mapper121_Init(CartInfo *); -void Mapper123_Init(CartInfo *); -void Mapper124_Init(CartInfo *); void Mapper125_Init(CartInfo *); void Mapper126_Init(CartInfo *); -void Mapper127_Init(CartInfo *); void Mapper128_Init(CartInfo *); void Mapper132_Init(CartInfo *); -void Mapper133_Init(CartInfo *); void Mapper134_Init(CartInfo *); void Mapper136_Init(CartInfo *); -void Mapper137_Init(CartInfo *); -void Mapper138_Init(CartInfo *); -void Mapper139_Init(CartInfo *); void Mapper140_Init(CartInfo *); -void Mapper141_Init(CartInfo *); -void Mapper142_Init(CartInfo *); -void Mapper143_Init(CartInfo *); void Mapper144_Init(CartInfo *); -void Mapper145_Init(CartInfo *); void Mapper147_Init(CartInfo *); -void Mapper148_Init(CartInfo *); -void Mapper149_Init(CartInfo *); -void Mapper150_Init(CartInfo *); void Mapper151_Init(CartInfo *); void Mapper152_Init(CartInfo *); void Mapper153_Init(CartInfo *); @@ -203,6 +166,7 @@ void Mapper154_Init(CartInfo *); void Mapper155_Init(CartInfo *); void Mapper156_Init(CartInfo *); void Mapper157_Init(CartInfo *); +void Mapper158_Init(CartInfo *); void Mapper159_Init(CartInfo *); void Mapper162_Init(CartInfo *); void Mapper163_Init(CartInfo *); @@ -212,7 +176,7 @@ void Mapper166_Init(CartInfo *); void Mapper167_Init(CartInfo *); void Mapper168_Init(CartInfo *); void Mapper170_Init(CartInfo *); -void Mapper171_Init(CartInfo *); /* Kaiser 7058 */ +void Mapper171_Init(CartInfo *); void Mapper172_Init(CartInfo *); void Mapper173_Init(CartInfo *); void Mapper174_Init(CartInfo *); @@ -221,6 +185,7 @@ void Mapper176_Init(CartInfo *); void Mapper177_Init(CartInfo *); void Mapper178_Init(CartInfo *); void Mapper180_Init(CartInfo *); +void Mapper181_Init(CartInfo *); void Mapper183_Init(CartInfo *); void Mapper184_Init(CartInfo *); void Mapper185_Init(CartInfo *); @@ -228,7 +193,6 @@ void Mapper186_Init(CartInfo *); void Mapper187_Init(CartInfo *); void Mapper188_Init(CartInfo *); void Mapper189_Init(CartInfo *); -void Mapper190_Init(CartInfo *); void Mapper191_Init(CartInfo *); void Mapper192_Init(CartInfo *); void Mapper193_Init(CartInfo *); @@ -253,13 +217,10 @@ void Mapper211_Init(CartInfo *); void Mapper212_Init(CartInfo *); void Mapper213_Init(CartInfo *); void Mapper214_Init(CartInfo *); -void Mapper215_Init(CartInfo *); void Mapper216_Init(CartInfo *); void Mapper217_Init(CartInfo *); void Mapper218_Init(CartInfo *); -void Mapper219_Init(CartInfo *); void Mapper220_Init(CartInfo *); -void Mapper221_Init(CartInfo *); void Mapper222_Init(CartInfo *); void Mapper224_Init(CartInfo *); void Mapper225_Init(CartInfo *); @@ -275,7 +236,6 @@ void Mapper234_Init(CartInfo *); void Mapper235_Init(CartInfo *); void Mapper236_Init(CartInfo *); void Mapper237_Init(CartInfo *); -void Mapper238_Init(CartInfo *); void Mapper240_Init(CartInfo *); void Mapper241_Init(CartInfo *); void Mapper242_Init(CartInfo *); @@ -288,101 +248,42 @@ void Mapper252_Init(CartInfo *); void Mapper253_Init(CartInfo *); void Mapper254_Init(CartInfo *); void Mapper255_Init(CartInfo *); -void Mapper256_Init(CartInfo *); -void Mapper257_Init(CartInfo *); -void Mapper259_Init(CartInfo *); -void Mapper260_Init(CartInfo *); -void Mapper261_Init(CartInfo *); -void Mapper262_Init(CartInfo *); -void Mapper263_Init(CartInfo *); -void Mapper264_Init(CartInfo *); -void Mapper265_Init(CartInfo *); -void Mapper266_Init(CartInfo *); -void Mapper267_Init(CartInfo *); -void Mapper268_Init(CartInfo *); -void Mapper269_Init(CartInfo *); -void Mapper271_Init(CartInfo *); + +void GN45_Init(CartInfo *info); /* m361, m366 */ void Mapper272_Init(CartInfo *); -void Mapper274_Init(CartInfo *); void Mapper277_Init(CartInfo *); void Mapper281_Init(CartInfo *); void Mapper282_Init(CartInfo *); void Mapper283_Init(CartInfo *); -void Mapper284_Init(CartInfo *); -void Mapper285_Init(CartInfo *); -void Mapper286_Init(CartInfo *); -void Mapper287_Init(CartInfo *); -void Mapper288_Init(CartInfo *); -void Mapper289_Init(CartInfo *); -void Mapper290_Init(CartInfo *); void Mapper291_Init(CartInfo *); -void Mapper292_Init(CartInfo *); +void Mapper295_Init(CartInfo *); + +void J2282_Init(CartInfo *); + +void Mapper265_Init(CartInfo *); +void Mapper267_Init(CartInfo *); +void Mapper268_Init(CartInfo *); +void Mapper269_Init(CartInfo *); +void Mapper271_Init(CartInfo *); +void Mapper288_Init(CartInfo *); void Mapper293_Init(CartInfo *); void Mapper294_Init(CartInfo *); -void Mapper295_Init(CartInfo *); void Mapper297_Init(CartInfo *); -void Mapper298_Init(CartInfo *); -void Mapper299_Init(CartInfo *); -void Mapper300_Init(CartInfo *); -void Mapper301_Init(CartInfo *); -void Mapper302_Init(CartInfo *); -void Mapper303_Init(CartInfo *); -void Mapper304_Init(CartInfo *); -void Mapper305_Init(CartInfo *); -void Mapper306_Init(CartInfo *); -void Mapper307_Init(CartInfo *); -void Mapper308_Init(CartInfo *); -void Mapper309_Init(CartInfo *); void Mapper310_Init(CartInfo *); -void Mapper312_Init(CartInfo *); -void Mapper313_Init(CartInfo *); -void Mapper314_Init(CartInfo *); -void Mapper315_Init(CartInfo *); void Mapper319_Init(CartInfo *); -void Mapper320_Init(CartInfo *); -void Mapper322_Init(CartInfo *); -void Mapper323_Init(CartInfo *); -void Mapper324_Init(CartInfo *); -void Mapper325_Init(CartInfo *); void Mapper326_Init(CartInfo *); -void Mapper327_Init(CartInfo *); -void Mapper328_Init(CartInfo *); -void Mapper329_Init(CartInfo *); void Mapper330_Init(CartInfo *); -void Mapper331_Init(CartInfo *); -void Mapper332_Init(CartInfo *); -void Mapper333_Init(CartInfo *); void Mapper334_Init(CartInfo *); -void Mapper335_Init(CartInfo *); -void Mapper336_Init(CartInfo *); -void Mapper337_Init(CartInfo *); -void Mapper338_Init(CartInfo *); -void Mapper339_Init(CartInfo *); -void Mapper340_Init(CartInfo *); -void Mapper341_Init(CartInfo *); -void Mapper342_Init(CartInfo *); -void Mapper343_Init(CartInfo *); -void Mapper344_Init(CartInfo *); -void Mapper345_Init(CartInfo *); -void Mapper346_Init(CartInfo *); -void Mapper347_Init(CartInfo *); -void Mapper348_Init(CartInfo *); -void Mapper349_Init(CartInfo *); -void Mapper350_Init(CartInfo *); void Mapper351_Init(CartInfo *); -void Mapper352_Init(CartInfo *); void Mapper353_Init(CartInfo *); void Mapper354_Init(CartInfo *); -void Mapper355_Init(CartInfo *); void Mapper356_Init(CartInfo *); void Mapper357_Init(CartInfo *); void Mapper358_Init(CartInfo *); void Mapper359_Init(CartInfo *); void Mapper360_Init(CartInfo *); -void Mapper361_Init(CartInfo *); void Mapper362_Init(CartInfo *); void Mapper364_Init(CartInfo *); -void Mapper366_Init(CartInfo *); void Mapper368_Init(CartInfo *); void Mapper369_Init(CartInfo *); void Mapper370_Init(CartInfo *); @@ -408,23 +309,17 @@ void Mapper395_Init(CartInfo *); void Mapper396_Init(CartInfo *); void Mapper397_Init(CartInfo *); void Mapper398_Init(CartInfo *); -void Mapper399_Init(CartInfo *); -void Mapper400_Init(CartInfo *); void Mapper401_Init(CartInfo *); -void Mapper402_Init(CartInfo *); void Mapper403_Init(CartInfo *); void Mapper404_Init(CartInfo *); -void Mapper406_Init(CartInfo *); void Mapper409_Init(CartInfo *); void Mapper410_Init(CartInfo *); void Mapper411_Init(CartInfo *); void Mapper412_Init(CartInfo *); -void Mapper413_Init(CartInfo *); void Mapper414_Init(CartInfo *); void Mapper415_Init(CartInfo *); void Mapper416_Init(CartInfo *); void Mapper417_Init(CartInfo *); -void Mapper418_Init(CartInfo *); void Mapper420_Init(CartInfo *); void Mapper421_Init(CartInfo *); void Mapper422_Init(CartInfo *); @@ -443,13 +338,8 @@ void Mapper439_Init(CartInfo *); void Mapper441_Init(CartInfo *); void Mapper443_Init(CartInfo *); void Mapper444_Init(CartInfo *); -void Mapper445_Init(CartInfo *); -void Mapper446_Init(CartInfo *); -void Mapper447_Init(CartInfo *); void Mapper448_Init(CartInfo *); void Mapper449_Init(CartInfo *); -void Mapper450_Init(CartInfo *); -void Mapper451_Init(CartInfo *); void Mapper452_Init(CartInfo *); void Mapper453_Init(CartInfo *); void Mapper454_Init(CartInfo *); @@ -466,50 +356,25 @@ void Mapper465_Init(CartInfo *); void Mapper466_Init(CartInfo *); void Mapper467_Init(CartInfo *); void Mapper468_Init(CartInfo *); -void Mapper471_Init(CartInfo *); +void INX_007T_Init(CartInfo* info); /* Mapper 470 */ void Mapper500_Init(CartInfo *); void Mapper501_Init(CartInfo *); void Mapper502_Init(CartInfo *); -void Mapper512_Init(CartInfo *); -void Mapper513_Init(CartInfo *); -void Mapper514_Init(CartInfo *); void Mapper516_Init(CartInfo *); -void Mapper517_Init(CartInfo *); -void Mapper518_Init(CartInfo *); -void Mapper519_Init(CartInfo *); -void Mapper520_Init(CartInfo *); -void Mapper521_Init(CartInfo *); -void Mapper522_Init(CartInfo *); void Mapper523_Init(CartInfo *); -void Mapper524_Init(CartInfo *); -void Mapper525_Init(CartInfo *); -void Mapper526_Init(CartInfo *); -void Mapper527_Init(CartInfo *); void Mapper528_Init(CartInfo *); -void Mapper529_Init(CartInfo *); -void Mapper530_Init(CartInfo *); void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); -void Mapper535_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); void Mapper540_Init(CartInfo *); void Mapper541_Init(CartInfo *); void Mapper543_Init(CartInfo *); -void Mapper544_Init(CartInfo *); -void Mapper547_Init(CartInfo *); -void Mapper548_Init(CartInfo *); -void Mapper549_Init(CartInfo *); void Mapper550_Init(CartInfo *); -void Mapper552_Init(CartInfo *); void Mapper553_Init(CartInfo *); void Mapper554_Init(CartInfo *); void Mapper555_Init(CartInfo *); void Mapper556_Init(CartInfo *); -void Mapper557_Init(CartInfo *); void Mapper558_Init(CartInfo *); -void Mapper559_Init(CartInfo *); -void Mapper561_Init(CartInfo *); -void Mapper562_Init(CartInfo *); #endif diff --git a/src/input.c b/src/input.c index 70d921314..fa52f8c0c 100644 --- a/src/input.c +++ b/src/input.c @@ -33,8 +33,6 @@ #include "vsuni.h" #include "fds.h" -#include "cart.h" - extern INPUTC *FCEU_InitZapper(int w); extern INPUTC *FCEU_InitMouse(int w); extern INPUTC *FCEU_InitPowerpadA(int w); @@ -222,7 +220,7 @@ void FCEU_UpdateInput(void) if (FCExp && FCExp->Update) FCExp->Update(InputDataPtrFC, JPAttribFC); - if (GameInfo && GameInfo->type == GIT_VSUNI || iNESCart.mapper == 124) + if (GameInfo && GameInfo->type == GIT_VSUNI) if (coinon) coinon--; if (GameInfo->type == GIT_VSUNI) diff --git a/src/mappers/hw/bandai.c b/src/mappers/hw/bandai.c deleted file mode 100644 index 687abd5cc..000000000 --- a/src/mappers/hw/bandai.c +++ /dev/null @@ -1,231 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2011 FCEUX team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * INES Mapper 016 - * iNES Mapper 016 is used for some of the Bandai FCG boards, namely, boards with - * the FCG-1 ASIC that supports no EEPROM, and the LZ93D50 ASIC with no or 256 bytes of EEPROM. - * - * INES Mapper 016 submapper table - * Submapper # Meaning Note - * 0 Unspecified Emulate both FCG-1/2 and LZ93D50 chips in their respective CPU address ranges. - * 1 LZ93D50 with 128 byte serial EEPROM (24C01) Deprecated, use INES Mapper 159 instead. - * 2 Datach Joint ROM System Deprecated, use INES Mapper 157 instead. - * 3 8 KiB of WRAM instead of serial EEPROM Deprecated, use INES Mapper 153 instead. - * 4 FCG-1/2 Responds only in the CPU $6000-$7FFF address range; IRQ counter is not latched. - * 5 LZ93D50 with no or 256-byte serial EEPROM (24C02) Responds only in the CPU $8000-$FFFF address range; IRQ counter is latched. - * - */ - -#include "mapinc.h" -#include "eeprom_x24c0x.h" -#include "bandai.h" - -EEPROM_TYPE eeprom_type = EEPROM_NONE; - -static uint8 prg; -static uint8 chr[8]; -static uint8 mirr; -static uint8 IRQa; -static int16 IRQCount, IRQLatch; - -static uint8 isFCG12 = 0; - -static uint8 eeprom[256]; - -void (*BANDAI_pwrap)(uint16 A, uint16 V); -void (*BANDAI_cwrap)(uint16 A, uint16 V); - -static SFORMAT StateRegs[] = -{ - { chr, 8, "CRGS" }, - { &prg, 1, "PREG" }, - { &mirr, 1, "MIRR" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 2, "IRQC" }, - { &IRQLatch, 2, "IRQL" }, /* need for Famicom Jump II - Saikyou no 7 Nin (J) [!] */ - { 0 } -}; - -static void GENPWRAP(uint16 A, uint16 V) { - setprg16(A, V & 0x0F); -} - -static void GENCWRAP(uint16 A, uint16 V) { - setchr1(A, V); -} - -void BANDAI_FixPRG(void) { - BANDAI_pwrap(0x8000, prg); - BANDAI_pwrap(0xC000, ~0); -} - -void BANDAI_FixCHR(void) { - BANDAI_cwrap(0x0000, chr[0]); - BANDAI_cwrap(0x0400, chr[1]); - BANDAI_cwrap(0x0800, chr[2]); - BANDAI_cwrap(0x0C00, chr[3]); - BANDAI_cwrap(0x1000, chr[4]); - BANDAI_cwrap(0x1400, chr[5]); - BANDAI_cwrap(0x1800, chr[6]); - BANDAI_cwrap(0x1C00, chr[7]); -} - -void BANDAI_FixMIR(void) { - switch (mirr & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -static DECLFR(BANDAI_Read) { - if (eeprom_type == EEPROM_X24C01) { - return (CPU_OPENBUS & ~0x010) | (x24c01_read() << 4); - } - return (CPU_OPENBUS & ~0x010) | (x24c02_read() << 4); -} - -DECLFW(BANDAI_Write) { - switch (A & 0x0F) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - chr[A & 0x07] = V; - BANDAI_FixCHR(); - break; - case 0x08: - prg = V; - BANDAI_FixPRG(); - break; - case 0x09: - mirr = V; - BANDAI_FixMIR(); - break; - case 0x0A: - IRQa = V & 1; - IRQCount = IRQLatch; - if (IRQa && !IRQLatch) { - X6502_IRQBegin(FCEU_IQEXT); - } else { - X6502_IRQEnd(FCEU_IQEXT); - } - break; - case 0x0B: - IRQLatch &= 0xFF00; - IRQLatch |= V; - break; - case 0x0C: - IRQLatch &= 0x00FF; - IRQLatch |= V << 8; - break; - case 0x0D: - if (eeprom_type == EEPROM_X24C02) { - x24c02_write(V); - } else if (eeprom_type == EEPROM_X24C01) { - x24c01_write(V); - } - break; - } -} - -void BANDAI_IRQHook(int a) { - if (IRQa) { - IRQCount -= a; - if (IRQCount < 0) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -void BANDAI_Reset(void) { - int x; - - prg = 0x00; - for (x = 0; x < 8; x++) { - chr[x] = x; - } - IRQCount = 0; - IRQLatch = 0; - IRQa = FALSE; - - BANDAI_FixPRG(); - BANDAI_FixCHR(); - BANDAI_FixMIR(); -} - -static void StateRestore(int version) { - BANDAI_FixPRG(); - BANDAI_FixCHR(); - BANDAI_FixMIR(); -} - -void BANDAI_Power(void) { - BANDAI_Reset(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, BANDAI_Write); - if (isFCG12) { - /* submapper 4 */ - SetWriteHandler(0x6000, 0x7FFF, BANDAI_Write); - } - - if (eeprom_type != EEPROM_NONE) { - SetReadHandler(0x6000, 0x7FFF, BANDAI_Read); - if (eeprom_type == EEPROM_X24C02) { - x24c02_init(eeprom); - } else if (eeprom_type == EEPROM_X24C01) { - x24c01_init(eeprom); - } - } -} - -void BANDAI_Init(CartInfo *info, EEPROM_TYPE _eeprom_type, int _isFCG) { - BANDAI_pwrap = GENPWRAP; - BANDAI_cwrap = GENCWRAP; - - eeprom_type = _eeprom_type; - isFCG12 = _isFCG; - - info->Power = BANDAI_Power; - MapIRQHook = BANDAI_IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - if (eeprom_type != EEPROM_NONE) { - info->battery = 1; - memset(eeprom, 0, sizeof(eeprom)); - if (eeprom_type == EEPROM_X24C02) { - info->SaveGame[0] = eeprom; - info->SaveGameLen[0] = 256; - AddExState(&x24c02_StateRegs, ~0, 0, 0); - } else if (eeprom_type == EEPROM_X24C01) { - info->SaveGame[0] = eeprom; - info->SaveGameLen[0] = 128; - AddExState(&x24c01_StateRegs, ~0, 0, 0); - } - } -} diff --git a/src/mappers/hw/bandai.h b/src/mappers/hw/bandai.h deleted file mode 100644 index 10bec3f96..000000000 --- a/src/mappers/hw/bandai.h +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _BANDAI_H -#define _BANDAI_H - -DECLFW(BANDAI_Write); - -void BANDAI_Power(void); -void BANDAI_IRQHook(int a); -void BANDAI_Reset(void); - -void BANDAI_Init(CartInfo *info, EEPROM_TYPE _eeprom_type, int _isFCG); - -void BANDAI_FixPRG(void); -void BANDAI_FixCHR(void); -void BANDAI_FixMIR(void); - -extern void (*BANDAI_pwrap)(uint16 A, uint16 V); -extern void (*BANDAI_cwrap)(uint16 A, uint16 V); - -#endif /* _BANDAI_H */ diff --git a/src/mappers/hw/eeprom_93Cx6.c b/src/mappers/hw/eeprom_93Cx6.c deleted file mode 100644 index 85f01a5ce..000000000 --- a/src/mappers/hw/eeprom_93Cx6.c +++ /dev/null @@ -1,173 +0,0 @@ -#include "mapinc.h" -#include "eeprom_93Cx6.h" - -struct EEPROM_93Cx6 { - uint8 *storage; - uint8 opcode; - uint16 data; - uint16 address; - uint8 state; - uint8 lastCLK; - uint8 writeEnabled; - uint8 output; - uint8 capacity; - uint8 wordsize; - uint8 state_address; - uint8 state_data; -} EEPROM_93Cx6; - -#define OPCODE_MISC 0 -#define OPCODE_WRITE 1 -#define OPCODE_READ 2 -#define OPCODE_ERASE 3 -#define OPCODE_WRITEDISABLE 10 -#define OPCODE_WRITEALL 11 -#define OPCODE_ERASEALL 12 -#define OPCODE_WRITEENABLE 13 - -#define STATE_STANDBY 0 -#define STATE_STARTBIT 1 -#define STATE_OPCODE 3 -#define STATE_ADDRESS8 12 -#define STATE_DATA8 20 -#define STATE_ADDRESS16 11 -#define STATE_DATA16 27 -#define STATE_FINISHED 99 - -static struct EEPROM_93Cx6 eeprom_93Cx6 = { 0 }; - -void eeprom_93Cx6_init(uint8 *data, uint32 capacity, uint8 wordsize) { - eeprom_93Cx6.storage = data; - eeprom_93Cx6.address = 0; - eeprom_93Cx6.state = STATE_STANDBY; - eeprom_93Cx6.lastCLK = FALSE; - eeprom_93Cx6.writeEnabled = FALSE; - eeprom_93Cx6.capacity = capacity; - eeprom_93Cx6.wordsize = wordsize; - - eeprom_93Cx6.state_address = (wordsize == 16) ? STATE_ADDRESS16 : STATE_ADDRESS8; - eeprom_93Cx6.state_data = (wordsize == 16) ? STATE_DATA16 : STATE_DATA8; -} - -uint8 eeprom_93Cx6_read(void) { - return eeprom_93Cx6.output; -} - -void eeprom_93Cx6_write(uint8 CS, uint8 CLK, uint8 DAT) { - if (!CS && (eeprom_93Cx6.state <= eeprom_93Cx6.state_address)) { - eeprom_93Cx6.state = STATE_STANDBY; - } else if ((eeprom_93Cx6.state == STATE_STANDBY) && CS && CLK && !eeprom_93Cx6.lastCLK) { - eeprom_93Cx6.state = STATE_STARTBIT; - eeprom_93Cx6.opcode = 0; - eeprom_93Cx6.address = 0; - eeprom_93Cx6.output = TRUE; - } else if (CLK && !eeprom_93Cx6.lastCLK) { - if ((eeprom_93Cx6.state >= STATE_STARTBIT) && (eeprom_93Cx6.state < STATE_OPCODE)) { - eeprom_93Cx6.opcode = (eeprom_93Cx6.opcode << 1) | (DAT ? 1 : 0); - } else if ((eeprom_93Cx6.state >= STATE_OPCODE) && (eeprom_93Cx6.state < eeprom_93Cx6.state_address)) { - eeprom_93Cx6.address = (eeprom_93Cx6.address << 1) | (DAT ? 1 : 0); - } else if ((eeprom_93Cx6.state >= eeprom_93Cx6.state_address) && (eeprom_93Cx6.state < eeprom_93Cx6.state_data)) { - if ((eeprom_93Cx6.opcode == OPCODE_WRITE) || (eeprom_93Cx6.opcode == OPCODE_WRITEALL)) { - eeprom_93Cx6.data = (eeprom_93Cx6.data << 1) | (DAT ? 1 : 0); - } else if (eeprom_93Cx6.opcode == OPCODE_READ) { - if (eeprom_93Cx6.wordsize == 16) { - eeprom_93Cx6.output = (eeprom_93Cx6.data & 0x8000) != 0; - } else { - eeprom_93Cx6.output = (eeprom_93Cx6.data & 0x80) != 0; - } - eeprom_93Cx6.data = eeprom_93Cx6.data << 1; - } - } - - eeprom_93Cx6.state++; - if (eeprom_93Cx6.state == eeprom_93Cx6.state_address) { - switch (eeprom_93Cx6.opcode) { - case OPCODE_MISC: - if (eeprom_93Cx6.wordsize == 16) { - eeprom_93Cx6.opcode = (eeprom_93Cx6.address >> 6) + 10; - } else { - eeprom_93Cx6.opcode = (eeprom_93Cx6.address >> 7) + 10; - } - switch (eeprom_93Cx6.opcode) { - case OPCODE_WRITEDISABLE: - eeprom_93Cx6.writeEnabled = FALSE; - eeprom_93Cx6.state = STATE_FINISHED; - break; - case OPCODE_WRITEENABLE: - eeprom_93Cx6.writeEnabled = TRUE; - eeprom_93Cx6.state = STATE_FINISHED; - break; - case OPCODE_ERASEALL: - if (eeprom_93Cx6.writeEnabled) { - int i; - - for (i = 0; i < eeprom_93Cx6.capacity; i++) { - eeprom_93Cx6.storage[i] = 0xFF; - } - } - eeprom_93Cx6.state = STATE_FINISHED; - break; - case OPCODE_WRITEALL: - eeprom_93Cx6.address = 0; - break; - } - break; - case OPCODE_ERASE: - if (eeprom_93Cx6.writeEnabled) { - if (eeprom_93Cx6.wordsize == 16) { - eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0] = 0xFF; - eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] = 0xFF; - } else { - eeprom_93Cx6.storage[eeprom_93Cx6.address] = 0xFF; - } - } - eeprom_93Cx6.state = STATE_FINISHED; - break; - case OPCODE_READ: - if (eeprom_93Cx6.wordsize == 16) { - eeprom_93Cx6.data = eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0]; - eeprom_93Cx6.data |= (eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] << 8); - eeprom_93Cx6.address++; - } else { - eeprom_93Cx6.data = eeprom_93Cx6.storage[eeprom_93Cx6.address++]; - } - break; - } - } else if (eeprom_93Cx6.state == eeprom_93Cx6.state_data) { - if (eeprom_93Cx6.opcode == OPCODE_WRITE) { - if (eeprom_93Cx6.wordsize == 16) { - eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0] = eeprom_93Cx6.data & 0xFF; - eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] = eeprom_93Cx6.data >> 8; - eeprom_93Cx6.address++; - } else { - eeprom_93Cx6.storage[eeprom_93Cx6.address++] = eeprom_93Cx6.data; - } - eeprom_93Cx6.state = STATE_FINISHED; - } else if (eeprom_93Cx6.opcode == OPCODE_WRITEALL) { - if (eeprom_93Cx6.wordsize == 16) { - eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0] = eeprom_93Cx6.data & 0xFF; - eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] = eeprom_93Cx6.data >> 8; - eeprom_93Cx6.address++; - } else { - eeprom_93Cx6.storage[eeprom_93Cx6.address++] = eeprom_93Cx6.data; - } - eeprom_93Cx6.state = (CS && (eeprom_93Cx6.address < eeprom_93Cx6.capacity)) ? eeprom_93Cx6.state_address : STATE_FINISHED; - } else if (eeprom_93Cx6.opcode == OPCODE_READ) { - if (eeprom_93Cx6.address < eeprom_93Cx6.capacity) { - if (eeprom_93Cx6.wordsize == 16) { - eeprom_93Cx6.data = eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 0]; - eeprom_93Cx6.data |= (eeprom_93Cx6.storage[(eeprom_93Cx6.address << 1) | 1] << 8); - } else { - eeprom_93Cx6.data = eeprom_93Cx6.storage[eeprom_93Cx6.address]; - } - } - eeprom_93Cx6.state = (CS && (++eeprom_93Cx6.address <= eeprom_93Cx6.capacity)) ? eeprom_93Cx6.state_address : STATE_FINISHED; - } - } - if (eeprom_93Cx6.state == STATE_FINISHED) { - eeprom_93Cx6.output = FALSE; - eeprom_93Cx6.state = STATE_STANDBY; - } - } - eeprom_93Cx6.lastCLK = CLK; -} diff --git a/src/mappers/hw/eeprom_93Cx6.h b/src/mappers/hw/eeprom_93Cx6.h deleted file mode 100644 index 439f4d025..000000000 --- a/src/mappers/hw/eeprom_93Cx6.h +++ /dev/null @@ -1,28 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _EEPROM_93Cx6_H -#define _EEPROM_93Cx6_H - -void eeprom_93Cx6_init (uint8 *data, uint32 capacity, uint8 wordsize); -uint8 eeprom_93Cx6_read (void); -void eeprom_93Cx6_write (uint8 CS, uint8 CLK, uint8 DAT); - -#endif diff --git a/src/mappers/hw/eeprom_x24c0x.c b/src/mappers/hw/eeprom_x24c0x.c deleted file mode 100644 index e0cf591a5..000000000 --- a/src/mappers/hw/eeprom_x24c0x.c +++ /dev/null @@ -1,251 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2011 FCEUX team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* x24C0x interface */ - -#include "mapinc.h" -#include "eeprom_x24c0x.h" - -#define X24C0X_STANDBY 0 -#define X24C0X_ADDRESS 1 -#define X24C0X_WORD 2 -#define X24C0X_READ 3 -#define X24C0X_WRITE 4 - -struct X24C0XP { - uint8 *data; - uint8 state; - uint8 addr; - uint8 word; - uint8 latch; - uint8 bitcount; - uint8 sda; - uint8 scl; - uint8 out; -} X24C0XP; - -static struct X24C0XP x24c01; -static struct X24C0XP x24c02; - -SFORMAT x24c01_StateRegs[] = { - { &x24c01.addr, 1, "ADDR" }, - { &x24c01.word, 1, "WORD" }, - { &x24c01.latch, 1, "LATC" }, - { &x24c01.bitcount, 1, "BITC" }, - { &x24c01.sda, 1, "SDA" }, - { &x24c01.scl, 1, "SCL" }, - { &x24c01.out, 1, "OUT" }, - { &x24c01.state, 1, "STAT" }, - { 0 } -}; - -SFORMAT x24c02_StateRegs[] = { - { &x24c02.addr, 1, "ADDR" }, - { &x24c02.word, 1, "WORD" }, - { &x24c02.latch, 1, "LATC" }, - { &x24c02.bitcount, 1, "BITC" }, - { &x24c02.sda, 1, "SDA" }, - { &x24c02.scl, 1, "SCL" }, - { &x24c02.out, 1, "OUT" }, - { &x24c02.state, 1, "STAT" }, - { 0 }, -}; - -void x24c01_init(uint8 *data) { - x24c01.data = data; - x24c01.addr = 0; - x24c01.word = 0; - x24c01.latch = 0; - x24c01.bitcount = 0; - x24c01.sda = 0; - x24c01.scl = 0; - x24c01.state = X24C0X_STANDBY; -} - -void x24c02_init(uint8 *data) { - x24c02.data = data; - x24c02.addr = 0; - x24c02.word = 0; - x24c02.latch = 0; - x24c02.bitcount = 0; - x24c02.sda = 0; - x24c02.scl = 0; - x24c02.state = X24C0X_STANDBY; -} - -uint8 x24c01_read(void) { - return x24c01.out; -} - -void x24c01_write(uint8 V) { - uint8 scl = (V >> 5) & 1; - uint8 sda = (V >> 6) & 1; - - if (x24c01.scl && scl) { - if (x24c01.sda && !sda) { /* START */ - x24c01.state = X24C0X_ADDRESS; - x24c01.bitcount = 0; - x24c01.addr = 0; - } else if (!x24c01.sda && sda) { /* STOP */ - x24c01.state = X24C0X_STANDBY; - } - } else if (!x24c01.scl && scl) { /* RISING EDGE */ - switch (x24c01.state) { - case X24C0X_ADDRESS: - if (x24c01.bitcount < 7) { - x24c01.addr <<= 1; - x24c01.addr |= sda; - } else { - x24c01.word = x24c01.addr; - if (sda) { /* READ COMMAND */ - x24c01.state = X24C0X_READ; - } else { /* WRITE COMMAND */ - x24c01.state = X24C0X_WRITE; - } - } - x24c01.bitcount++; - break; - case X24C0X_READ: - if (x24c01.bitcount == 8) { /* ACK */ - x24c01.out = 0; - x24c01.latch = x24c01.data[x24c01.word]; - x24c01.bitcount = 0; - } else { /* REAL OUTPUT */ - x24c01.out = x24c01.latch >> 7; - x24c01.latch <<= 1; - x24c01.bitcount++; - if (x24c01.bitcount == 8) { - x24c01.word++; - x24c01.word &= 0xff; - } - } - break; - case X24C0X_WRITE: - if (x24c01.bitcount == 8) { /* ACK */ - x24c01.out = 0; - x24c01.latch = 0; - x24c01.bitcount = 0; - } else { /* REAL INPUT */ - x24c01.latch <<= 1; - x24c01.latch |= sda; - x24c01.bitcount++; - if (x24c01.bitcount == 8) { - x24c01.data[x24c01.word] = x24c01.latch; - x24c01.word++; - x24c01.word &= 0xff; - } - } - break; - } - } - - x24c01.sda = sda; - x24c01.scl = scl; -} - -uint8 x24c02_read(void) { - return x24c02.out; -} - -void x24c02_write(uint8 V) { - uint8 scl = (V >> 5) & 1; - uint8 sda = (V >> 6) & 1; - - if (x24c02.scl && scl) { - if (x24c02.sda && !sda) { /* START */ - x24c02.state = X24C0X_ADDRESS; - x24c02.bitcount = 0; - x24c02.addr = 0; - } else if (!x24c02.sda && sda) { /* STOP */ - x24c02.state = X24C0X_STANDBY; - } - } else if (!x24c02.scl && scl) { /* RISING EDGE */ - switch (x24c02.state) { - case X24C0X_ADDRESS: - if (x24c02.bitcount < 7) { - x24c02.addr <<= 1; - x24c02.addr |= sda; - } else { - if ((x24c02.addr & 0x78) == 0x50) { - if (sda) { /* READ COMMAND */ - x24c02.state = X24C0X_READ; - } else { /* WRITE COMMAND */ - x24c02.state = X24C0X_WORD; - } - } else { /* invalid device address */ - x24c02.state = X24C0X_STANDBY; - x24c02.out = 1; - } - } - x24c02.bitcount++; - break; - case X24C0X_WORD: - if (x24c02.bitcount == 8) { /* ACK */ - x24c02.word = 0; - x24c02.out = 0; - } else { /* WORD ADDRESS INPUT */ - x24c02.word <<= 1; - x24c02.word |= sda; - if (x24c02.bitcount == 16) { /* END OF ADDRESS INPUT */ - x24c02.bitcount = 7; - x24c02.state = X24C0X_WRITE; - } - } - x24c02.bitcount++; - break; - case X24C0X_READ: - if (x24c02.bitcount == 8) { /* ACK */ - x24c02.out = 0; - x24c02.latch = x24c02.data[x24c02.word]; - x24c02.bitcount = 0; - } else { /* REAL OUTPUT */ - x24c02.out = x24c02.latch >> 7; - x24c02.latch <<= 1; - x24c02.bitcount++; - if (x24c02.bitcount == 8) { - x24c02.word++; - x24c02.word &= 0xff; - } - } - break; - case X24C0X_WRITE: - if (x24c02.bitcount == 8) { /* ACK */ - x24c02.out = 0; - x24c02.latch = 0; - x24c02.bitcount = 0; - } else { /* REAL INPUT */ - x24c02.latch <<= 1; - x24c02.latch |= sda; - x24c02.bitcount++; - if (x24c02.bitcount == 8) { - x24c02.data[x24c02.word] = x24c02.latch; - x24c02.word++; - x24c02.word &= 0xff; - } - } - break; - } - } - - x24c02.sda = sda; - x24c02.scl = scl; -} diff --git a/src/mappers/hw/eeprom_x24c0x.h b/src/mappers/hw/eeprom_x24c0x.h deleted file mode 100644 index 4567e208e..000000000 --- a/src/mappers/hw/eeprom_x24c0x.h +++ /dev/null @@ -1,40 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _EEPROM_X24C0X_H -#define _EEPROM_X24C0X_H - -typedef enum { - EEPROM_NONE = 0, - EEPROM_X24C01, - EEPROM_X24C02 -} EEPROM_TYPE; - -void x24c01_init(uint8 *data); -void x24c01_write(uint8 V); -uint8 x24c01_read(void); -extern SFORMAT x24c01_StateRegs[9]; - -void x24c02_init(uint8 *data); -void x24c02_write(uint8 V); -uint8 x24c02_read(void); -extern SFORMAT x24c02_StateRegs[9]; - -#endif /* _EEPROM_X24C0X_H */ diff --git a/src/mappers/hw/flashrom.c b/src/mappers/hw/flashrom.c deleted file mode 100644 index b9a00c963..000000000 --- a/src/mappers/hw/flashrom.c +++ /dev/null @@ -1,135 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "flashrom.h" - -static uint8 *flash_data; -static uint32 flash_size; - -static uint8 flash_id[2]; -static uint8 flash_state; -static uint32 flash_addr1; -static uint32 flash_addr2; -static uint32 flash_sect_size; -static int32 time_out; - -static SFORMAT FlashStateRegs[] = { - { &flash_state, 1, "STAT" }, - { &time_out, 4, "TIME" }, - { 0 } -}; - -#define PRG_OFFSET(A) (&Page[(A) >> 11][(A)] - flash_data) - -DECLFR(FlashROM_Read) { - if (flash_state == 0x90) { - /* 0: manufacturer id */ - /* 1: model id */ - return flash_id[A & 1]; - } else if (time_out > 0) { - return ((flash_data[PRG_OFFSET(A)] ^ ((time_out & 1) << 6)) & 0x77); - } - return flash_data[PRG_OFFSET(A)]; -} - -DECLFW(FlashROM_Write) { - uint32 chip_address = PRG_OFFSET(A); - uint32 cmd = chip_address & 0x7FFF; - - switch (flash_state) { - default: - case 0x80: - if ((cmd == flash_addr1) && (V == 0xAA)) { - flash_state++; - } - break; - case 0x01: - case 0x81: - if ((cmd == flash_addr2) && (V == 0x55)) { - flash_state++; - } - break; - case 0x02: - if (cmd == flash_addr1) { - flash_state = V; - } - break; - case 0x82: - /* sector or chip erase */ - if (V == 0x30) { - /* sector erase */ - if (chip_address < flash_size) { - uint32 i; - chip_address &= ~(flash_sect_size - 1); - for (i = 0; i < flash_sect_size; i++) { - flash_data[chip_address + i] = 0xFF; - } - FCEU_printf("Flash sector #%d is erased (0x%08x - 0x%08x).\n", chip_address / flash_sect_size, chip_address, chip_address + flash_sect_size); - time_out = flash_sect_size; - } - } else if ((cmd == flash_addr1) && (V == 0x10)) { - int i; - /* chip erase */ - for (i = 0; i <= (int)flash_size; i++) { - flash_data[i] = 0xFF; - } - FCEU_printf("Flash chip erased.\n"); - time_out = flash_size; - } else if (V == 0xF0) { - flash_state = 0; - } - break; - case 0x90: - /* software id */ - if (V == 0xF0) { - flash_state = 0; - } - break; - case 0xA0: - /* byte program */ - flash_data[chip_address] = V; - flash_state = 0; - break; - } - - /* FCEU_printf("%04x:%02x cmd:%04x state:%02x addr1:%04x addr2:%04x\n", A, V, cmd, flash_state, flash_addr1, flash_addr2); */ -} - -void FlashROM_CPUCyle(int a) { - if (time_out > 0) { - time_out -= a; - if (time_out <= 0) { - flash_state = 0; - } - } -} - -void FlashROM_Init(uint8 *data, uint32 size, uint8 manufacter_id, uint8 model_id, uint32 sector_size, uint32 adr1, uint32 adr2) { - flash_data = data; - flash_size = size; - flash_id[0] = manufacter_id; - flash_id[1] = model_id; - flash_addr1 = adr1; - flash_addr2 = adr2; - flash_sect_size = sector_size; - - AddExState(FlashStateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/hw/flashrom.h b/src/mappers/hw/flashrom.h deleted file mode 100644 index 19e6c50cb..000000000 --- a/src/mappers/hw/flashrom.h +++ /dev/null @@ -1,30 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef FLASHROM_H -#define FLASHROM_H - -DECLFW(FlashROM_Write); -DECLFR(FlashROM_Read); - -void FlashROM_Init(uint8 *data, uint32 size, uint8 manufacter_id, uint8 model_id, uint32 sector_size, uint32 adr1, uint32 adr2); -void FlashROM_CPUCyle(int a); - -#endif /* FLASHROM_H */ diff --git a/src/mappers/hw/fme7.c b/src/mappers/hw/fme7.c deleted file mode 100644 index 8d252e930..000000000 --- a/src/mappers/hw/fme7.c +++ /dev/null @@ -1,236 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "fme7.h" -#include "s5bsound.h" - -static uint8 IRQa; -static int32 IRQCount; - -FME7 fme7; - -void (*FME7_pwrap)(uint16 A, uint16 V); -void (*FME7_cwrap)(uint16 A, uint16 V); - -void (*FME7_FixWRAM)(void); -void (*FME7_FixPRG)(void); -void (*FME7_FixCHR)(void); -void (*FME7_FixMIR)(void); - -static SFORMAT StateRegs[] = { - { fme7.prg, 4, "PREG" }, - { fme7.chr, 8, "CREG" }, - { &fme7.cmd, 1, "CMDR" }, - { &fme7.mirr, 1, "MIRR" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 4, "IRQC" }, - { 0 } -}; - -static void GENPWRAP(uint16 A, uint16 V) { - setprg8(A, V); -} - -static void GENCWRAP(uint16 A, uint16 V) { - setchr1(A, V); -} - -static void GENFIXWRAM(void) { - if (fme7.prg[0] & 0x40) { - setprg8r(0x10, 0x6000, fme7.prg[0] & 0x3F); - } else { - setprg8(0x6000, fme7.prg[0] & 0x3F); - } -} - -static void GENFIXPRG(void) { - FME7_pwrap(0x8000, fme7.prg[1]); - FME7_pwrap(0xA000, fme7.prg[2]); - FME7_pwrap(0xC000, fme7.prg[3]); - FME7_pwrap(0xE000, ~0); -} - -static void GENFIXCHR(void) { - FME7_cwrap(0x0000, fme7.chr[0]); - FME7_cwrap(0x0400, fme7.chr[1]); - FME7_cwrap(0x0800, fme7.chr[2]); - FME7_cwrap(0x0C00, fme7.chr[3]); - FME7_cwrap(0x1000, fme7.chr[4]); - FME7_cwrap(0x1400, fme7.chr[5]); - FME7_cwrap(0x1800, fme7.chr[6]); - FME7_cwrap(0x1C00, fme7.chr[7]); -} - -static void GENFIXMIR(void) { - switch (fme7.mirr & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -static DECLFW(FME7_WRAMWrite) { - if ((fme7.prg[0] & 0xC0) == 0xC0) { - CartBW(A, V); - } -} - -static DECLFR(FME7_WRAMRead) { - if ((fme7.prg[0] & 0xC0) == 0x40) { - return CPU_OPENBUS; - } - return CartBR(A); - -} - -DECLFW(FME7_WriteIndex) { - fme7.cmd = V; -} - -DECLFW(FME7_WriteReg) { - switch (fme7.cmd & 0x0F) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - fme7.chr[fme7.cmd] = V; - FME7_FixCHR(); - break; - case 0x08: case 0x09: case 0x0A: case 0x0B: - fme7.prg[fme7.cmd & 0x03] = V; - FME7_FixPRG(); - FME7_FixWRAM(); - break; - case 0x0C: - fme7.mirr = V; - FME7_FixMIR(); - break; - case 0x0D: - IRQa = V; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x0E: - IRQCount = (IRQCount & 0xFF00) | (V & 0xFF); - break; - case 0x0F: - IRQCount = (IRQCount & 0x00FF) | (V << 8); - break; - } -} - -void FME7_Reset(void) { - fme7.prg[0] = 0; - fme7.prg[1] = 0; - fme7.prg[2] = 1; - fme7.prg[3] = ~1; - fme7.chr[0] = 0; - fme7.chr[1] = 1; - fme7.chr[2] = 2; - fme7.chr[3] = 3; - fme7.chr[4] = 4; - fme7.chr[5] = 5; - fme7.chr[6] = 6; - fme7.chr[7] = 7; - fme7.cmd = 0; - IRQCount = ~0; - IRQa = 0; - - FME7_FixPRG(); - FME7_FixCHR(); - FME7_FixMIR(); - FME7_FixWRAM(); -} - -void FME7_Power(void) { - SetReadHandler(0x8000, 0xFFFF, CartBR); - - SetWriteHandler(0x8000, 0x9FFF, FME7_WriteIndex); - SetWriteHandler(0xA000, 0xBFFF, FME7_WriteReg); - - SetReadHandler(0x6000, 0x7FFF, FME7_WRAMRead); - SetWriteHandler(0x6000, 0x7FFF, FME7_WRAMWrite); - - SetWriteHandler(0xC000, 0xDFFF, S5BSound_Write); - SetWriteHandler(0xE000, 0xFFFF, S5BSound_Write); - - if (WRAM) { - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } - - FME7_Reset(); -} - -static void FME7_Close(void) { -} - -static void FME7_IRQHook(int a) { - if (IRQa) { - IRQCount -= a; - if (IRQCount <= 0) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - IRQCount = 0xFFFF; - } - } -} - -static void StateRestore(int version) { - FME7_FixWRAM(); - FME7_FixPRG(); - FME7_FixCHR(); - FME7_FixMIR(); -} - -void FME7_Init(CartInfo *info, int wram, int battery) { - FME7_FixPRG = GENFIXPRG; - FME7_FixCHR = GENFIXCHR; - FME7_FixMIR = GENFIXMIR; - FME7_FixWRAM = GENFIXWRAM; - - FME7_pwrap = GENPWRAP; - FME7_cwrap = GENCWRAP; - - if (wram) { - WRAMSIZE = 8192; - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } - - info->Power = FME7_Power; - info->Close = FME7_Close; - MapIRQHook = FME7_IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - S5BSound_ESI(); - S5BSound_AddStateInfo(); -} diff --git a/src/mappers/hw/fme7.h b/src/mappers/hw/fme7.h deleted file mode 100644 index dd40c13da..000000000 --- a/src/mappers/hw/fme7.h +++ /dev/null @@ -1,47 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _FME7_H -#define _FME7_H -typedef struct __FME7 { - uint8 prg[4]; - uint8 chr[8]; - uint8 cmd; - uint8 mirr; -} FME7; - -extern FME7 fme7; - -DECLFW(FME7_WriteIndex); -DECLFW(FME7_WriteReg); - -void FME7_Init(CartInfo *info, int wram, int battery); -void FME7_Power(void); -void FME7_Reset(void); - -extern void (*FME7_FixPRG)(void); -extern void (*FME7_FixCHR)(void); -extern void (*FME7_FixMIR)(void); -extern void (*FME7_FixWRAM)(void); - -extern void (*FME7_pwrap)(uint16 A, uint16 V); -extern void (*FME7_cwrap)(uint16 A, uint16 V); - -#endif /* _FME7_H */ diff --git a/src/mappers/hw/jv001.c b/src/mappers/hw/jv001.c deleted file mode 100644 index 7291293a5..000000000 --- a/src/mappers/hw/jv001.c +++ /dev/null @@ -1,134 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * TXC/Micro Genius simplified mapper - * updated 06-2019 http://wiki.nesdev.com/w/index.php/INES_Mapper_036 - * - * Known games: - * - Strike Wolf (Asia) (Unl) - * - Policeman (Gluk Video) (unl) - * - F-15 City War (Spain) (Gluk Video) (Unl) - * - * TXC mappers, originally much complex banksitching - * - * 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang - * 01-22110-000 (52S ) - MGC-002 2-in-1 Gun - * 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block - * (079 ) - MGC-012 Poke Block - * 01-22110-200 (05-00002-010) (036 ) - MGC-014 Strike Wolf - * 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman - * 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior - * 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1 - * 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom - * 01-22200-400 (------------) (079 ) - ET.03 F-15 City War - * (172 ) - 1991 Du Ma Racing - * - */ - -/* added 2020-2-16 - * Updated based on latest source - * Mappers 36, 132, 173 - * Mappers 136, 147, 172 - */ - -#include "mapinc.h" -#include "jv001.h" - -JV001 jv001; - -static void Dummyfunc(void) { } -static void (*WSync)(void) = Dummyfunc; - -static SFORMAT StateRegs[] = -{ - { &jv001.accumulator, 1, "ACC0" }, - { &jv001.inverter, 1, "INVR" }, - { &jv001.staging, 1, "STG0" }, - { &jv001.output, 1, "OUT0" }, - { &jv001.increase, 1, "INC0" }, - { &jv001.X, 1, "XFLG" }, - { &jv001.invert, 1, "INVT" }, - { 0 } -}; - -DECLFR(JV001_Read) { - uint8 ret = CPU_OPENBUS; - if ((A & 0x103) == 0x100) { - ret = ((jv001.accumulator & 0x0F) | ((jv001.inverter ^ jv001.invert) & ~0x0F)); - WSync(); - } - return ret; -} - -DECLFW(JV001_Write) { - if (A & 0x8000) { - jv001.output = (jv001.accumulator & 0x0F) | (jv001.inverter & 0xF0); - } else { - switch (A & 0x103) { - case 0x100: - if (jv001.increase) { - jv001.accumulator++; - } else { - jv001.accumulator = ((jv001.accumulator & ~0x0F) | ((jv001.staging ^ jv001.invert) & 0x0F)); - } - break; - case 0x101: - jv001.invert = (V & 0x01) ? 0xFF : 0x00; - break; - case 0x102: - jv001.staging = V & 0x0F; - jv001.inverter = V & ~0x0F; - break; - case 0x103: - jv001.increase = ((V & 0x01) != 0); - break; - } - } - jv001.X = jv001.invert ? jv001.A : jv001.B; - WSync(); -} - -void JV001_Reset(void) { - WSync(); -} - -void JV001_Power(void) { - jv001.output = 0; - jv001.accumulator = 0; - jv001.inverter = 0; - jv001.staging = 0; - jv001.increase = 0; - jv001.invert = 0xFF; - jv001.X = 0; - jv001.A = 0; - jv001.B = 1; - JV001_Reset(); -} - -static void StateRestore(int version) { - WSync(); -} - -void JV001_Init(CartInfo *info, void (*proc)(void)) { - WSync = proc; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/hw/jv001.h b/src/mappers/hw/jv001.h deleted file mode 100644 index a2c0476bd..000000000 --- a/src/mappers/hw/jv001.h +++ /dev/null @@ -1,46 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _JV001_H -#define _JV001_H - -typedef struct __JV001 { - uint8 accumulator; - uint8 inverter; - uint8 staging; - uint8 output; - uint8 increase; - uint8 invert; - uint8 A; - uint8 B; - uint8 X; -} JV001; - -extern JV001 jv001; - -void JV001_Power(void); -void JV001_Reset(void); - -void JV001_Init(CartInfo *info, void (*proc)(void)); - -DECLFR(JV001_Read); -DECLFW(JV001_Write); - -#endif /* _JV001_H */ diff --git a/src/mappers/hw/jyasic.c b/src/mappers/hw/jyasic.c deleted file mode 100644 index 185ee251a..000000000 --- a/src/mappers/hw/jyasic.c +++ /dev/null @@ -1,520 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -JYASIC jyasic = { 0 }; - -static uint8 dipSwitch; -static uint8 allow_extended_mirroring; -static uint32 lastPPUAddress; - -uint8 JYASIC_CPUWriteHandlersSet; -writefunc JYASIC_cpuWrite[0x10000]; /* Actual write handlers for CPU write trapping as a method fo IRQ clocking */ - -void (*JYASIC_pwrap)(uint16 A, uint16 V); -void (*JYASIC_wwrap)(uint16 A, uint16 V); -void (*JYASIC_cwrap)(uint16 A, uint16 V); - -uint32 (*JYASIC_GetPRGBank)(uint32 V); -uint32 (*JYASIC_GetCHRBank)(uint32 V); - -static SFORMAT JYASIC_StateRegs[] = { - { jyasic.mode, 4, "TKCO" }, - { jyasic.prg, 4, "PRGB" }, - { jyasic.mul, 2, "MUL" }, - { jyasic.latch, 2, "CLTC" }, - { jyasic.chr, 16, "CHRB" }, - { jyasic.nt, 8, "NMS0" }, - { &jyasic.adder, 1, "ADDE" }, - { &jyasic.test, 1, "REGI" }, - { &jyasic.irq.control, 1, "IRQM" }, - { &jyasic.irq.prescaler, 1, "IRQP" }, - { &jyasic.irq.counter, 1, "IRQC" }, - { &jyasic.irq.xor, 1, "IRQX" }, - { &jyasic.irq.enable, 1, "IRQA" }, - { 0 } -}; - -static uint8 rev(uint8 val) { - return ( - ((val << 6) & 0x40) | - ((val << 4) & 0x20) | - ((val << 2) & 0x10) | - ((val << 0) & 0x08) | - ((val >> 2) & 0x04) | - ((val >> 4) & 0x02) | - ((val >> 6) & 0x01)); -} - -static uint32 GENPRGBANK(uint32 V) { return 0; } -static uint32 GENCHRBANK(uint32 V) { return 0; } - -static void GENPWRAP(uint16 A, uint16 V) { - uint32 bank = JYASIC_GetPRGBank(V); - setprg8(A, bank); -} - -static void GENCWRAP(uint16 A, uint16 V) { - uint32 bank = JYASIC_GetCHRBank(V); - setchr1(A, bank); -} - -static void GENWWRAP(uint16 A, uint16 V) { - uint32 bank = JYASIC_GetPRGBank(V); - setprg8(A, bank); -} - -void JYASIC_FixPRG(void) { - uint8 prgLast = (jyasic.mode[0] & 0x04) ? jyasic.prg[3] : 0xFF; - uint8 prg6000 = 0; - - switch (jyasic.mode[0] & 0x03) { - case 0: - JYASIC_pwrap(0x8000, (prgLast << 2) | 0); - JYASIC_pwrap(0xA000, (prgLast << 2) | 1); - JYASIC_pwrap(0xC000, (prgLast << 2) | 2); - JYASIC_pwrap(0xE000, (prgLast << 2) | 3); - prg6000 = (jyasic.prg[3] << 2) | 3; - break; - case 1: - JYASIC_pwrap(0x8000, (jyasic.prg[1] << 1) | 0); - JYASIC_pwrap(0xA000, (jyasic.prg[1] << 1) | 1); - JYASIC_pwrap(0xC000, (prgLast << 1) | 0); - JYASIC_pwrap(0xE000, (prgLast << 1) | 1); - prg6000 = (jyasic.prg[3] << 1) | 1; - break; - case 2: - JYASIC_pwrap(0x8000, jyasic.prg[0]); - JYASIC_pwrap(0xA000, jyasic.prg[1]); - JYASIC_pwrap(0xC000, jyasic.prg[2]); - JYASIC_pwrap(0xE000, prgLast); - prg6000 = jyasic.prg[3]; - break; - case 3: - JYASIC_pwrap(0x8000, rev(jyasic.prg[0])); - JYASIC_pwrap(0xA000, rev(jyasic.prg[1])); - JYASIC_pwrap(0xC000, rev(jyasic.prg[2])); - JYASIC_pwrap(0xE000, rev(prgLast)); - prg6000 = rev(jyasic.prg[3]); - break; - } - if (jyasic.mode[0] & 0x80) { /* Map ROM */ - JYASIC_wwrap(0x6000, prg6000); - } else if (WRAMSIZE) { /* Otherwise map WRAM if it exists */ - setprg8r(0x10, 0x6000, 0); - } -} - -void JYASIC_FixCHR(void) { - /* MMC4 jyasic.mode[0] with 4 KiB CHR jyasic.mode[0] */ - if (jyasic.mode[3] & 0x80 && (jyasic.mode[0] & 0x18) == 0x08) { - JYASIC_cwrap(0x0000, (jyasic.chr[(jyasic.latch[0] & 2) | 0] << 2) | 0); - JYASIC_cwrap(0x0400, (jyasic.chr[(jyasic.latch[0] & 2) | 0] << 2) | 1); - JYASIC_cwrap(0x0800, (jyasic.chr[(jyasic.latch[0] & 2) | 0] << 2) | 2); - JYASIC_cwrap(0x0C00, (jyasic.chr[(jyasic.latch[0] & 2) | 0] << 2) | 3); - JYASIC_cwrap(0x1000, (jyasic.chr[(jyasic.latch[1] & 2) | 4] << 2) | 0); - JYASIC_cwrap(0x1400, (jyasic.chr[(jyasic.latch[1] & 2) | 4] << 2) | 1); - JYASIC_cwrap(0x1800, (jyasic.chr[(jyasic.latch[1] & 2) | 4] << 2) | 2); - JYASIC_cwrap(0x1C00, (jyasic.chr[(jyasic.latch[1] & 2) | 4] << 2) | 3); - } else { - switch (jyasic.mode[0] & 0x18) { - case 0x00: /* 8 KiB CHR mode */ - JYASIC_cwrap(0x0000, (jyasic.chr[0] << 3) | 0); - JYASIC_cwrap(0x0400, (jyasic.chr[0] << 3) | 1); - JYASIC_cwrap(0x0800, (jyasic.chr[0] << 3) | 2); - JYASIC_cwrap(0x0C00, (jyasic.chr[0] << 3) | 3); - JYASIC_cwrap(0x1000, (jyasic.chr[0] << 3) | 4); - JYASIC_cwrap(0x1400, (jyasic.chr[0] << 3) | 5); - JYASIC_cwrap(0x1800, (jyasic.chr[0] << 3) | 6); - JYASIC_cwrap(0x1C00, (jyasic.chr[0] << 3) | 7); - break; - case 0x08: /* 4 KiB CHR mode */ - JYASIC_cwrap(0x0000, (jyasic.chr[0] << 2) | 0); - JYASIC_cwrap(0x0400, (jyasic.chr[0] << 2) | 1); - JYASIC_cwrap(0x0800, (jyasic.chr[0] << 2) | 2); - JYASIC_cwrap(0x0C00, (jyasic.chr[0] << 2) | 3); - JYASIC_cwrap(0x1000, (jyasic.chr[4] << 2) | 0); - JYASIC_cwrap(0x1400, (jyasic.chr[4] << 2) | 1); - JYASIC_cwrap(0x1800, (jyasic.chr[4] << 2) | 2); - JYASIC_cwrap(0x1C00, (jyasic.chr[4] << 2) | 3); - break; - case 0x10: /* 2 KiB CHR mode */ - JYASIC_cwrap(0x0000, (jyasic.chr[0] << 1) | 0); - JYASIC_cwrap(0x0400, (jyasic.chr[0] << 1) | 1); - JYASIC_cwrap(0x0800, (jyasic.chr[2] << 1) | 0); - JYASIC_cwrap(0x0C00, (jyasic.chr[2] << 1) | 1); - JYASIC_cwrap(0x1000, (jyasic.chr[4] << 1) | 0); - JYASIC_cwrap(0x1400, (jyasic.chr[4] << 1) | 1); - JYASIC_cwrap(0x1800, (jyasic.chr[6] << 1) | 0); - JYASIC_cwrap(0x1C00, (jyasic.chr[6] << 1) | 1); - break; - case 0x18: /* 1 KiB CHR mode */ - JYASIC_cwrap(0x0000, jyasic.chr[0]); - JYASIC_cwrap(0x0400, jyasic.chr[1]); - JYASIC_cwrap(0x0800, jyasic.chr[2]); - JYASIC_cwrap(0x0C00, jyasic.chr[3]); - JYASIC_cwrap(0x1000, jyasic.chr[4]); - JYASIC_cwrap(0x1400, jyasic.chr[5]); - JYASIC_cwrap(0x1800, jyasic.chr[6]); - JYASIC_cwrap(0x1C00, jyasic.chr[7]); - break; - } - } - - PPUCHRRAM = (jyasic.mode[2] & 0x40) ? 0xFF : 0x00; /* Write-protect or write-enable CHR-RAM */ -} - -void JYASIC_FixMIR(void) { - if (jyasic.mode[0] & 0x20 || jyasic.mode[1] & 0x08) { - /* ROM nametables or extended mirroring */ - /* First, set normal CIRAM pages using extended registers ... */ - setmirrorw(jyasic.nt[0] & 1, jyasic.nt[1] & 1, jyasic.nt[2] & 1, jyasic.nt[3] & 1); - - if (jyasic.mode[0] & 0x20) { - int i; - for (i = 0; i < 4; i++) { - /* Then replace with ROM nametables if such are generally enabled */ - /* ROM nametables are used either when globally enabled via - * D000.6 or per-bank via B00x.7 vs. D002.7 */ - if (((jyasic.nt[i] & 0x80) ^ (jyasic.mode[2] & 0x80)) | (jyasic.mode[0] & 0x40)) { - setntamem(CHRptr[0] + 0x400 * (JYASIC_GetCHRBank(jyasic.nt[i]) & CHRmask1[0]), 0, i); - } - } - } - } else { - switch (jyasic.mode[1] & 0x03) { - /* Regularly mirrored CIRAM */ - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } - } -} - -static void clockIRQ(void) { - uint8 mask = jyasic.irq.control & 0x04 ? 0x07 : 0xFF; - uint8 prescaler = jyasic.irq.prescaler & mask; - uint8 clockIrqCounter = FALSE; - - if (jyasic.irq.enable) { - switch (jyasic.irq.control & 0xC0) { - case 0x40: - prescaler++; - if ((prescaler & mask) == 0) { - clockIrqCounter = TRUE; - } - break; - case 0x80: - if (--prescaler == 0) { - clockIrqCounter = TRUE; - } - break; - } - - jyasic.irq.prescaler = (jyasic.irq.prescaler & ~mask) | (prescaler & mask); - - if (clockIrqCounter) { - switch (jyasic.irq.control & 0xC0) { - case 0x40: - if ((jyasic.irq.control & 0x08) == 0) { - jyasic.irq.counter++; - } - if (jyasic.irq.counter == 0x00) { - X6502_IRQBegin(FCEU_IQEXT); - } - break; - case 0x80: - if ((jyasic.irq.control & 0x08) == 0) { - jyasic.irq.counter--; - } - if (jyasic.irq.counter == 0xFF) { - X6502_IRQBegin(FCEU_IQEXT); - } - break; - } - } - } -} - -DECLFW(JYASIC_trapCPUWrite) { - if ((jyasic.irq.control & 0x03) == 0x03) { - clockIRQ(); /* Clock IRQ counter on CPU writes */ - } - JYASIC_cpuWrite[A](A, V); -} - -static void trapPPUAddressChange(uint32 A) { - if (((jyasic.irq.control & 0x03) == 0x02) && (lastPPUAddress != A)) { - int i; - for (i = 0; i < 2; i++) { - clockIRQ(); /* Clock IRQ counter on PPU "reads" */ - } - } - if ((jyasic.mode[3] & 0x80) && ((jyasic.mode[0] & 0x18) == 0x08) && (((A & 0x2FF0) == 0xFD0) || ((A & 0x2FF0) == 0xFE0))) { - /* If MMC4 jyasic.mode[0] is enabled, and CHR jyasic.mode[0] is 4 KiB, and tile FD or FE is being fetched ... */ - jyasic.latch[(A >> 12) & 1] = ((A >> 10) & 4) | ((A >> 4) & 2); /* switch the left or right pattern table's latch to 0 (FD) or 2 (FE), - * being used as an offset for the CHR register index. */ - JYASIC_FixCHR(); - } - lastPPUAddress = A; -} - -static void ppuScanline(void) { - if ((jyasic.irq.control & 0x03) == 0x01) { - int i; - for (i = 0; i < 8; i++) { - clockIRQ(); /* Clock IRQ counter on A12 rises (eight per scanline). This should be done in - trapPPUAddressChange, but would require more accurate PPU emulation for that. */ - } - } -} - -static void cpuCycle(int a) { - if ((jyasic.irq.control & 0x03) == 0x00) { - while (a--) { - clockIRQ(); /* Clock IRQ counter on M2 cycles */ - } - } -} - -DECLFR(JYASIC_ReadALU_DIP) { - if ((A & 0x3FF) == 0 && - A != 0x5800) { /* 5000, 5400, 5C00: read solder pad setting */ - return dipSwitch | (CPU_OPENBUS & 0x3F); - } - - if (A & 0x800) { - switch (A & 3) { - /* 5800-5FFF: read ALU */ - case 0: return (jyasic.mul[0] * jyasic.mul[1]) & 0xFF; - case 1: return (jyasic.mul[0] * jyasic.mul[1]) >> 8; - case 2: return jyasic.adder; - case 3: return jyasic.test; - } - } - /* all others */ - return CPU_OPENBUS; -} - -DECLFW(JYASIC_WriteALU) { - switch (A & 3) { - case 0: jyasic.mul[0] = V; break; - case 1: jyasic.mul[1] = V; break; - case 2: jyasic.adder += V; break; - case 3: jyasic.test = V; jyasic.adder = 0; break; - } -} - -DECLFW(JYASIC_WritePRG) { - jyasic.prg[A & 3] = V; - JYASIC_FixPRG(); -} - -DECLFW(JYASIC_WriteCHRLow) { - jyasic.chr[A & 7] = (jyasic.chr[A & 7] & 0xFF00) | V; - JYASIC_FixCHR(); -} - -DECLFW(JYASIC_WriteCHRHigh) { - jyasic.chr[A & 7] = (jyasic.chr[A & 7] & 0x00FF) | V << 8; - JYASIC_FixCHR(); -} - -DECLFW(JYASIC_WriteNT) { - if (~A & 4) { - jyasic.nt[A & 3] = (jyasic.nt[A & 3] & 0xFF00) | V; - } else { - jyasic.nt[A & 3] = (jyasic.nt[A & 3] & 0x00FF) | V << 8; - } - JYASIC_FixMIR(); -} - -DECLFW(JYASIC_WriteIRQ) { - switch (A & 7) { - case 0: - jyasic.irq.enable = !!(V & 1); - if (!jyasic.irq.enable) { - jyasic.irq.prescaler = 0; - X6502_IRQEnd(FCEU_IQEXT); - } - break; - case 1: - jyasic.irq.control = V; - break; - case 2: - jyasic.irq.enable = 0; - jyasic.irq.prescaler = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: - jyasic.irq.enable = 1; - break; - case 4: - jyasic.irq.prescaler = V ^ jyasic.irq.xor; - break; - case 5: - jyasic.irq.counter = V ^ jyasic.irq.xor; - break; - case 6: - jyasic.irq.xor = V; - break; - } -} - -DECLFW(JYASIC_WriteMode) { - switch (A & 3) { - case 0: - jyasic.mode[0] = V; - if (!allow_extended_mirroring) { - jyasic.mode[0] &= ~0x20; - } - break; - case 1: - jyasic.mode[1] = V; - if (!allow_extended_mirroring) { - jyasic.mode[1] &= ~0x08; - } - break; - case 2: - jyasic.mode[2] = V; - break; - case 3: - jyasic.mode[3] = V; - break; - } - JYASIC_FixPRG(); - JYASIC_FixCHR(); - JYASIC_FixMIR(); -} - -void JYASIC_restoreWriteHandlers(void) { - int i; - if (JYASIC_CPUWriteHandlersSet) { - for (i = 0; i < 0x10000; i++) { - SetWriteHandler(i, i, JYASIC_cpuWrite[i]); - } - JYASIC_CPUWriteHandlersSet = 0; - } -} - -void JYASIC_RegReset(void) { - memset(jyasic.mode, 0, sizeof(jyasic.mode)); - memset(jyasic.prg, 0, sizeof(jyasic.prg)); - memset(jyasic.chr, 0, sizeof(jyasic.chr)); - memset(jyasic.nt, 0, sizeof(jyasic.nt)); - memset(jyasic.mul, 0, sizeof(jyasic.mul)); - - jyasic.adder = jyasic.test = dipSwitch = 0; - jyasic.irq.control = jyasic.irq.enable = 0; - jyasic.irq.prescaler = jyasic.irq.counter = 0; - jyasic.irq.xor = lastPPUAddress = 0; - - jyasic.latch[0] = 0; - jyasic.latch[1] = 4; - - JYASIC_FixPRG(); - JYASIC_FixCHR(); - JYASIC_FixMIR(); -} - -void JYASIC_Power(void) { - int i; - - SetWriteHandler(0x5000, 0x5FFF, JYASIC_WriteALU); - SetWriteHandler(0x6000, 0x7fff, CartBW); - SetWriteHandler(0x8000, 0x87FF, JYASIC_WritePRG); /* 8800-8FFF ignored */ - SetWriteHandler(0x9000, 0x97FF, JYASIC_WriteCHRLow); /* 9800-9FFF ignored */ - SetWriteHandler(0xA000, 0xA7FF, JYASIC_WriteCHRHigh); /* A800-AFFF ignored */ - SetWriteHandler(0xB000, 0xB7FF, JYASIC_WriteNT); /* B800-BFFF ignored */ - SetWriteHandler(0xC000, 0xCFFF, JYASIC_WriteIRQ); - SetWriteHandler(0xD000, 0xD7FF, JYASIC_WriteMode); /* D800-DFFF ignored */ - - JYASIC_restoreWriteHandlers(); - for (i = 0; i < 0x10000; i++) { - JYASIC_cpuWrite[i] = GetWriteHandler(i); - } - SetWriteHandler(0x0000, 0xFFFF, JYASIC_trapCPUWrite); /* Trap all CPU writes for IRQ clocking purposes */ - JYASIC_CPUWriteHandlersSet = 1; - - SetReadHandler(0x5000, 0x5FFF, JYASIC_ReadALU_DIP); - SetReadHandler(0x6000, 0xFFFF, CartBR); - - JYASIC_RegReset(); -} - -void JYASIC_Reset(void) { - dipSwitch = (dipSwitch + 0x40) & 0xC0; - JYASIC_FixPRG(); - JYASIC_FixCHR(); - JYASIC_FixMIR(); -} - -void JYASIC_Close(void) { -} - -static void StateRestore(int version) { - JYASIC_FixPRG(); - JYASIC_FixCHR(); - JYASIC_FixMIR(); -} - -void JYASIC_Init(CartInfo *info, int extended_mirr) { - JYASIC_pwrap = GENPWRAP; - JYASIC_wwrap = GENWWRAP; - JYASIC_cwrap = GENCWRAP; - - JYASIC_GetPRGBank = GENPRGBANK; - JYASIC_GetCHRBank = GENCHRBANK; - - allow_extended_mirroring = extended_mirr; - - JYASIC_CPUWriteHandlersSet = 0; - info->Reset = JYASIC_Reset; - info->Power = JYASIC_Power; - info->Close = JYASIC_Close; - - PPU_hook = trapPPUAddressChange; - MapIRQHook = cpuCycle; - GameHBIRQHook2 = ppuScanline; - - AddExState(JYASIC_StateRegs, ~0, 0, 0); - GameStateRestore = StateRestore; - - /* WRAM is present only in iNES mapper 35, or in mappers with numbers above 255 that require NES 2.0, which - * explicitly denotes WRAM size */ - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } else { - WRAMSIZE = info->mapper == 35 ? 8192 : 0; - } - - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } -} diff --git a/src/mappers/hw/jyasic.h b/src/mappers/hw/jyasic.h deleted file mode 100644 index 2b43f0761..000000000 --- a/src/mappers/hw/jyasic.h +++ /dev/null @@ -1,75 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _JYASIC_H -#define _JYASIC_H - -typedef struct __JYASIC { - uint8 mode[4]; - uint8 prg[4]; - uint8 mul[2]; - uint8 adder; - uint8 test; - uint8 latch[2]; - uint16 chr[8]; - uint16 nt[4]; - struct irq { - uint8 control; - uint8 enable; - uint8 prescaler; - uint8 counter; - uint8 xor; - } irq; -} JYASIC; - -extern JYASIC jyasic; - -extern uint8 JYASIC_CPUWriteHandlersSet; -extern writefunc JYASIC_cpuWrite[0x10000]; - -DECLFR(JYASIC_ReadALU_DIP); -DECLFW(JYASIC_trapCPUWrite); -DECLFW(JYASIC_WriteALU); -DECLFW(JYASIC_WritePRG); -DECLFW(JYASIC_WriteCHRLow); -DECLFW(JYASIC_WriteCHRHigh); -DECLFW(JYASIC_WriteNT); -DECLFW(JYASIC_WriteIRQ); -DECLFW(JYASIC_WriteMode); - -void JYASIC_restoreWriteHandlers(void); -void JYASIC_RegReset(void); -void JYASIC_Reset(void); -void JYASIC_Close(void); -void JYASIC_Power(void); -void JYASIC_Init(CartInfo * info, int extended_mirr); - -void JYASIC_FixPRG(void); -void JYASIC_FixCHR(void); -void JYASIC_FixMIR(void); - -extern void (*JYASIC_pwrap)(uint16 A, uint16 V); -extern void (*JYASIC_wwrap)(uint16 A, uint16 V); -extern void (*JYASIC_cwrap)(uint16 A, uint16 V); - -extern uint32 (*JYASIC_GetPRGBank)(uint32 V); -extern uint32 (*JYASIC_GetCHRBank)(uint32 V); - -#endif /* _JYASIC_H */ diff --git a/src/mappers/hw/ks202.c b/src/mappers/hw/ks202.c deleted file mode 100644 index d72f161bd..000000000 --- a/src/mappers/hw/ks202.c +++ /dev/null @@ -1,137 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * KS202 Asic, used for Mapper 142, and Mapper 56 with extra PAL chip - * - */ - -#include "mapinc.h" -#include "ks202.h" - -static uint8 IRQa = 0; -static int32 IRQCount, IRQLatch; - -static void (*WSync)(void); - -KS202 ks202 = { 0 }; - -static SFORMAT StateRegs[] = -{ - { &ks202.cmd, 1, "CMD" }, - { ks202.reg, 8, "REGS" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 4, "IRQC" }, - { 0 } -}; - -DECLFW(KS202_Write) { -/* FCEU_printf("bs %04x %02x\n",A,V); */ - switch (A & 0xF000) { - case 0x8000: - IRQLatch = (IRQLatch & 0xFFF0) | (V & 0x0F); - break; - case 0x9000: - IRQLatch = (IRQLatch & 0xFF0F) | ((V & 0x0F) << 4); - break; - case 0xA000: - IRQLatch = (IRQLatch & 0xF0FF) | ((V & 0x0F) << 8); - break; - case 0xB000: - IRQLatch = (IRQLatch & 0x0FFF) | (V << 12); - break; - case 0xC000: - IRQa = (V & 0xF); - if (IRQa) { - IRQCount = IRQLatch; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xD000: - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xE000: - ks202.cmd = V & 7; - break; - case 0xF000: - ks202.reg[ks202.cmd] = V; - WSync(); - break; - } -} - -static void KS202IRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount >= 0xFFFF) { - IRQa = 0; - IRQCount = IRQLatch; - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -void KS202_Power(void) { - KS202_Reset(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, KS202_Write); - if (WRAMSIZE) { - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } -} - -void KS202_Reset(void) { - ks202.reg[0] = ks202.reg[1] = ks202.reg[2] = ks202.reg[3] = 0; - ks202.reg[4] = ks202.reg[5] = ks202.reg[6] = ks202.reg[7] = 0; - ks202.cmd = 0; - IRQa = IRQCount = IRQLatch = 0; - WSync(); -} - -void KS202_Close(void) { -} - -void KS202_Restore(int version) { - WSync(); -} - -void KS202_Init(CartInfo *info, void (*proc)(void), int wram, int battery) { - WSync = proc; - - info->Power = KS202_Power; - info->Close = KS202_Close; - MapIRQHook = KS202IRQHook; - GameStateRestore = KS202_Restore; - - AddExState(StateRegs, ~0, 0, NULL); - - if (wram) { - WRAMSIZE = 8 * 1024; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - if (battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } -} diff --git a/src/mappers/hw/ks202.h b/src/mappers/hw/ks202.h deleted file mode 100644 index f06c352d5..000000000 --- a/src/mappers/hw/ks202.h +++ /dev/null @@ -1,40 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _KS202_H -#define _KS202_H - -typedef struct __KS202 { - uint8 reg[8]; - uint8 cmd; -} KS202; - -extern KS202 ks202; - -DECLFW(KS202_Write); - -void KS202_Power(void); -void KS202_Close(void); -void KS202_Reset(void); -void KS202_Restore(int version); - -void KS202_Init(CartInfo *info, void (*proc)(void), int wram, int battery); - -#endif /* _KS202_H */ diff --git a/src/mappers/hw/latch.c b/src/mappers/hw/latch.c deleted file mode 100644 index 63cc7454c..000000000 --- a/src/mappers/hw/latch.c +++ /dev/null @@ -1,92 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 bus_conflict; -static void (*WSync)(void); -static readfunc defread; - -LATCH latch; - -DECLFW(Latch_Write) { - /* FCEU_printf("bs %04x %02x\n",A,V); */ - if (bus_conflict) { - V &= CartBR(A); - } - latch.addr = A; - latch.data = V; - WSync(); -} - -void Latch_RegReset(void) { - latch.addr = 0; - latch.data = 0; - WSync(); -} - -void Latch_Power(void) { - Latch_RegReset(); - if (WRAM) { - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } - SetReadHandler(0x8000, 0xFFFF, defread); - SetWriteHandler(0x8000, 0xFFFF, Latch_Write); -} - -void Latch_Close(void) { -} - -static void LatchReset(void) { - WSync(); -} - -static void StateRestore(int version) { - WSync(); -} - -void Latch_Init(CartInfo *info, void (*proc)(void), readfunc func, - uint8 wram, uint8 busc) { - bus_conflict = busc; - WSync = proc; - if (func != NULL) - defread = func; - else - defread = CartBROB; - info->Power = Latch_Power; - info->Close = Latch_Close; - info->Reset = LatchReset; - GameStateRestore = StateRestore; - if (wram) { - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - AddExState(&latch.addr, 2, 0, "ADDR"); - AddExState(&latch.data, 1, 0, "DATA"); -} diff --git a/src/mappers/hw/latch.h b/src/mappers/hw/latch.h deleted file mode 100644 index 22b36f6d3..000000000 --- a/src/mappers/hw/latch.h +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _FCEU_LATCH_H -#define _FCEU_LATCH_H - -typedef struct __LATCH { - uint16 addr; - uint8 data; -} LATCH; - -extern LATCH latch; - -DECLFW(Latch_Write); - -void Latch_Power(void); -void Latch_Close(void); -void Latch_RegReset(void); - -void Latch_Init(CartInfo *info, void (*proc)(void), readfunc func, uint8 wram, uint8 busc); - -#endif /* _FCEU_LATCH_H */ diff --git a/src/mappers/hw/mmc1.c b/src/mappers/hw/mmc1.c deleted file mode 100644 index d13186d66..000000000 --- a/src/mappers/hw/mmc1.c +++ /dev/null @@ -1,280 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 1998 BERO - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc1.h" - - /* size of non-battery-backed portion of WRAM */ - /* serves as starting offset for actual save ram from total wram size */ - /* returns 0 if entire work ram is battery backed ram */ -static uint32 NONSaveRAMSIZE = 0; - -MMC1Type mmc1_type = MMC1B; - -void (*MMC1_pwrap)(uint16 A, uint16 V); -void (*MMC1_cwrap)(uint16 A, uint16 V); -void (*MMC1_mwrap)(uint8 V); -void (*MMC1_wwrap)(void); - -MMC1 mmc1; - -static void GENWRAMWRAP(void) { - uint8 bank = 0; - - if (!WRAMSIZE) { - return; - } - if (WRAMSIZE > 8192) { - if (WRAMSIZE > 16384) { - bank = (mmc1.reg[1] >> 2) & 3; - } else { - bank = (mmc1.reg[1] >> 3) & 1; - } - } - setprg8r(0x10, 0x6000, bank); -} - -static void GENPWRAP(uint16 A, uint16 V) { - setprg16(A, V & 0x0F); -} - -static void GENCWRAP(uint16 A, uint16 V) { - setchr4(A, V & 0x1F); -} - -static uint8 MMC1WRAMEnabled(void) { - if ((mmc1.reg[3] & 0x10) && (mmc1_type == MMC1B)) { - return FALSE; - } - - return TRUE; -} - -static DECLFW(MBWRAM) { - if (MMC1WRAMEnabled()) { - /* WRAM is enabled. */ - CartBW(A, V); - } -} - -static DECLFR(MAWRAM) { - if (!MMC1WRAMEnabled()) { - /* WRAM is disabled */ - return CPU_OPENBUS; - } - - return CartBR(A); -} - -uint32 MMC1_GetPRGBank(int index) { - uint32 bank; - uint8 prg = mmc1.reg[3]; - - switch (mmc1.reg[0] & 0xC) { - case 0xC: - bank = prg | (index * 0x0F); - break; - case 0x8: - bank = (prg & (index * 0x0F)); - break; - case 0x0: - case 0x4: - default: - bank = (prg & ~1) | index; - break; - } - - if ((mmc1.reg[3] & 0x10) && (mmc1_type == MMC1A)) { - return ((bank & 0x07) | (mmc1.reg[3] & 0x08)); - } - - return (bank & 0x0F); -} - -uint32 MMC1_GetCHRBank(int index) { - if (mmc1.reg[0] & 0x10) { - return (mmc1.reg[1 + index]); - } - - return ((mmc1.reg[1] & ~1) | index); -} - -void MMC1_FixCHR(void) { - if (MMC1_wwrap) { - MMC1_wwrap(); - } - - MMC1_cwrap(0x0000, MMC1_GetCHRBank(0)); - MMC1_cwrap(0x1000, MMC1_GetCHRBank(1)); -} - -void MMC1_FixPRG(void) { - MMC1_pwrap(0x8000, MMC1_GetPRGBank(0)); - MMC1_pwrap(0xC000, MMC1_GetPRGBank(1)); -} - -void MMC1_FixMIR(void) { - switch (mmc1.reg[0] & 3) { - case 2: setmirror(MI_V); break; - case 3: setmirror(MI_H); break; - case 0: setmirror(MI_0); break; - case 1: setmirror(MI_1); break; - } -} - -static uint64 lreset; -DECLFW(MMC1_Write) { - int n = (A >> 13) - 4; - - /* The MMC1 is busy so ignore the write. */ - /* As of version FCE Ultra 0.81, the timestamp is only - increased before each instruction is executed(in other words - precision isn't that great), but this should still work to - deal with 2 writes in a row from a single RMW instruction. - */ - if ((timestampbase + timestamp) < (lreset + 2)) { - return; - } - - /* FCEU_printf("Write %04x:%02x\n",A,V); */ - if (V & 0x80) { - mmc1.reg[0] |= 0xC; - mmc1.shift = mmc1.buffer = 0; - MMC1_FixPRG(); - lreset = timestampbase + timestamp; - return; - } - - mmc1.buffer |= (V & 1) << (mmc1.shift++); - - if (mmc1.shift == 5) { - /* FCEU_printf("REG[%d]=%02x\n",n,mmc1.buffer); */ - mmc1.reg[n] = mmc1.buffer; - mmc1.shift = mmc1.buffer = 0; - switch (n) { - case 0: - MMC1_FixMIR(); - MMC1_FixCHR(); - MMC1_FixPRG(); - break; - case 1: - MMC1_FixCHR(); - MMC1_FixPRG(); - break; - case 2: - MMC1_FixCHR(); - break; - case 3: - MMC1_FixPRG(); - break; - } - } -} - -void MMC1_Restore(int version) { - MMC1_FixMIR(); - MMC1_FixCHR(); - MMC1_FixPRG(); - lreset = 0; /* timestamp(base) is not stored in save states. */ -} - -void MMC1_Reset(void) { - mmc1.reg[0] = 0x0C; - mmc1.reg[1] = 0; - mmc1.reg[2] = 0; - mmc1.reg[3] = 0; - - mmc1.buffer = mmc1.shift = 0; - - MMC1_FixPRG(); - MMC1_FixCHR(); - MMC1_FixMIR(); - - lreset = 0; -} - -void MMC1_Power(void) { - lreset = 0; - SetWriteHandler(0x8000, 0xFFFF, MMC1_Write); - SetReadHandler(0x8000, 0xFFFF, CartBR); - - if (WRAMSIZE) { - FCEU_CheatAddRAM(8, 0x6000, WRAM); - - /* clear non-battery-backed portion of WRAM */ - if (NONSaveRAMSIZE) { - FCEU_MemoryRand(WRAM, NONSaveRAMSIZE); - } - - SetReadHandler(0x6000, 0x7FFF, MAWRAM); - SetWriteHandler(0x6000, 0x7FFF, MBWRAM); - setprg8r(0x10, 0x6000, 0); - } - - MMC1_Reset(); -} - -void MMC1_Close(void) { -} - -void MMC1_Init(CartInfo *info, int wram, int saveram) { - MMC1_pwrap = GENPWRAP; - MMC1_cwrap = GENCWRAP; - MMC1_wwrap = GENWRAMWRAP; - - WRAMSIZE = wram * 1024; - NONSaveRAMSIZE = (wram - saveram) * 1024; - - if (WRAMSIZE) { - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (saveram) { - info->SaveGame[0] = WRAM + NONSaveRAMSIZE; - info->SaveGameLen[0] = saveram * 1024; - } - } - - AddExState(mmc1.reg, 4, 0, "DREG"); - - info->Power = MMC1_Power; - info->Close = MMC1_Close; - GameStateRestore = MMC1_Restore; - AddExState(&mmc1.buffer, 1, 0, "BFFR"); - AddExState(&mmc1.shift, 1, 0, "BFRS"); -} - -void SAROM_Init(CartInfo *info) { - MMC1_Init(info, 8, info->battery ? 8 : 0); -} - -void SKROM_Init(CartInfo *info) { - MMC1_Init(info, 8, info->battery ? 8 : 0); -} - -void SNROM_Init(CartInfo *info) { - MMC1_Init(info, 8, info->battery ? 8 : 0); -} - -void SOROM_Init(CartInfo *info) { - MMC1_Init(info, 16, info->battery ? 8 : 0); -} diff --git a/src/mappers/hw/mmc1.h b/src/mappers/hw/mmc1.h deleted file mode 100644 index 9970cb9db..000000000 --- a/src/mappers/hw/mmc1.h +++ /dev/null @@ -1,59 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _MMC1_H -#define _MMC1_H - -typedef enum { - MMC1A, - MMC1B -} MMC1Type; - -typedef struct __MMC1 { - uint8 reg[4]; - uint8 buffer; - uint8 shift; -} MMC1; - -extern MMC1 mmc1; -extern MMC1Type mmc1_type; - -uint32 MMC1_GetPRGBank(int index); -uint32 MMC1_GetCHRBank(int index); - -DECLFW(MMC1_Write); - -void MMC1_Power(void); -void MMC1_Close(void); -void MMC1_Restore(int version); -void MMC1_Reset(void); - -void MMC1_Init(CartInfo *info, int wram, int saveram); - -void MMC1_FixPRG(void); -void MMC1_FixCHR(void); -void MMC1_FixMIR(void); - -extern void (*MMC1_pwrap)(uint16 A, uint16 V); -extern void (*MMC1_cwrap)(uint16 A, uint16 V); -extern void (*MMC1_mwrap)(uint8 V); -extern void (*MMC1_wwrap)(void); - -#endif /* _MMC1_H */ diff --git a/src/mappers/hw/mmc2.c b/src/mappers/hw/mmc2.c deleted file mode 100644 index 4a2023ba7..000000000 --- a/src/mappers/hw/mmc2.c +++ /dev/null @@ -1,150 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "mmc2.h" - -void (*MMC2_pwrap)(uint16 A, uint16 V); -void (*MMC2_cwrap)(uint16 A, uint16 V); -void (*MMC2_mwrap)(uint8 V); - -MMC2 mmc2; - -static SFORMAT StateRegs[] = -{ - { mmc2.chr, 4, "CREG" }, - { mmc2.latch, 2, "PPUL" }, - { &mmc2.prg, 1, "PREG" }, - { &mmc2.mirr, 1, "MIRR" }, - { 0 } -}; - -static void GENPWRAP(uint16 A, uint16 V) { - setprg8(A, V); -} - -static void GENCWRAP(uint16 A, uint16 V) { - setchr4(A, V); -} - -static void GENMWRAP(uint8 V) { - mmc2.mirr = V; - setmirror((mmc2.mirr & 1) ^ 1); -} - -void MMC2_FixPRG(void) { - MMC2_pwrap(0x8000, mmc2.prg); - MMC2_pwrap(0xA000, ~2); - MMC2_pwrap(0xC000, ~1); - MMC2_pwrap(0xE000, ~0); -} - -void MMC2_FixCHR(void) { - MMC2_cwrap(0x0000, mmc2.chr[mmc2.latch[0] | 0]); - MMC2_cwrap(0x1000, mmc2.chr[mmc2.latch[1] | 2]); - - if (MMC2_mwrap) { - MMC2_mwrap(mmc2.mirr); - } -} - -DECLFW(MMC2_Write) { - switch (A & 0xF000) { - case 0xA000: - mmc2.prg = V; - MMC2_FixPRG(); - break; - case 0xB000: - case 0xC000: - case 0xD000: - case 0xE000: - mmc2.chr[(A - 0xB000) >> 12] = V; - MMC2_FixCHR(); - break; - case 0xF000: - if (MMC2_mwrap) { - MMC2_mwrap(V); - } - break; - } -} - -static void MMC2PPUHook(uint32 A) { - uint8 bank = (A >> 12) & 0x01; - if ((A & 0x2000) || (((A & 0xFF0) != 0xFD0) && ((A & 0xFF0) != 0xFE0))) { - return; - } - mmc2.latch[bank] = (A >> 5) & 0x01; - MMC2_FixCHR(); -} - -void MMC2_Reset(void) { - mmc2.prg = mmc2.mirr = 0; - mmc2.latch[0] = mmc2.latch[1] = 0; - MMC2_FixPRG(); - MMC2_FixCHR(); -} - -void MMC2_Power(void) { - MMC2_Reset(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0xA000, 0xFFFF, MMC2_Write); - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } -} - -void MMC2_Restore(int version) { - MMC2_FixPRG(); - MMC2_FixCHR(); -} - -void MMC2_Close(void) { -} - -void MMC2_Init(CartInfo *info, int wram, int battery) { - MMC2_pwrap = GENPWRAP; - MMC2_cwrap = GENCWRAP; - MMC2_mwrap = GENMWRAP; - - info->Power = MMC2_Power; - info->Close = MMC2_Close; - PPU_hook = MMC2PPUHook; - - GameStateRestore = MMC2_Restore; - AddExState(StateRegs, ~0, 0, NULL); - - if (wram) { - WRAMSIZE = wram * 1024; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } -} diff --git a/src/mappers/hw/mmc2.h b/src/mappers/hw/mmc2.h deleted file mode 100644 index 43f8b6fbd..000000000 --- a/src/mappers/hw/mmc2.h +++ /dev/null @@ -1,48 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _MMC2_H -#define _MMC2_H - -typedef struct __MMC2 { - uint8 prg; - uint8 chr[4]; - uint8 latch[2]; - uint8 mirr; -} MMC2; - -extern MMC2 mmc2; - -DECLFW(MMC2_Write); - -void MMC2_Power(void); -void MMC2_Close(void); -void MMC2_Reset(void); -void MMC2_Restore(int version); -void MMC2_Init(CartInfo *info, int wram, int battery); - -void MMC2_FixPRG(void); -void MMC2_FixCHR(void); - -extern void (*MMC2_pwrap)(uint16 A, uint16 V); -extern void (*MMC2_cwrap)(uint16 A, uint16 V); -extern void (*MMC2_mwrap)(uint8 V); - -#endif /* _MMC2_H */ diff --git a/src/mappers/hw/mmc3.c b/src/mappers/hw/mmc3.c deleted file mode 100644 index a32a099ad..000000000 --- a/src/mappers/hw/mmc3.c +++ /dev/null @@ -1,337 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 1998 BERO - * Copyright (C) 2003 Xodnizel - * Mapper 12 code Copyright (C) 2003 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Code for emulating iNES mappers 4,12,44,45,47,49,52,74,114,115,116,118, - 119,165,205,245,249,250,254 -*/ - -#include "mapinc.h" -#include "mmc3.h" - -MMC3 mmc3; - -static uint8 IRQCount, IRQLatch, IRQa; -static uint8 IRQReload; - -static SFORMAT MMC3_StateRegs[] = -{ - { mmc3.reg, 8, "REGS" }, - { &mmc3.cmd, 1, "CMD" }, - { &mmc3.mirr, 1, "A000" }, - { &mmc3.wram, 1, "A001" }, - { &IRQReload, 1, "IRQR" }, - { &IRQCount, 1, "IRQC" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQa, 1, "IRQA" }, - { 0 } -}; - -static void GENFIXPRG(void); -static void GENFIXCHR(void); - -static void GENPWRAP(uint16 A, uint16 V); -static void GENCWRAP(uint16 A, uint16 V); - -int isRevB = 1; - -void (*MMC3_FixPRG)(void); -void (*MMC3_FixCHR)(void); -void (*MMC3_FixMIR)(void); - -void (*MMC3_pwrap)(uint16 A, uint16 V); -void (*MMC3_cwrap)(uint16 A, uint16 V); - -static void GENCWRAP(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -static void GENPWRAP(uint16 A, uint16 V) { - setprg8(A, (V & 0x7F)); -} - -/* ---------------------------------------------------------------------- - * ------------------------- Generic MM3 Code --------------------------- - * ---------------------------------------------------------------------- - */ - -uint8 MMC3_GetPRGBank(int V) { - if ((~V & 0x01) && (mmc3.cmd & 0x40)) { - V ^= 0x02; - } - if (V & 0x02) { - return (0xFE | (V & 0x01)); - } - return mmc3.reg[6 | (V & 0x01)]; -} - -uint8 MMC3_GetCHRBank(int V) { - if (mmc3.cmd & 0x80) { - V ^= 0x04; - } - if (V & 0x04) { - return mmc3.reg[V - 2]; - } - return ((mmc3.reg[V >> 1] & ~0x01) | (V & 0x01)); -} - -int MMC3_WramIsWritable(void) { - return ((mmc3.wram & 0x80) && !(mmc3.wram & 0x40)) ? TRUE : FALSE; -} - -static void GENFIXPRG(void) { - MMC3_pwrap(0x8000, MMC3_GetPRGBank(0)); - MMC3_pwrap(0xA000, MMC3_GetPRGBank(1)); - MMC3_pwrap(0xC000, MMC3_GetPRGBank(2)); - MMC3_pwrap(0xE000, MMC3_GetPRGBank(3)); -} - -static void GENFIXCHR(void) { - MMC3_cwrap(0x0000, MMC3_GetCHRBank(0)); - MMC3_cwrap(0x0400, MMC3_GetCHRBank(1)); - MMC3_cwrap(0x0800, MMC3_GetCHRBank(2)); - MMC3_cwrap(0x0C00, MMC3_GetCHRBank(3)); - - MMC3_cwrap(0x1000, MMC3_GetCHRBank(4)); - MMC3_cwrap(0x1400, MMC3_GetCHRBank(5)); - MMC3_cwrap(0x1800, MMC3_GetCHRBank(6)); - MMC3_cwrap(0x1C00, MMC3_GetCHRBank(7)); -} - -static void GENFIXMIR(void) { - setmirror((mmc3.mirr & 0x01) ^ 0x01); -} - -void MMC3_Reset(void) { - IRQCount = IRQLatch = IRQa = mmc3.cmd = 0; - mmc3.mirr = mmc3.wram = 0; - - mmc3.reg[0] = 0; - mmc3.reg[1] = 2; - mmc3.reg[2] = 4; - mmc3.reg[3] = 5; - mmc3.reg[4] = 6; - mmc3.reg[5] = 7; - mmc3.reg[6] = 0; - mmc3.reg[7] = 1; - - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); -} - -DECLFW(MMC3_CMDWrite) { - uint8 oldcmd = mmc3.cmd; - /* FCEU_printf("bs %04x %02x\n",A,V); */ - switch (A & 0xE001) { - case 0x8000: - mmc3.cmd = V; - if ((oldcmd & 0x40) != (mmc3.cmd & 0x40)) { - MMC3_FixPRG(); - } - if ((oldcmd & 0x80) != (mmc3.cmd & 0x80)) { - MMC3_FixCHR(); - } - break; - case 0x8001: { - int cbase = (mmc3.cmd & 0x80) << 5; - mmc3.reg[mmc3.cmd & 0x7] = V; - switch (mmc3.cmd & 0x07) { - case 0: - MMC3_cwrap((cbase ^ 0x000), V & (~1)); - MMC3_cwrap((cbase ^ 0x400), V | 1); - break; - case 1: - MMC3_cwrap((cbase ^ 0x800), V & (~1)); - MMC3_cwrap((cbase ^ 0xC00), V | 1); - break; - case 2: - MMC3_cwrap(cbase ^ 0x1000, V); - break; - case 3: - MMC3_cwrap(cbase ^ 0x1400, V); - break; - case 4: - MMC3_cwrap(cbase ^ 0x1800, V); - break; - case 5: - MMC3_cwrap(cbase ^ 0x1C00, V); - break; - case 6: - if (mmc3.cmd & 0x40) { - MMC3_pwrap(0xC000, V); - } else { - MMC3_pwrap(0x8000, V); - } - break; - case 7: - MMC3_pwrap(0xA000, V); - break; - } - break; - } - case 0xA000: - mmc3.mirr = V; - MMC3_FixMIR(); - break; - case 0xA001: - mmc3.wram = V; - break; - } -} - -DECLFW(MMC3_IRQWrite) { - /* FCEU_printf("%04x:%04x\n",A,V); */ - switch (A & 0xE001) { - case 0xC000: - IRQLatch = V; - break; - case 0xC001: - IRQCount = 0; - IRQReload = 1; - break; - case 0xE000: - X6502_IRQEnd(FCEU_IQEXT); - IRQa = 0; - break; - case 0xE001: - IRQa = 1; - break; - } -} - -DECLFW(MMC3_Write) { - /* FCEU_printf("bs %04x %02x\n",A,V); */ - switch (A & 0xE000) { - case 0x8000: - case 0xA000: - MMC3_CMDWrite(A, V); - break; - case 0xC000: - case 0xE000: - MMC3_IRQWrite(A, V); - break; - } -} - -void MMC3_IRQHBHook(void) { - int count = IRQCount; - if (!count || IRQReload) { - IRQCount = IRQLatch; - IRQReload = 0; - } else { - IRQCount--; - } - if ((count | isRevB) && !IRQCount && IRQa) { - X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void MMC3_hb(void) { - MMC3_IRQHBHook(); -} - -static void MMC3_hb_KickMasterHack(void) { - if (scanline == 238) { - MMC3_IRQHBHook(); - } - MMC3_IRQHBHook(); -} - -static void MMC3_hb_PALStarWarsHack(void) { - if (scanline == 240) { - MMC3_IRQHBHook(); - } - MMC3_IRQHBHook(); -} - -static void StateRestore(int version) { - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); -} - -void MMC3_Power(void) { - if (!CHR_ROM_SIZE) { - setchr8(0); - } - - SetWriteHandler(0x8000, 0xBFFF, MMC3_CMDWrite); - SetWriteHandler(0xC000, 0xFFFF, MMC3_IRQWrite); - SetReadHandler(0x8000, 0xFFFF, CartBR); - - setmirror(1); - if (mmc3.opts & 1) { - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - SetWriteHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBW); - SetReadHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBR); - setprg8r(0x10, 0x6000, 0); - if (!(mmc3.opts & 2)) { - FCEU_MemoryRand(WRAM, WRAMSIZE); - } - } - MMC3_Reset(); -} - -void MMC3_Close(void) { -} - -void MMC3_Init(CartInfo *info, int wram, int battery) { - MMC3_FixPRG = GENFIXPRG; - MMC3_FixCHR = GENFIXCHR; - MMC3_FixMIR = GENFIXMIR; - - MMC3_pwrap = GENPWRAP; - MMC3_cwrap = GENCWRAP; - - WRAMSIZE = wram << 10; - - if (wram) { - mmc3.opts |= 1; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - - if (battery) { - mmc3.opts |= 2; - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - - AddExState(MMC3_StateRegs, ~0, 0, 0); - - info->Power = MMC3_Power; - info->Reset = MMC3_Reset; - info->Close = MMC3_Close; - - if (info->CRC32 == 0x5104833e) { /* Kick Master */ - GameHBIRQHook = MMC3_hb_KickMasterHack; - } else if (info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20) { /* Shougi Meikan '92/'93 */ - GameHBIRQHook = MMC3_hb_KickMasterHack; - } else if (info->CRC32 == 0xfcd772eb) { /* PAL Star Wars, similar problem as Kick Master. */ - GameHBIRQHook = MMC3_hb_PALStarWarsHack; - } else { - GameHBIRQHook = MMC3_hb; - } - GameStateRestore = StateRestore; -} diff --git a/src/mappers/hw/mmc3.h b/src/mappers/hw/mmc3.h deleted file mode 100644 index ae113b4b8..000000000 --- a/src/mappers/hw/mmc3.h +++ /dev/null @@ -1,56 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _MMC3_H -#define _MMC3_H - -typedef struct __MMC3 { - uint8 cmd; - uint8 opts; - uint8 mirr; - uint8 wram; - uint8 reg[8]; -} MMC3; - -extern MMC3 mmc3; -extern int isRevB; - -uint8 MMC3_GetPRGBank(int V); -uint8 MMC3_GetCHRBank(int V); - -DECLFW(MMC3_CMDWrite); /* $ 0x8000 - 0xBFFF */ -DECLFW(MMC3_IRQWrite); /* $ 0xC000 - 0xFFFF */ -DECLFW(MMC3_Write); /* $ 0x8000 - 0xFFFF */ - -void MMC3_Power(void); -void MMC3_Reset(void); -void MMC3_Close(void); -void MMC3_IRQHBHook(void); -int MMC3_WramIsWritable(void); -void MMC3_Init(CartInfo *info, int wram, int battery); - -extern void (*MMC3_FixPRG)(void); -extern void (*MMC3_FixCHR)(void); -extern void (*MMC3_FixMIR)(void); - -extern void (*MMC3_pwrap)(uint16 A, uint16 V); -extern void (*MMC3_cwrap)(uint16 A, uint16 V); - -#endif /* _MMC3_H */ diff --git a/src/mappers/hw/mmc4.c b/src/mappers/hw/mmc4.c deleted file mode 100644 index 86615dee3..000000000 --- a/src/mappers/hw/mmc4.c +++ /dev/null @@ -1,148 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "mmc4.h" - -void (*MMC4_pwrap)(uint16 A, uint16 V); -void (*MMC4_cwrap)(uint16 A, uint16 V); -void (*MMC4_mwrap)(uint8 V); - -MMC4 mmc4; - -static SFORMAT StateRegs[] = -{ - { mmc4.chr, 4, "CREG" }, - { mmc4.latch, 2, "PPUL" }, - { &mmc4.prg, 1, "PREG" }, - { &mmc4.mirr, 1, "MIRR" }, - { 0 } -}; - -static void GENPWRAP(uint16 A, uint16 V) { - setprg16(A, V); -} - -static void GENCWRAP(uint16 A, uint16 V) { - setchr4(A, V); -} - -static void GENMWRAP(uint8 V) { - mmc4.mirr = V; - setmirror((mmc4.mirr & 1) ^ 1); -} - -void MMC4_FixPRG(void) { - MMC4_pwrap(0x8000, mmc4.prg); - MMC4_pwrap(0xC000, ~0); -} - -void MMC4_FixCHR(void) { - MMC4_cwrap(0x0000, mmc4.chr[mmc4.latch[0] | 0]); - MMC4_cwrap(0x1000, mmc4.chr[mmc4.latch[1] | 2]); - - if (MMC4_mwrap) { - MMC4_mwrap(mmc4.mirr); - } -} - -DECLFW(MMC4_Write) { - switch (A & 0xF000) { - case 0xA000: - mmc4.prg = V; - MMC4_FixPRG(); - break; - case 0xB000: - case 0xC000: - case 0xD000: - case 0xE000: - mmc4.chr[(A - 0xB000) >> 12] = V; - MMC4_FixCHR(); - break; - case 0xF000: - if (MMC4_mwrap) { - MMC4_mwrap(V); - } - break; - } -} - -static void MMC4PPUHook(uint32 A) { - uint8 bank = (A >> 12) & 0x01; - if ((A & 0x2000) || (((A & 0xFF0) != 0xFD0) && ((A & 0xFF0) != 0xFE0))) { - return; - } - mmc4.latch[bank] = (A >> 5) & 0x01; - MMC4_FixCHR(); -} - -void MMC4_Reset(void) { - mmc4.prg = mmc4.mirr = 0; - mmc4.latch[0] = mmc4.latch[1] = 0; - MMC4_FixPRG(); - MMC4_FixCHR(); -} - -void MMC4_Power(void) { - MMC4_Reset(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0xA000, 0xFFFF, MMC4_Write); - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } -} - -void MMC4_Restore(int version) { - MMC4_FixPRG(); - MMC4_FixCHR(); -} - -void MMC4_Close(void) { -} - -void MMC4_Init(CartInfo *info, int wram, int battery) { - MMC4_pwrap = GENPWRAP; - MMC4_cwrap = GENCWRAP; - MMC4_mwrap = GENMWRAP; - - info->Power = MMC4_Power; - info->Close = MMC4_Close; - PPU_hook = MMC4PPUHook; - - GameStateRestore = MMC4_Restore; - AddExState(StateRegs, ~0, 0, NULL); - - if (wram) { - WRAMSIZE = wram * 1024; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } -} diff --git a/src/mappers/hw/mmc4.h b/src/mappers/hw/mmc4.h deleted file mode 100644 index 6b72ecb8b..000000000 --- a/src/mappers/hw/mmc4.h +++ /dev/null @@ -1,48 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _MMC4_H -#define _MMC4_H - -typedef struct __MMC4 { - uint8 prg; - uint8 chr[4]; - uint8 latch[2]; - uint8 mirr; -} MMC4; - -extern MMC4 mmc4; - -DECLFW(MMC4_Write); - -void MMC4_Power(void); -void MMC4_Close(void); -void MMC4_Reset(void); -void MMC4_Restore(int version); -void MMC4_Init(CartInfo *info, int wram, int battery); - -void MMC4_FixPRG(void); -void MMC4_FixCHR(void); - -extern void (*MMC4_pwrap)(uint16 A, uint16 V); -extern void (*MMC4_cwrap)(uint16 A, uint16 V); -extern void (*MMC4_mwrap)(uint8 V); - -#endif /* _MMC4_H */ diff --git a/src/mappers/hw/mmc6.c b/src/mappers/hw/mmc6.c deleted file mode 100644 index 7382b56e9..000000000 --- a/src/mappers/hw/mmc6.c +++ /dev/null @@ -1,285 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc6.h" - -typedef struct __MMC6 { - uint8 cmd; - uint8 opts; - uint8 mirr; - uint8 wram; - uint8 reg[8]; -} MMC6; - -static MMC6 mmc6; - -static uint8 IRQCount, IRQLatch, IRQa; -static uint8 IRQReload; - -static SFORMAT MMC6_StateRegs[] = -{ - { mmc6.reg, 8, "REGS" }, - { &mmc6.cmd, 1, "CMD" }, - { &mmc6.mirr, 1, "A000" }, - { &mmc6.wram, 1, "A001" }, - { &IRQReload, 1, "IRQR" }, - { &IRQCount, 1, "IRQC" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQa, 1, "IRQA" }, - { 0 } -}; - -static void MMC6_FixPRG(void) { - if (!(mmc6.cmd & 0x40)) { - setprg8(0x8000, mmc6.reg[6]); - setprg8(0xA000, mmc6.reg[7]); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); - } else { - setprg8(0x8000, ~1); - setprg8(0xA000, mmc6.reg[7]); - setprg8(0xC000, mmc6.reg[6]); - setprg8(0xE000, ~0); - } -} - -static void MMC6_FixCHR(void) { - if (!(mmc6.cmd & 0x80)) { - setchr1(0x0000, mmc6.reg[0] & 0xFE); - setchr1(0x0400, mmc6.reg[0] | 0x01); - setchr1(0x0800, mmc6.reg[1] & 0xFE); - setchr1(0x0C00, mmc6.reg[1] | 0x01); - - setchr1(0x1000, mmc6.reg[2]); - setchr1(0x1400, mmc6.reg[3]); - setchr1(0x1800, mmc6.reg[4]); - setchr1(0x1C00, mmc6.reg[5]); - } else { - setchr1(0x0000, mmc6.reg[2]); - setchr1(0x0400, mmc6.reg[3]); - setchr1(0x0800, mmc6.reg[4]); - setchr1(0x0C00, mmc6.reg[5]); - - setchr1(0x1000, mmc6.reg[0] & 0xFE); - setchr1(0x1400, mmc6.reg[0] | 0x01); - setchr1(0x1800, mmc6.reg[1] & 0xFE); - setchr1(0x1C00, mmc6.reg[1] | 0x01); - } -} - -static void MMC6_FixMIR(void) { - setmirror((mmc6.mirr & 0x01) ^ 0x01); -} - -static void MMC6_Reset(void) { - IRQCount = IRQLatch = IRQa = mmc6.cmd = 0; - mmc6.mirr = mmc6.wram = 0; - - mmc6.reg[0] = 0; - mmc6.reg[1] = 2; - mmc6.reg[2] = 4; - mmc6.reg[3] = 5; - mmc6.reg[4] = 6; - mmc6.reg[5] = 7; - mmc6.reg[6] = 0; - mmc6.reg[7] = 1; - - MMC6_FixPRG(); - MMC6_FixCHR(); - MMC6_FixMIR(); -} - - -static DECLFW(MBWRAMMMC6) { - if (!(mmc6.cmd & 0x20)) { - /* wram disabled */ - return; - } - - A &= 0x3FF; - if (!(A & 0x200)) { - /* 1st bank writes are disabled */ - if ((mmc6.wram & 0x30) == 0x30) WRAM[A] = V; - } else { - /* 2nd bank writes are disabled */ - if ((mmc6.wram & 0xC0) == 0xC0) WRAM[A] = V; - } -} - -static DECLFR(MAWRAMMMC6) { - if (!(mmc6.cmd & 0x20)) { - /* wram disabled */ - return CPU_OPENBUS; - } - - A &= 0x3FF; - if (!(A & 0x200)) { - /* 1st bank */ - if (mmc6.wram & 0x20) return WRAM[A]; - if (mmc6.wram & 0x80) return 0x00; - } else { - /* 2nd bank */ - if (mmc6.wram & 0x80) return WRAM[A]; - if (mmc6.wram & 0x20) return 0x00; - } - return CPU_OPENBUS; -} - -static DECLFW(MMC6_CMDWrite) { - uint8 oldcmd = mmc6.cmd; - /* FCEU_printf("bs %04x %02x\n",A,V); */ - switch (A & 0xE001) { - case 0x8000: - mmc6.cmd = V; - if ((oldcmd & 0x40) != (mmc6.cmd & 0x40)) - MMC6_FixPRG(); - if ((oldcmd & 0x80) != (mmc6.cmd & 0x80)) - MMC6_FixCHR(); - break; - case 0x8001: { - int cbase = (mmc6.cmd & 0x80) << 5; - mmc6.reg[mmc6.cmd & 0x7] = V; - switch (mmc6.cmd & 0x07) { - case 0: - setchr1((cbase ^ 0x000), V & (~1)); - setchr1((cbase ^ 0x400), V | 1); - break; - case 1: - setchr1((cbase ^ 0x800), V & (~1)); - setchr1((cbase ^ 0xC00), V | 1); - break; - case 2: - setchr1(cbase ^ 0x1000, V); - break; - case 3: - setchr1(cbase ^ 0x1400, V); - break; - case 4: - setchr1(cbase ^ 0x1800, V); - break; - case 5: - setchr1(cbase ^ 0x1C00, V); - break; - case 6: - if (mmc6.cmd & 0x40) - setprg8(0xC000, V); - else - setprg8(0x8000, V); - break; - case 7: - setprg8(0xA000, V); - break; - } - break; - } - case 0xA000: - mmc6.mirr = V; - MMC6_FixMIR(); - break; - case 0xA001: - mmc6.wram = V; - break; - } -} - -static DECLFW(MMC6_IRQWrite) { - /* FCEU_printf("%04x:%04x\n",A,V); */ - switch (A & 0xE001) { - case 0xC000: - IRQLatch = V; - break; - case 0xC001: - IRQReload = 1; - break; - case 0xE000: - X6502_IRQEnd(FCEU_IQEXT); - IRQa = 0; - break; - case 0xE001: - IRQa = 1; - break; - } -} - -static void MMC6_IRQHBHook(void) { - int count = IRQCount; - - if (!count || IRQReload) { - IRQCount = IRQLatch; - IRQReload = 0; - } else - IRQCount--; - if (!IRQCount && IRQa) { - X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void StateRestore(int version) { - MMC6_FixPRG(); - MMC6_FixCHR(); - MMC6_FixMIR(); -} - -static void MMC6_Power(void) { - if (!CHR_ROM_SIZE) { - setchr8(0); - } - - SetWriteHandler(0x8000, 0xBFFF, MMC6_CMDWrite); - SetWriteHandler(0xC000, 0xFFFF, MMC6_IRQWrite); - SetReadHandler(0x8000, 0xFFFF, CartBR); - - setmirror(1); - - FCEU_CheatAddRAM(1, 0x7000, WRAM); - SetReadHandler(0x7000, 0x7FFF, MAWRAMMMC6); - SetWriteHandler(0x7000, 0x7FFF, MBWRAMMMC6); - if (!(mmc6.opts & 2)) { - FCEU_MemoryRand(WRAM, WRAMSIZE); - } - - MMC6_Reset(); -} - -static void MMC6_Close(void) { -} - -void MMC6_Init(CartInfo *info) { - WRAMSIZE = 1024; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - if (info->battery) { - mmc6.opts |= 2; - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - - AddExState(MMC6_StateRegs, ~0, 0, 0); - - info->Power = MMC6_Power; - info->Reset = MMC6_Reset; - info->Close = MMC6_Close; - - GameHBIRQHook = MMC6_IRQHBHook; - GameStateRestore = StateRestore; -} diff --git a/src/mappers/hw/mmc6.h b/src/mappers/hw/mmc6.h deleted file mode 100644 index adf0cd54f..000000000 --- a/src/mappers/hw/mmc6.h +++ /dev/null @@ -1,26 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _MMC6_H -#define _MMC6_H - -void MMC6_Init(CartInfo *info); - -#endif /* _MMC6_H */ diff --git a/src/mappers/hw/n118.c b/src/mappers/hw/n118.c deleted file mode 100644 index 6e63ef294..000000000 --- a/src/mappers/hw/n118.c +++ /dev/null @@ -1,127 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "n118.h" - -void (*N118_FixPRG)(void); -void (*N118_FixCHR)(void); - -void (*N118_pwrap)(uint16 A, uint16 V); -void (*N118_cwrap)(uint16 A, uint16 V); - -N118 n118; - -static SFORMAT StateRegs[] = { - { n118.reg, 8, "REGS" }, - { &n118.cmd, 1, "CMD0" }, - { 0 } -}; - -static void GENCWRAP(uint16 A, uint16 V) { - setchr1(A, V & 0x3F); -} - -static void GENPWRAP(uint16 A, uint16 V) { - setprg8(A, V & 0x0F); -} - -static void GENFIXCHR(void) { - N118_cwrap(0x0000, n118.reg[0] & (~1)); - N118_cwrap(0x0400, n118.reg[0] | 1); - N118_cwrap(0x0800, n118.reg[1] & (~1)); - N118_cwrap(0x0C00, n118.reg[1] | 1); - N118_cwrap(0x1000, n118.reg[2]); - N118_cwrap(0x1400, n118.reg[3]); - N118_cwrap(0x1800, n118.reg[4]); - N118_cwrap(0x1C00, n118.reg[5]); -} - -static void GENFIXPRG(void) { - N118_pwrap(0x8000, n118.reg[6]); - N118_pwrap(0xA000, n118.reg[7]); - N118_pwrap(0xC000, ~1); - N118_pwrap(0xE000, ~0); -} - -DECLFW(N118_Write) { - if (A & 0x01) { - n118.reg[n118.cmd & 0x07] = V; - } else { - n118.cmd = V; - } - N118_FixPRG(); - N118_FixCHR(); -} - -void N118_Power(void) { - n118.reg[0] = 0; - n118.reg[1] = 2; - n118.reg[2] = 4; - n118.reg[3] = 5; - n118.reg[4] = 6; - n118.reg[5] = 7; - n118.reg[6] = 0; - n118.reg[7] = 1; - n118.cmd = 0; - - N118_FixPRG(); - N118_FixCHR(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0x9FFF, N118_Write); - - if (WRAM) { - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } -} - -static void StateRestore(int version) { - N118_FixPRG(); - N118_FixCHR(); -} - -void N118_Init(CartInfo *info, int wsize, int battery) { - N118_FixPRG = GENFIXPRG; - N118_FixCHR = GENFIXCHR; - - N118_pwrap = GENPWRAP; - N118_cwrap = GENCWRAP; - - WRAMSIZE = wsize * 1024; - - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - if (battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } - - info->Power = N118_Power; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/hw/n118.h b/src/mappers/hw/n118.h deleted file mode 100644 index 0bfb456bc..000000000 --- a/src/mappers/hw/n118.h +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _N118_H -#define _N118_H - -typedef struct __N118 { - uint8 reg[8]; - uint8 cmd; -} N118; - -extern N118 n118; - -DECLFW(N118_Write); - -void N118_Close(void); -void N118_Power(void); - -void N118_Init(CartInfo *info, int wsize, int battery); - -extern void (*N118_FixPRG)(void); -extern void (*N118_FixCHR)(void); - -extern void (*N118_pwrap)(uint16 A, uint16 V); -extern void (*N118_cwrap)(uint16 A, uint16 V); - -#endif /* _N118_H */ diff --git a/src/mappers/hw/pic16c5x.c b/src/mappers/hw/pic16c5x.c deleted file mode 100644 index c5a79e6be..000000000 --- a/src/mappers/hw/pic16c5x.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* license:BSD-3-Clause - copyright-holders:Tony La Porta */ - /**************************************************************************\ - * Microchip PIC16C5x Emulator * - * * - * Copyright Tony La Porta * - * Originally written for the MAME project. * - * * - * * - * Addressing architecture is based on the Harvard addressing scheme. * - * * - * * - * **** Change Log **** * - * TLP (06-Apr-2003) * - * - First Public release. * - * BO (07-Apr-2003) Ver 1.01 * - * - Renamed 'sleep' function to 'sleepic' to avoid C conflicts. * - * TLP (09-Apr-2003) Ver 1.10 * - * - Fixed modification of file register $03 (Status). * - * - Corrected support for 7FFh (12-bit) size ROMs. * - * - The 'call' and 'goto' instructions weren't correctly handling the * - * STATUS page info correctly. * - * - The FSR register was incorrectly oring the data with 0xe0 when read. * - * - Prescaler masking information was set to 3 instead of 7. * - * - Prescaler assign bit was set to 4 instead of 8. * - * - Timer source and edge select flags/masks were wrong. * - * - Corrected the memory bank selection in GET/SET_REGFILE and also the * - * indirect register addressing. * - * BMP (18-May-2003) Ver 1.11 * - * - PIC16C5x_get_reg functions were missing 'returns'. * - * TLP (27-May-2003) Ver 1.12 * - * - Fixed the WatchDog timer count. * - * - The Prescaler rate was incorrectly being zeroed, instead of the * - * actual Prescaler counter in the CLRWDT and SLEEP instructions. * - * - Added masking to the FSR register. Upper unused bits are always 1. * - * TLP (27-Aug-2009) Ver 1.13 * - * - Indirect addressing was not taking into account special purpose * - * memory mapped locations. * - * - 'iorlw' instruction was saving the result to memory instead of * - * the W register. * - * - 'tris' instruction no longer modifies Port-C on PIC models that * - * do not have Port-C implemented. * - * TLP (07-Sep-2009) Ver 1.14 * - * - Edge sense control for the T0 count input was incorrectly reversed * - * LE (05-Feb-2017) Ver 1.15 * - * - Allow writing all bits of the status register except TO and PD. * - * This enables e.g. bcf, bsf or clrf to change the flags when the * - * status register is the destination. * - * - Changed rlf and rrf to update the carry flag in the last step. * - * Fixes the case where the status register is the destination. * - * hap (12-Feb-2017) Ver 1.16 * - * - Added basic support for the old GI PIC1650 and PIC1655. * - * - Made RTCC(aka T0CKI) pin an inputline handler. * - * * - * * - * **** Notes: **** * - * PIC WatchDog Timer has a separate internal clock. For the moment, we're * - * basing the count on a 4MHz input clock, since 4MHz is the typical * - * input frequency (but by no means always). * - * A single scaler is available for the Counter/Timer or WatchDog Timer. * - * When connected to the Counter/Timer, it functions as a Prescaler, * - * hence prescale overflows, tick the Counter/Timer. * - * When connected to the WatchDog Timer, it functions as a Postscaler * - * hence WatchDog Timer overflows, tick the Postscaler. This scenario * - * means that the WatchDog timeout occurs when the Postscaler has * - * reached the scaler rate value, not when the WatchDog reaches zero. * - * CLRWDT should prevent the WatchDog Timer from timing out and generating * - * a device reset, but how is not known. The manual also mentions that * - * the WatchDog Timer can only be disabled during ROM programming, and * - * no other means seem to exist??? * - * * - \**************************************************************************/ - -#include -#include "pic16c5x.h" - -/******************** CPU Internal Registers *******************/ -static uint16 m_PC; -static uint16 m_PREVPC; /* previous program counter */ -static uint8 m_W; -static uint8 m_OPTION; -static uint16 m_CONFIG; -static uint8 m_ALU; -static uint16 m_WDT; -static uint8 m_TRISA; -static uint8 m_TRISB; -static uint8 m_TRISC; -static uint16 m_STACK[2]; -static uint16 m_prescaler; /* Note: this is really an 8-bit register */ -static uint16 m_opcode; -static uint8 m_internalram[128]; -static uint8 *m_rom; - -static int m_icount; -static int m_picmodel; -static int m_delay_timer; -static uint16 m_temp_config; -static int m_rtcc; -static uint8 m_count_pending; /* boolean type */ -static int8 m_old_data; -static uint8 m_picRAMmask; -static uint16 m_picROMmask; -static int m_inst_cycles; -static int m_clock2cycle; - -/*address_space *m_program; -memory_access_cache<1, -1, ENDIANNESS_LITTLE> *m_cache; -address_space *m_data;*/ - -/* i/o handlers */ -static pic16c5x_readfunc m_read; -static pic16c5x_writefunc m_write; - -static void PIC16C5x(int program_width, int data_width, int picmodel, uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) -{ - m_rom = rom; - m_picmodel = picmodel; - m_temp_config = 0; - m_picRAMmask = ((1 << data_width) - 1); - m_picROMmask = ((1 << program_width) - 1); - m_read = _rd; - m_write = _wr; - m_PC = 0; - m_PREVPC = 0; - m_W = 0; - m_OPTION = 0; - m_CONFIG = 0; - m_ALU = 0; - m_WDT = 0; - m_TRISA = 0; - m_TRISB = 0; - m_TRISC = 0; - m_prescaler = 0; - m_icount = 0; - m_delay_timer = 0; - m_rtcc = 0; - m_count_pending = 0; - m_old_data = 0; - m_inst_cycles = 0; - m_clock2cycle = 0; -} - -void pic16c54_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x( 9, 5, 0x16C54, rom, _rd, _wr); } -void pic16c55_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x( 9, 5, 0x16C55, rom, _rd, _wr); } -void pic16c56_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x(10, 5, 0x16C56, rom, _rd, _wr); } -void pic16c57_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x(11, 7, 0x16C57, rom, _rd, _wr); } -void pic16c58_init(uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x(11, 7, 0x16C58, rom, _rd, _wr); } -void pic1650_init (uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x( 9, 5, 0x1650, rom, _rd, _wr); } -void pic1655_init (uint8 *rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr) { PIC16C5x( 9, 5, 0x1655, rom, _rd, _wr); } - -#define M_OPCODE_B0 (m_opcode & 0xFF) -#define M_OPCODE_B1 ((m_opcode >> 8) & 0xFF) -#define M_OPCODE_S0 m_opcode - -#define M_RDRAM(A) m_internalram[A &m_picRAMmask] -#define M_WRTRAM(A,V) m_internalram[A &m_picRAMmask] =(V) -#define M_RDOP(A) m_rom[(A &m_picROMmask) <<1 |0] | m_rom[(A &m_picROMmask) <<1 |1] <<8 -#define ADDR_MASK 0x7ff - -#define TMR0 m_internalram[1] -#define PCL m_internalram[2] -#define STATUS m_internalram[3] -#define FSR m_internalram[4] -#define PORTA m_internalram[5] -#define PORTB m_internalram[6] -#define PORTC m_internalram[7] -#define PORTD m_internalram[8] -#define INDF M_RDRAM(FSR) - -#define ADDR (M_OPCODE_B0 & 0x1f) - - -/******** The following is the Status Flag register definition. *********/ - /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */ - /* | PA | TO | PD | Z | DC | C | */ -#define PA_REG 0xe0 /* PA Program Page Preselect - bit 8 is unused here */ -#define TO_FLAG 0x10 /* TO Time Out flag (WatchDog) */ -#define PD_FLAG 0x08 /* PD Power Down flag */ -#define Z_FLAG 0x04 /* Z Zero Flag */ -#define DC_FLAG 0x02 /* DC Digit Carry/Borrow flag (Nibble) */ -#define C_FLAG 0x01 /* C Carry/Borrow Flag (Byte) */ - -#define PA (STATUS & PA_REG) -#define TO (STATUS & TO_FLAG) -#define PD (STATUS & PD_FLAG) -#define ZERO (STATUS & Z_FLAG) -#define DC (STATUS & DC_FLAG) -#define CARRY (STATUS & C_FLAG) - - -/******** The following is the Option Flag register definition. *********/ - /* | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */ - /* | 0 | 0 | TOCS | TOSE | PSA | PS | */ -#define T0CS_FLAG 0x20 /* TOCS Timer 0 clock source select */ -#define T0SE_FLAG 0x10 /* TOSE Timer 0 clock source edge select */ -#define PSA_FLAG 0x08 /* PSA Prescaler Assignment bit */ -#define PS_REG 0x07 /* PS Prescaler Rate select */ - -#define T0CS (m_OPTION & T0CS_FLAG) -#define T0SE (m_OPTION & T0SE_FLAG) -#define PSA (m_OPTION & PSA_FLAG) -#define PS (m_OPTION & PS_REG) - - -/******** The following is the Config Flag register definition. *********/ - /* | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | */ - /* | CP | WDTE | FOSC | */ - /* CP Code Protect (ROM read protect) */ -#define WDTE_FLAG 0x04 /* WDTE WatchDog Timer enable */ -#define FOSC_FLAG 0x03 /* FOSC Oscillator source select */ - -#define WDTE (m_CONFIG & WDTE_FLAG) -#define FOSC (m_CONFIG & FOSC_FLAG) - - -/************************************************************************ - * Shortcuts - ************************************************************************/ - -#define CLR(flagreg, flag) ( flagreg &= (uint8)(~flag) ) -#define SET(flagreg, flag) ( flagreg |= flag ) - - -/* Easy bit position selectors */ -#define POS ((M_OPCODE_B0 >> 5) & 7) -static const unsigned int bit_clr[8] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f }; -static const unsigned int bit_set[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; - -static INLINE void CALCULATE_Z_FLAG(void) -{ - if (m_ALU == 0) SET(STATUS, Z_FLAG); - else CLR(STATUS, Z_FLAG); -} - -static INLINE void CALCULATE_ADD_CARRY(void) -{ - if ((uint8)(m_old_data) > (uint8)(m_ALU)) { - SET(STATUS, C_FLAG); - } - else { - CLR(STATUS, C_FLAG); - } -} - -static INLINE void CALCULATE_ADD_DIGITCARRY(void) -{ - if (((uint8)(m_old_data) & 0x0f) > ((uint8)(m_ALU) & 0x0f)) { - SET(STATUS, DC_FLAG); - } - else { - CLR(STATUS, DC_FLAG); - } -} - -static INLINE void CALCULATE_SUB_CARRY(void) -{ - if ((uint8)(m_old_data) < (uint8)(m_ALU)) { - CLR(STATUS, C_FLAG); - } - else { - SET(STATUS, C_FLAG); - } -} - -static INLINE void CALCULATE_SUB_DIGITCARRY(void) -{ - if (((uint8)(m_old_data) & 0x0f) < ((uint8)(m_ALU) & 0x0f)) { - CLR(STATUS, DC_FLAG); - } - else { - SET(STATUS, DC_FLAG); - } -} - - - -static INLINE uint16 POP_STACK(void) -{ - uint16 data = m_STACK[1]; - m_STACK[1] = m_STACK[0]; - return (data & ADDR_MASK); -} -static INLINE void PUSH_STACK(uint16 data) -{ - m_STACK[0] = m_STACK[1]; - m_STACK[1] = (data & ADDR_MASK); -} - - - -static INLINE uint8 GET_REGFILE(uint32_t addr) /* Read from internal memory */ -{ - uint8 data = 0; - - if (addr == 0) { /* Indirect addressing */ - addr = (FSR & m_picRAMmask); - } - - if ((m_picmodel == 0x16C57) || (m_picmodel == 0x16C58)) { - addr |= (FSR & 0x60); /* FSR bits 6-5 are used for banking in direct mode */ - } - - if ((addr & 0x10) == 0) addr &= 0x0f; - - switch(addr) - { - case 0: /* Not an actual register, so return 0 */ - data = 0; - break; - case 4: data = (FSR | (uint8)(~m_picRAMmask)); - break; - case 5: /* read port A */ - if (m_picmodel == 0x1650) { - data = m_read(PIC16C5x_PORTA) & PORTA; - } - else if (m_picmodel == 0x1655) { - data = m_read(PIC16C5x_PORTA) & 0x0f; - } - else { - data = m_read(PIC16C5x_PORTA); - data &= m_TRISA; - data |= ((uint8)(~m_TRISA) & PORTA); - data &= 0x0f; /* 4-bit port (only lower 4 bits used) */ - } - break; - case 6: /* read port B */ - if (m_picmodel == 0x1650) { - data = m_read(PIC16C5x_PORTB) & PORTB; - } - else if (m_picmodel != 0x1655) { /* B is output-only on 1655 */ - data = m_read(PIC16C5x_PORTB); - data &= m_TRISB; - data |= ((uint8)(~m_TRISB) & PORTB); - } - break; - case 7: /* read port C */ - if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { - data = m_read(PIC16C5x_PORTC) & PORTC; - } - else if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { - data = m_read(PIC16C5x_PORTC); - data &= m_TRISC; - data |= ((uint8)(~m_TRISC) & PORTC); - } - else { /* PIC16C54, PIC16C56, PIC16C58 */ - data = M_RDRAM(addr); - } - break; - case 8: /* read port D */ - if (m_picmodel == 0x1650) { - data = m_read(PIC16C5x_PORTD) & PORTD; - } - else { - data = M_RDRAM(addr); - } - break; - default: data = M_RDRAM(addr); - break; - } - return data; -} - -static INLINE void STORE_REGFILE(uint32_t addr, uint8 data) /* Write to internal memory */ -{ - if (addr == 0) { /* Indirect addressing */ - addr = (FSR & m_picRAMmask); - } - - if ((m_picmodel == 0x16C57) || (m_picmodel == 0x16C58)) { - addr |= (FSR & 0x60); /* FSR bits 6-5 are used for banking in direct mode */ - } - - if ((addr & 0x10) == 0) addr &= 0x0f; - - switch(addr) - { - case 0: /* Not an actual register, nothing to save */ - break; - case 1: m_delay_timer = 2; /* Timer starts after next two instructions */ - if (PSA == 0) m_prescaler = 0; /* Must clear the Prescaler */ - TMR0 = data; - break; - case 2: PCL = data; - m_PC = ((STATUS & PA_REG) << 4) | data; - break; - case 3: STATUS = (STATUS & (TO_FLAG | PD_FLAG)) | (data & (uint8)(~(TO_FLAG | PD_FLAG))); - break; - case 4: FSR = (data | (uint8)(~m_picRAMmask)); - break; - case 5: /* write port A */ - if (m_picmodel == 0x1650) { - m_write(PIC16C5x_PORTA, data); - } - else if (m_picmodel != 0x1655) { /* A is input-only on 1655 */ - data &= 0x0f; /* 4-bit port (only lower 4 bits used) */ - m_write(PIC16C5x_PORTA, data & (uint8)(~m_TRISA)); - } - PORTA = data; - break; - case 6: /* write port B */ - if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { - m_write(PIC16C5x_PORTB, data); - } - else { - m_write(PIC16C5x_PORTB, data & (uint8)(~m_TRISB)); - } - PORTB = data; - break; - case 7: /* write port C */ - if (m_picmodel == 0x1650 || m_picmodel == 0x1655) { - m_write(PIC16C5x_PORTC, data); - } - else if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { - m_write(PIC16C5x_PORTC, data & (uint8)(~m_TRISC)); - } - PORTC = data; /* also writes to RAM */ - break; - case 8: /* write port D */ - if (m_picmodel == 0x1650) { - m_write(PIC16C5x_PORTD, data); - } - PORTD = data; /* also writes to RAM */ - break; - default: M_WRTRAM(addr, data); - break; - } -} - - -static INLINE void STORE_RESULT(uint32_t addr, uint8 data) -{ - if (M_OPCODE_B0 & 0x20) - { - STORE_REGFILE(addr, data); - } - else - { - m_W = data; - } -} - - -/************************************************************************ - * Emulate the Instructions - ************************************************************************/ - -/* This following function is here to fill in the void for */ -/* the opcode call function. This function is never called. */ - - -static INLINE void illegal(void) -{ - /* printf("PIC16C5x: PC=%03x, Illegal opcode = %04x\n", (m_PC-1), M_OPCODE_S0); */ -} - -/* - Note: - According to the manual, if the STATUS register is the destination for an instruction that affects the Z, DC or C bits - then the write to these three bits is disabled. These bits are set or cleared according to the device logic. - To ensure this is correctly emulated, in instructions that write to the file registers, always change the status flags - *after* storing the result of the instruction. - e.g. CALCULATE_*, SET(STATUS,*_FLAG) and CLR(STATUS,*_FLAG) should appear as the last steps of the instruction emulation. -*/ - -static INLINE void addwf(void) -{ - m_old_data = GET_REGFILE(ADDR); - m_ALU = m_old_data + m_W; - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); - CALCULATE_ADD_CARRY(); - CALCULATE_ADD_DIGITCARRY(); -} - -static INLINE void andwf(void) -{ - m_ALU = GET_REGFILE(ADDR) & m_W; - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); -} - -static INLINE void andlw(void) -{ - m_ALU = M_OPCODE_B0 & m_W; - m_W = m_ALU; - CALCULATE_Z_FLAG(); -} - -static INLINE void bcf(void) -{ - m_ALU = GET_REGFILE(ADDR); - m_ALU &= bit_clr[POS]; - STORE_REGFILE(ADDR, m_ALU); -} - -static INLINE void bsf(void) -{ - m_ALU = GET_REGFILE(ADDR); - m_ALU |= bit_set[POS]; - STORE_REGFILE(ADDR, m_ALU); -} - -static INLINE void btfss(void) -{ - if ((GET_REGFILE(ADDR) & bit_set[POS]) == bit_set[POS]) - { - m_PC++; - PCL = m_PC & 0xff; - m_inst_cycles += 1; /* Add NOP cycles */ - } -} - -static INLINE void btfsc(void) -{ - if ((GET_REGFILE(ADDR) & bit_set[POS]) == 0) - { - m_PC++; - PCL = m_PC & 0xff; - m_inst_cycles += 1; /* Add NOP cycles */ - } -} - -static INLINE void call(void) -{ - PUSH_STACK(m_PC); - m_PC = ((STATUS & PA_REG) << 4) | M_OPCODE_B0; - m_PC &= 0x6ff; - PCL = m_PC & 0xff; -} - -static INLINE void clrw(void) -{ - m_W = 0; - SET(STATUS, Z_FLAG); -} - -static INLINE void clrf(void) -{ - STORE_REGFILE(ADDR, 0); - SET(STATUS, Z_FLAG); -} - -static INLINE void clrwdt(void) -{ - m_WDT = 0; - if (PSA) m_prescaler = 0; - SET(STATUS, TO_FLAG); - SET(STATUS, PD_FLAG); -} - -static INLINE void comf(void) -{ - m_ALU = (uint8)(~(GET_REGFILE(ADDR))); - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); -} - -static INLINE void decf(void) -{ - m_ALU = GET_REGFILE(ADDR) - 1; - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); -} - -static INLINE void decfsz(void) -{ - m_ALU = GET_REGFILE(ADDR) - 1; - STORE_RESULT(ADDR, m_ALU); - if (m_ALU == 0) - { - m_PC++; - PCL = m_PC & 0xff; - m_inst_cycles += 1; /* Add NOP cycles */ - } -} - -static INLINE void goto_op(void) -{ - m_PC = ((STATUS & PA_REG) << 4) | (M_OPCODE_S0 & 0x1ff); - m_PC &= ADDR_MASK; - PCL = m_PC & 0xff; -} - -static INLINE void incf(void) -{ - m_ALU = GET_REGFILE(ADDR) + 1; - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); -} - -static INLINE void incfsz(void) -{ - m_ALU = GET_REGFILE(ADDR) + 1; - STORE_RESULT(ADDR, m_ALU); - if (m_ALU == 0) - { - m_PC++; - PCL = m_PC & 0xff; - m_inst_cycles += 1; /* Add NOP cycles */ - } -} - -static INLINE void iorlw(void) -{ - m_ALU = M_OPCODE_B0 | m_W; - m_W = m_ALU; - CALCULATE_Z_FLAG(); -} - -static INLINE void iorwf(void) -{ - m_ALU = GET_REGFILE(ADDR) | m_W; - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); -} - -static INLINE void movf(void) -{ - m_ALU = GET_REGFILE(ADDR); - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); -} - -static INLINE void movlw(void) -{ - m_W = M_OPCODE_B0; -} - -static INLINE void movwf(void) -{ - STORE_REGFILE(ADDR, m_W); -} - -static INLINE void nop(void) -{ - /* Do nothing */ -} - -static INLINE void option(void) -{ - m_OPTION = m_W & (T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG); -} - -static INLINE void retlw(void) -{ - m_W = M_OPCODE_B0; - m_PC = POP_STACK(); - PCL = m_PC & 0xff; -} - -static INLINE void rlf(void) -{ - uint8 bit7; - m_ALU = GET_REGFILE(ADDR); - bit7 = m_ALU & 0x80; - m_ALU <<= 1; - if (STATUS & C_FLAG) m_ALU |= 1; - STORE_RESULT(ADDR, m_ALU); - if (bit7) SET(STATUS, C_FLAG); - else CLR(STATUS, C_FLAG); -} - -static INLINE void rrf(void) -{ - uint8 bit0; - m_ALU = GET_REGFILE(ADDR); - bit0 = m_ALU & 1; - m_ALU >>= 1; - if (STATUS & C_FLAG) m_ALU |= 0x80; - STORE_RESULT(ADDR, m_ALU); - if (bit0) SET(STATUS, C_FLAG); - else CLR(STATUS, C_FLAG); -} - -static INLINE void sleepic(void) -{ - if (WDTE) m_WDT = 0; - if (PSA) m_prescaler = 0; - SET(STATUS, TO_FLAG); - CLR(STATUS, PD_FLAG); -} - -static INLINE void subwf(void) -{ - m_old_data = GET_REGFILE(ADDR); - m_ALU = m_old_data - m_W; - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); - CALCULATE_SUB_CARRY(); - CALCULATE_SUB_DIGITCARRY(); -} - -static INLINE void swapf(void) -{ - m_ALU = ((GET_REGFILE(ADDR) << 4) & 0xf0); - m_ALU |= ((GET_REGFILE(ADDR) >> 4) & 0x0f); - STORE_RESULT(ADDR, m_ALU); -} - -static INLINE void tris(void) -{ - switch(M_OPCODE_B0 & 0x7) - { - case 5: if (m_TRISA == m_W) break; - else { m_TRISA = m_W | 0xf0; m_write(PIC16C5x_PORTA, 0x1000 | (PORTA & (uint8)(~m_TRISA) & 0x0f)); break; } - case 6: if (m_TRISB == m_W) break; - else { m_TRISB = m_W; m_write(PIC16C5x_PORTB, 0x1000 | (PORTB & (uint8)(~m_TRISB))); break; } - case 7: if ((m_picmodel == 0x16C55) || (m_picmodel == 0x16C57)) { - if (m_TRISC == m_W) break; - else { m_TRISC = m_W; m_write(PIC16C5x_PORTC, 0x1000 | (PORTC & (uint8)(~m_TRISC))); break; } - } - else { - illegal(); break; - } - default: illegal(); break; - } -} - -static INLINE void xorlw(void) -{ - m_ALU = m_W ^ M_OPCODE_B0; - m_W = m_ALU; - CALCULATE_Z_FLAG(); -} - -static INLINE void xorwf(void) -{ - m_ALU = GET_REGFILE(ADDR) ^ m_W; - STORE_RESULT(ADDR, m_ALU); - CALCULATE_Z_FLAG(); -} - - - - -/*********************************************************************** - * Opcode Table (Cycles, Instruction) - ***********************************************************************/ - -static const uint8 s_opcode_main_cycles[256] = { -/*00*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*08*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*10*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*18*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*20*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*28*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*30*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*38*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*40*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*48*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*50*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*58*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*60*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*68*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*70*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*78*/ 1, 1, 1, 1, 1, 1, 1, 1, - -/*80*/ 2, 2, 2, 2, 2, 2, 2, 2, -/*88*/ 2, 2, 2, 2, 2, 2, 2, 2, -/*90*/ 2, 2, 2, 2, 2, 2, 2, 2, -/*98*/ 2, 2, 2, 2, 2, 2, 2, 2, -/*A0*/ 2, 2, 2, 2, 2, 2, 2, 2, -/*A8*/ 2, 2, 2, 2, 2, 2, 2, 2, -/*B0*/ 2, 2, 2, 2, 2, 2, 2, 2, -/*B8*/ 2, 2, 2, 2, 2, 2, 2, 2, - -/*C0*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*C8*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*D0*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*D8*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*E0*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*E8*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*F0*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*F8*/ 1, 1, 1, 1, 1, 1, 1, 1 -}; - -static const uint8 s_opcode_00x_cycles[16] = { -/*00*/ 1, 1, 1, 1, 1, 1, 1, 1, -/*08*/ 1, 1, 1, 1, 1, 1, 1, 1 -}; - - - -/**************************************************************************** - * Inits CPU emulation - ****************************************************************************/ - -enum -{ - PIC16C5x_PC=1, PIC16C5x_STK0, PIC16C5x_STK1, PIC16C5x_FSR, - PIC16C5x_W, PIC16C5x_ALU, PIC16C5x_STR, PIC16C5x_OPT, - PIC16C5x_TMR0, PIC16C5x_PRTA, PIC16C5x_PRTB, PIC16C5x_PRTC, PIC16C5x_PRTD, - PIC16C5x_WDT, PIC16C5x_TRSA, PIC16C5x_TRSB, PIC16C5x_TRSC, - PIC16C5x_PSCL -}; - -/**************************************************************************** - * Reset registers to their initial values - ****************************************************************************/ - -static INLINE void PIC16C5x_reset_regs(void) -{ - m_PC = m_picROMmask; - m_CONFIG = m_temp_config; - m_TRISA = 0xff; - m_TRISB = 0xff; - m_TRISC = 0xff; - m_OPTION = (T0CS_FLAG | T0SE_FLAG | PSA_FLAG | PS_REG); - PCL = 0xff; - FSR |= (uint8)(~m_picRAMmask); - m_prescaler = 0; - m_delay_timer = 0; - m_inst_cycles = 0; - m_count_pending = FALSE; -} - -void pic16c5x_reset(uint8 hard) -{ - if (hard) { - memset(m_internalram, 0, sizeof(m_internalram)); - PIC16C5x_reset_regs(); - CLR(STATUS, PA_REG); - SET(STATUS, (TO_FLAG | PD_FLAG)); - m_icount = 0; - m_clock2cycle = 0; - } else { - SET(STATUS, (TO_FLAG | PD_FLAG | Z_FLAG | DC_FLAG | C_FLAG)); - PIC16C5x_reset_regs(); - } -} - -void pic16c5x_set_config(uint16 data) -{ - m_temp_config = data; -} - - - -/**************************************************************************** - * WatchDog - ****************************************************************************/ - -static INLINE void PIC16C5x_update_watchdog(int counts) -{ - /* WatchDog is set up to count 18,000 (0x464f hex) ticks to provide */ - /* the timeout period of 0.018ms based on a 4MHz input clock. */ - /* Note: the 4MHz clock should be divided by the PIC16C5x_CLOCK_DIVIDER */ - /* which effectively makes the PIC run at 1MHz internally. */ - - /* If the current instruction is CLRWDT or SLEEP, don't update the WDT */ - - if ((M_OPCODE_S0 != 3) && (M_OPCODE_S0 != 4)) - { - uint16 old_WDT = m_WDT; - - m_WDT -= counts; - - if (m_WDT > 0x464f) { - m_WDT = 0x464f - (0xffff - m_WDT); - } - - if (((old_WDT != 0) && (old_WDT < m_WDT)) || (m_WDT == 0)) - { - if (PSA) { - m_prescaler++; - if (m_prescaler >= (1 << PS)) { /* Prescale values from 1 to 128 */ - m_prescaler = 0; - CLR(STATUS, TO_FLAG); - /* PIC16C5x_soft_reset(); */ - } - } - else { - CLR(STATUS, TO_FLAG); - /* PIC16C5x_soft_reset(); */ - } - } - } -} - - -/**************************************************************************** - * Update Timer - ****************************************************************************/ - -static INLINE void PIC16C5x_update_timer(int counts) -{ - if (PSA == 0) { - m_prescaler += counts; - if (m_prescaler >= (2 << PS)) { /* Prescale values from 2 to 256 */ - TMR0 += (m_prescaler / (2 << PS)); - m_prescaler %= (2 << PS); /* Overflow prescaler */ - } - } - else { - TMR0 += counts; - } -} - -void pic16c5x_set_input(int line, int state) -{ - switch (line) - { - /* RTCC/T0CKI pin */ - case PIC16C5x_RTCC: - if (T0CS && state != m_rtcc) /* Count mode, edge triggered */ - if ((T0SE && !state) || (!T0SE && state)) - m_count_pending = TRUE; - - m_rtcc = state; - break; - - default: - break; - } -} - - -void pic16c5x_run(void) -{ - if ((++m_clock2cycle &3) ==0) m_icount++; - - while (m_icount > 0) { - if (PD == 0) /* Sleep Mode */ - { - m_count_pending = FALSE; - m_inst_cycles = 1; - if (WDTE) { - PIC16C5x_update_watchdog(1); - } - } - else - { - if (m_count_pending) { /* RTCC/T0CKI clocked while in Count mode */ - m_count_pending = FALSE; - PIC16C5x_update_timer(1); - } - - m_PREVPC = m_PC; - - M_OPCODE_S0 = M_RDOP(m_PC); - /* printf("%04X: %03X %03X\n", m_PC, M_OPCODE_S0, M_OPCODE_B0); */ - m_PC++; - PCL++; - - if (m_picmodel == 0x1650 || m_picmodel == 0x1655 || (M_OPCODE_S0 & 0xff0) != 0x000) { /* Do all opcodes except the 00? ones */ - uint8 b1 = (M_OPCODE_S0 >> 4) & 0xff; - m_inst_cycles = s_opcode_main_cycles[b1]; - switch (b1) { - #include "pic16c5x_ops_main.inc" - } - } - else { /* Opcode 0x00? has many opcodes in its minor nibble */ - uint8 b1 = M_OPCODE_B0 & 0x1f; - m_inst_cycles = s_opcode_00x_cycles[b1]; - switch (b1) { - #include "pic16c5x_ops_00x.inc" - } - } - - if (!T0CS) { /* Timer mode */ - if (m_delay_timer) { - m_delay_timer--; - } - else { - PIC16C5x_update_timer(m_inst_cycles); - } - } - if (WDTE) { - PIC16C5x_update_watchdog(m_inst_cycles); - } - } - - m_icount -= m_inst_cycles; - } -} - -void AddExState(void *v, uint32 s, int type, char *desc); - -void pic16c5x_add_statesinfo(void) { - AddExState(&m_PC, sizeof(m_PC), 0, "PC00"); - AddExState(&m_PREVPC, sizeof(m_PREVPC), 0, "PRPC"); - AddExState(&m_W, sizeof(m_W), 0, "W000"); - AddExState(&m_OPTION, sizeof(m_OPTION), 0, "OPT0"); - AddExState(&m_CONFIG, sizeof(m_CONFIG), 0, "CONF"); - AddExState(&m_ALU, sizeof(m_ALU), 0, "ALU"); - AddExState(&m_WDT, sizeof(m_WDT), 0, "WDT"); - AddExState(&m_TRISA, sizeof(m_TRISA), 0, "TRSA"); - AddExState(&m_TRISB, sizeof(m_TRISB), 0, "TRSB"); - AddExState(&m_TRISC, sizeof(m_TRISC), 0, "TRSC"); - AddExState(&m_STACK[0], sizeof(m_STACK[0]), 0, "STC0"); - AddExState(&m_STACK[1], sizeof(m_STACK[1]), 0, "STC1"); - AddExState(&m_prescaler, sizeof(m_prescaler), 0, "PSCL"); - AddExState(&m_opcode, sizeof(m_opcode), 0, "OPS0"); - AddExState(m_internalram, sizeof(m_internalram), 0, "IRAM"); - AddExState(&m_icount, sizeof(m_icount), 0, "ICNT"); - AddExState(&m_delay_timer, sizeof(m_delay_timer), 0, "DTIM"); - AddExState(&m_rtcc, sizeof(m_rtcc), 0, "RTCC"); - AddExState(&m_count_pending, sizeof(m_count_pending), 0, "CNTP"); - AddExState(&m_inst_cycles, sizeof(m_inst_cycles), 0, "ICYC"); - AddExState(&m_clock2cycle, sizeof(m_clock2cycle), 0, "CL2C"); -} \ No newline at end of file diff --git a/src/mappers/hw/pic16c5x.h b/src/mappers/hw/pic16c5x.h deleted file mode 100644 index 67c03dc17..000000000 --- a/src/mappers/hw/pic16c5x.h +++ /dev/null @@ -1,57 +0,0 @@ -/* license:BSD-3-Clause */ -/* copyright-holders:Tony La Porta */ - /**************************************************************************\ - * Microchip PIC16C5x_ Emulator * - * * - * Copyright Tony La Porta * - * Originally written for the MAME project. * - * * - * * - * Addressing architecture is based on the Harvard addressing scheme. * - * * - \**************************************************************************/ - -#ifndef _PIC16C5x_H -#define _PIC16C5x_H - -#include "../../fceu-types.h" - -typedef uint8 (*pic16c5x_readfunc)(int); -typedef void (*pic16c5x_writefunc)(int, int); - -enum { - PIC16C5x_RTCC = 0 -}; - - -/* in the mid-90s RTCC was renamed to T0CKI */ -#define PIC16C5x_T0CKI PIC16C5x_RTCC - -/* i/o ports */ -enum { - PIC16C5x_PORTA = 0, - PIC16C5x_PORTB, - PIC16C5x_PORTC, - PIC16C5x_PORTD -}; - -/**************************************************************************** - * Function to configure the CONFIG register. This is actually hard-wired - * during ROM programming, so should be called in the driver INIT, with - * the value if known (available in HEX dumps of the ROM). - */ -void pic16c5x_set_input(int line, int state); -void pic16c5x_set_config(uint16 data); -void pic16c5x_reset(uint8 hard); -void pic16c5x_run(void); -void pic16c5x_add_statesinfo(void); - -void pic16c54_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); -void pic16c55_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); -void pic16c56_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); -void pic16c57_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); -void pic16c58_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); -void pic1650_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); -void pic1655_init(uint8* rom, pic16c5x_readfunc _rd, pic16c5x_writefunc _wr); - -#endif /* _PIC16C5x_H */ diff --git a/src/mappers/hw/pic16c5x_ops_00x.inc b/src/mappers/hw/pic16c5x_ops_00x.inc deleted file mode 100644 index 67f058efc..000000000 --- a/src/mappers/hw/pic16c5x_ops_00x.inc +++ /dev/null @@ -1,16 +0,0 @@ -case 0x00: nop(); break; -case 0x01: illegal(); break; -case 0x02: option(); break; -case 0x03: sleepic(); break; -case 0x04: clrwdt(); break; -case 0x05: tris(); break; -case 0x06: tris(); break; -case 0x07: tris(); break; -case 0x08: illegal(); break; -case 0x09: illegal(); break; -case 0x0A: illegal(); break; -case 0x0B: illegal(); break; -case 0x0C: illegal(); break; -case 0x0D: illegal(); break; -case 0x0E: illegal(); break; -case 0x0F: illegal(); break; \ No newline at end of file diff --git a/src/mappers/hw/pic16c5x_ops_main.inc b/src/mappers/hw/pic16c5x_ops_main.inc deleted file mode 100644 index f054d548f..000000000 --- a/src/mappers/hw/pic16c5x_ops_main.inc +++ /dev/null @@ -1,287 +0,0 @@ -case 0x00: nop(); break; -case 0x01: illegal(); break; -case 0x02: movwf(); break; -case 0x03: movwf(); break; -case 0x04: clrw(); break; -case 0x05: illegal(); break; -case 0x06: clrf(); break; -case 0x07: clrf(); break; -/*08*/ -case 0x08: subwf(); break; -case 0x09: subwf(); break; -case 0x0A: subwf(); break; -case 0x0B: subwf(); break; -case 0x0C: decf(); break; -case 0x0D: decf(); break; -case 0x0E: decf(); break; -case 0x0F: decf(); break; -/*10*/ -case 0x10: iorwf(); break; -case 0x11: iorwf(); break; -case 0x12: iorwf(); break; -case 0x13: iorwf(); break; -case 0x14: andwf(); break; -case 0x15: andwf(); break; -case 0x16: andwf(); break; -case 0x17: andwf(); break; -/*18*/ -case 0x18: xorwf(); break; -case 0x19: xorwf(); break; -case 0x1A: xorwf(); break; -case 0x1B: xorwf(); break; -case 0x1C: addwf(); break; -case 0x1D: addwf(); break; -case 0x1E: addwf(); break; -case 0x1F: addwf(); break; -/*20*/ -case 0x20: movf(); break; -case 0x21: movf(); break; -case 0x22: movf(); break; -case 0x23: movf(); break; -case 0x24: comf(); break; -case 0x25: comf(); break; -case 0x26: comf(); break; -case 0x27: comf(); break; -/*28*/ -case 0x28: incf(); break; -case 0x29: incf(); break; -case 0x2A: incf(); break; -case 0x2B: incf(); break; -case 0x2C: decfsz(); break; -case 0x2D: decfsz(); break; -case 0x2E: decfsz(); break; -case 0x2F: decfsz(); break; -/*30*/ -case 0x30: rrf(); break; -case 0x31: rrf(); break; -case 0x32: rrf(); break; -case 0x33: rrf(); break; -case 0x34: rlf(); break; -case 0x35: rlf(); break; -case 0x36: rlf(); break; -case 0x37: rlf(); break; -/*38*/ -case 0x38: swapf(); break; -case 0x39: swapf(); break; -case 0x3A: swapf(); break; -case 0x3B: swapf(); break; -case 0x3C: incfsz(); break; -case 0x3D: incfsz(); break; -case 0x3E: incfsz(); break; -case 0x3F: incfsz(); break; -/*40*/ -case 0x40: bcf(); break; -case 0x41: bcf(); break; -case 0x42: bcf(); break; -case 0x43: bcf(); break; -case 0x44: bcf(); break; -case 0x45: bcf(); break; -case 0x46: bcf(); break; -case 0x47: bcf(); break; -/*48*/ -case 0x48: bcf(); break; -case 0x49: bcf(); break; -case 0x4A: bcf(); break; -case 0x4B: bcf(); break; -case 0x4C: bcf(); break; -case 0x4D: bcf(); break; -case 0x4E: bcf(); break; -case 0x4F: bcf(); break; -/*50*/ -case 0x50: bsf(); break; -case 0x51: bsf(); break; -case 0x52: bsf(); break; -case 0x53: bsf(); break; -case 0x54: bsf(); break; -case 0x55: bsf(); break; -case 0x56: bsf(); break; -case 0x57: bsf(); break; -/*58*/ -case 0x58: bsf(); break; -case 0x59: bsf(); break; -case 0x5A: bsf(); break; -case 0x5B: bsf(); break; -case 0x5C: bsf(); break; -case 0x5D: bsf(); break; -case 0x5E: bsf(); break; -case 0x5F: bsf(); break; -/*60*/ -case 0x60: btfsc(); break; -case 0x61: btfsc(); break; -case 0x62: btfsc(); break; -case 0x63: btfsc(); break; -case 0x64: btfsc(); break; -case 0x65: btfsc(); break; -case 0x66: btfsc(); break; -case 0x67: btfsc(); break; -/*68*/ -case 0x68: btfsc(); break; -case 0x69: btfsc(); break; -case 0x6A: btfsc(); break; -case 0x6B: btfsc(); break; -case 0x6C: btfsc(); break; -case 0x6D: btfsc(); break; -case 0x6E: btfsc(); break; -case 0x6F: btfsc(); break; -/*70*/ -case 0x70: btfss(); break; -case 0x71: btfss(); break; -case 0x72: btfss(); break; -case 0x73: btfss(); break; -case 0x74: btfss(); break; -case 0x75: btfss(); break; -case 0x76: btfss(); break; -case 0x77: btfss(); break; -/*78*/ -case 0x78: btfss(); break; -case 0x79: btfss(); break; -case 0x7A: btfss(); break; -case 0x7B: btfss(); break; -case 0x7C: btfss(); break; -case 0x7E: btfss(); break; -case 0x7D: btfss(); break; -case 0x7F: btfss(); break; -/*80*/ -case 0x80: retlw(); break; -case 0x81: retlw(); break; -case 0x82: retlw(); break; -case 0x83: retlw(); break; -case 0x84: retlw(); break; -case 0x85: retlw(); break; -case 0x86: retlw(); break; -case 0x87: retlw(); break; -/*88*/ -case 0x88: retlw(); break; -case 0x89: retlw(); break; -case 0x8A: retlw(); break; -case 0x8B: retlw(); break; -case 0x8C: retlw(); break; -case 0x8D: retlw(); break; -case 0x8E: retlw(); break; -case 0x8F: retlw(); break; -/*90*/ -case 0x90: call(); break; -case 0x91: call(); break; -case 0x92: call(); break; -case 0x93: call(); break; -case 0x94: call(); break; -case 0x95: call(); break; -case 0x96: call(); break; -case 0x97: call(); break; -/*98*/ -case 0x98: call(); break; -case 0x99: call(); break; -case 0x9A: call(); break; -case 0x9B: call(); break; -case 0x9C: call(); break; -case 0x9D: call(); break; -case 0x9E: call(); break; -case 0x9F: call(); break; -/*A0*/ -case 0xA0: goto_op(); break; -case 0xA1: goto_op(); break; -case 0xA2: goto_op(); break; -case 0xA3: goto_op(); break; -case 0xA4: goto_op(); break; -case 0xA5: goto_op(); break; -case 0xA6: goto_op(); break; -case 0xA7: goto_op(); break; -/*A8*/ -case 0xA8: goto_op(); break; -case 0xA9: goto_op(); break; -case 0xAA: goto_op(); break; -case 0xAB: goto_op(); break; -case 0xAC: goto_op(); break; -case 0xAD: goto_op(); break; -case 0xAE: goto_op(); break; -case 0xAF: goto_op(); break; -/*B0*/ -case 0xB0: goto_op(); break; -case 0xB1: goto_op(); break; -case 0xB2: goto_op(); break; -case 0xB3: goto_op(); break; -case 0xB4: goto_op(); break; -case 0xB5: goto_op(); break; -case 0xB6: goto_op(); break; -case 0xB7: goto_op(); break; -/*B8*/ -case 0xB8: goto_op(); break; -case 0xB9: goto_op(); break; -case 0xBA: goto_op(); break; -case 0xBB: goto_op(); break; -case 0xBC: goto_op(); break; -case 0xBD: goto_op(); break; -case 0xBE: goto_op(); break; -case 0xBF: goto_op(); break; -/*C0*/ -case 0xC0: movlw(); break; -case 0xC1: movlw(); break; -case 0xC2: movlw(); break; -case 0xC3: movlw(); break; -case 0xC4: movlw(); break; -case 0xC5: movlw(); break; -case 0xC6: movlw(); break; -case 0xC7: movlw(); break; -/*C8*/ -case 0xC8: movlw(); break; -case 0xC9: movlw(); break; -case 0xCA: movlw(); break; -case 0xCB: movlw(); break; -case 0xCC: movlw(); break; -case 0xCD: movlw(); break; -case 0xCE: movlw(); break; -case 0xCF: movlw(); break; -/*D0*/ -case 0xD0: iorlw(); break; -case 0xD1: iorlw(); break; -case 0xD2: iorlw(); break; -case 0xD3: iorlw(); break; -case 0xD4: iorlw(); break; -case 0xD5: iorlw(); break; -case 0xD6: iorlw(); break; -case 0xD7: iorlw(); break; -/*D8*/ -case 0xD8: iorlw(); break; -case 0xD9: iorlw(); break; -case 0xDA: iorlw(); break; -case 0xDB: iorlw(); break; -case 0xDC: iorlw(); break; -case 0xDD: iorlw(); break; -case 0xDE: iorlw(); break; -case 0xDF: iorlw(); break; -/*E0*/ -case 0xE0: andlw(); break; -case 0xE1: andlw(); break; -case 0xE2: andlw(); break; -case 0xE3: andlw(); break; -case 0xE4: andlw(); break; -case 0xE5: andlw(); break; -case 0xE6: andlw(); break; -case 0xE7: andlw(); break; -/*E8*/ -case 0xE8: andlw(); break; -case 0xE9: andlw(); break; -case 0xEA: andlw(); break; -case 0xEB: andlw(); break; -case 0xEC: andlw(); break; -case 0xED: andlw(); break; -case 0xEE: andlw(); break; -case 0xEF: andlw(); break; -/*F0*/ -case 0xF0: xorlw(); break; -case 0xF1: xorlw(); break; -case 0xF2: xorlw(); break; -case 0xF3: xorlw(); break; -case 0xF4: xorlw(); break; -case 0xF5: xorlw(); break; -case 0xF6: xorlw(); break; -case 0xF7: xorlw(); break; -/*F8*/ -case 0xF8: xorlw(); break; -case 0xF9: xorlw(); break; -case 0xFA: xorlw(); break; -case 0xFB: xorlw(); break; -case 0xFC: xorlw(); break; -case 0xFD: xorlw(); break; -case 0xFE: xorlw(); break; -case 0xFF: xorlw(); break; diff --git a/src/mappers/hw/txc.c b/src/mappers/hw/txc.c deleted file mode 100644 index 98953e27a..000000000 --- a/src/mappers/hw/txc.c +++ /dev/null @@ -1,138 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * TXC/Micro Genius simplified mapper - * updated 06-2019 http://wiki.nesdev.com/w/index.php/INES_Mapper_036 - * - * Known games: - * - Strike Wolf (Asia) (Unl) - * - Policeman (Gluk Video) (unl) - * - F-15 City War (Spain) (Gluk Video) (Unl) - * - * TXC mappers, originally much complex banksitching - * - * 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang - * 01-22110-000 (52S ) - MGC-002 2-in-1 Gun - * 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block - * (079 ) - MGC-012 Poke Block - * 01-22110-200 (05-00002-010) (036 ) - MGC-014 Strike Wolf - * 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman - * 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior - * 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1 - * 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom - * 01-22200-400 (------------) (079 ) - ET.03 F-15 City War - * (172 ) - 1991 Du Ma Racing - * - */ - -/* added 2020-2-16 - * Updated based on latest source - * Mappers 36, 132, 173 - * Mappers 136, 147, 172 - */ - -#include "mapinc.h" -#include "txc.h" - -TXC txc; - -static void Dummyfunc(void) { } -static void (*WSync)(void) = Dummyfunc; - -static SFORMAT StateRegs[] = -{ - { &txc.accumulator, 1, "ACC0" }, - { &txc.inverter, 1, "INVR" }, - { &txc.staging, 1, "STG0" }, - { &txc.output, 1, "OUT0" }, - { &txc.increase, 1, "INC0" }, - { &txc.X, 1, "XFLG" }, - { &txc.Y, 1, "YFLG" }, - { &txc.invert, 1, "INVT" }, - { 0 } -}; - -DECLFR(TXC_Read) { - uint8 ret = CPU_OPENBUS; - if ((A & 0x103) == 0x100) { - ret = ((txc.accumulator & 0x07) | ((txc.inverter ^ txc.invert) & ~0x07)); - txc.Y = txc.X || ((ret & 0x10) != 0); - WSync(); - } - return ret; -} - -DECLFW(TXC_Write) { - if (A & 0x8000) { - txc.output = (txc.accumulator & 0x0F) | ((txc.inverter << 1) & 0x10); - } else { - switch (A & 0x103) { - case 0x100: - if (txc.increase) { - txc.accumulator++; - } else { - txc.accumulator = ((txc.accumulator & ~0x07) | ((txc.staging ^ txc.invert) & 0x07)); - } - break; - case 0x101: - txc.invert = (V & 0x01) ? 0xFF : 0x00; - break; - case 0x102: - txc.staging = V & 0x07; - txc.inverter = V & ~0x07; - break; - case 0x103: - txc.increase = ((V & 0x01) != 0); - break; - } - } - txc.X = txc.invert ? txc.A : txc.B; - txc.Y = txc.X || ((V & 0x10) != 0); - WSync(); -} - -static void TXCRegReset(void) { - WSync(); -} - -void TXC_Power(void) { - txc.output = 0; - txc.accumulator = 0; - txc.inverter = 0; - txc.staging = 0; - txc.increase = 0; - txc.invert = 0; - txc.X = 0; - txc.Y = 0; - txc.A = 0; - txc.B = 1; - TXCRegReset(); -} - -static void StateRestore(int version) { - WSync(); -} - -void TXC_Init(CartInfo *info, void (*proc)(void)) { - WSync = proc; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/hw/txc.h b/src/mappers/hw/txc.h deleted file mode 100644 index 589ec32ee..000000000 --- a/src/mappers/hw/txc.h +++ /dev/null @@ -1,46 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _TXC_H -#define _TXC_H - -typedef struct __TXC { - uint8 accumulator; - uint8 inverter; - uint8 staging; - uint8 output; - uint8 increase; - uint8 invert; - uint8 A; - uint8 B; - uint8 X; - uint8 Y; -} TXC; - -extern TXC txc; - -DECLFR(TXC_Read); -DECLFW(TXC_Write); - -void TXC_Power(void); - -void TXC_Init(CartInfo *info, void (*proc)(void)); - -#endif /* _TXC_H */ diff --git a/src/mappers/hw/vrc24.c b/src/mappers/hw/vrc24.c deleted file mode 100644 index ba5216eb6..000000000 --- a/src/mappers/hw/vrc24.c +++ /dev/null @@ -1,277 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * VRC-2/VRC-4 Konami - * VRC-4 Pirate - * - * VRC2 - * Nickname PCB A0 A1 Registers iNES mapper submapper - * VRC2a 351618 A1 A0 $x000, $x002, $x001, $x003 22 0 - * VRC2b many† A0 A1 $x000, $x001, $x002, $x003 23 3 - * VRC2c 351948 A1 A0 $x000, $x002, $x001, $x003 25 3 - * VRC4 - * Nickname PCB A0 A1 Registers iNES mapper submapper - * VRC4a 352398 A1 A2 $x000, $x002, $x004, $x006 21 1 - * VRC4b 351406 A1 A0 $x000, $x002, $x001, $x003 25 1 - * VRC4c 352889 A6 A7 $x000, $x040, $x080, $x0C0 21 2 - * VRC4d 352400 A3 A2 $x000, $x008, $x004, $x00C 25 2 - * VRC4e 352396 A2 A3 $x000, $x004, $x008, $x00C 23 2 - * VRC4f - A0 A1 $x000, $x001, $x002, $x003 23 1 - * - */ - -#include "mapinc.h" -#include "vrc24.h" -#include "vrcirq.h" - -void (*VRC24_FixPRG)(void); -void (*VRC24_FixCHR)(void); -void (*VRC24_FixMIR)(void); - -void (*VRC24_pwrap)(uint16 A, uint16 V); -void (*VRC24_cwrap)(uint16 A, uint16 V); -void (*VRC24_miscWrite)(uint16 A, uint8 V); - -VRC24 vrc24; - -static SFORMAT StateRegs[] = { - { vrc24.prg, 2, "PREG" }, - { vrc24.chr, 16, "CREG" }, - { &vrc24.cmd, 1, "CMDR" }, - { &vrc24.mirr, 1, "MIRR" }, - { &vrc24.latch, 1, "LATC" }, - - { &vrc24.VRC4, 1, "VRC4" }, - { &vrc24.A0, 2, "ADR0" }, - { &vrc24.A1, 2, "ADR1" }, - - { 0 } -}; - -static void GENFIXPRG(void) { - if (vrc24.cmd & 2) { - VRC24_pwrap(0x8000, ~1); - VRC24_pwrap(0xC000, vrc24.prg[0]); - } else { - VRC24_pwrap(0x8000, vrc24.prg[0]); - VRC24_pwrap(0xC000, ~1); - } - VRC24_pwrap(0xA000, vrc24.prg[1]); - VRC24_pwrap(0xE000, ~0); -} - -static void GENFIXCHR(void) { - VRC24_cwrap(0x0000, vrc24.chr[0]); - VRC24_cwrap(0x0400, vrc24.chr[1]); - VRC24_cwrap(0x0800, vrc24.chr[2]); - VRC24_cwrap(0x0C00, vrc24.chr[3]); - VRC24_cwrap(0x1000, vrc24.chr[4]); - VRC24_cwrap(0x1400, vrc24.chr[5]); - VRC24_cwrap(0x1800, vrc24.chr[6]); - VRC24_cwrap(0x1C00, vrc24.chr[7]); -} - -static void GENFIXMIR(void) { - switch (vrc24.mirr & (vrc24.VRC4 ? 0x03 : 0x01)) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -static DECLFR(VRC24WRAMRead) { - A = 0x6000 | (A & (WRAMSIZE - 1)); - return CartBR(A); -} - -static DECLFW(VRC24WRAMWrite) { - A = 0x6000 | (A & (WRAMSIZE - 1)); - CartBW(A, V); -} - -static DECLFR(VRC24LatchRead) { - return (CPU_OPENBUS & ~0x01) | (vrc24.latch & 0x01); -} - -static DECLFW(VRC24LatchWrite) { - vrc24.latch = V; - VRC24_FixPRG(); - VRC24_FixCHR(); -} - -DECLFW(VRC24_Write) { - uint8 index; - - switch (A & 0xF000) { - case 0x8000: - case 0xA000: - vrc24.prg[(A >> 13) & 0x01] = V & 0x1F; - VRC24_FixPRG(); - break; - - case 0x9000: - index = ((A & vrc24.A1) ? 0x02 : 0x00) | ((A & vrc24.A0) ? 0x01 : 0x00); - switch (index & (vrc24.VRC4 ? 0x03 : 0x00)) { - case 0: - case 1: - if (V != 0xFF) { - vrc24.mirr = V; - VRC24_FixMIR(); - } - break; - case 2: - vrc24.cmd = V; - VRC24_FixPRG(); - break; - case 3: - if (VRC24_miscWrite) { - VRC24_miscWrite(A, V); - } - break; - } - break; - - case 0xF000: - index = ((A & vrc24.A1) ? 0x02 : 0x00) | ((A & vrc24.A0) ? 0x01 : 0x00); - switch (index) { - case 0x00: VRCIRQ_LatchNibble(V, 0); break; - case 0x01: VRCIRQ_LatchNibble(V, 1); break; - case 0x02: VRCIRQ_Control(V); break; - case 0x03: VRCIRQ_Acknowledge(); break; - } - break; - - default: - index = (((A - 0xB000) >> 11) & 0x06) | ((A & vrc24.A1) ? 0x01 : 0x00); - if (A & vrc24.A0) { - /* m25 can be 512K, rest are 256K or less */ - vrc24.chr[index] = (vrc24.chr[index] & 0x000F) | (V << 4); - } else { - vrc24.chr[index] = (vrc24.chr[index] & 0x0FF0) | (V & 0x0F); - } - VRC24_cwrap(index << 10, vrc24.chr[index]); - break; - } -} - -static void GENPWRAP(uint16 A, uint16 V) { - setprg8(A, V & 0x1F); -} - -static void GENCWRAP(uint16 A, uint16 V) { - setchr1(A, V & 0x1FF); -} - -void VRC24_IRQCPUHook(int a) { - VRCIRQ_CPUHook(a); -} - -void VRC24_Reset(void) { - vrc24.prg[0] = 0; - vrc24.prg[1] = 1; - - vrc24.chr[0] = 0; - vrc24.chr[1] = 1; - vrc24.chr[2] = 2; - vrc24.chr[3] = 3; - vrc24.chr[4] = 4; - vrc24.chr[5] = 5; - vrc24.chr[6] = 6; - vrc24.chr[7] = 7; - - vrc24.cmd = vrc24.mirr = 0; - - VRC24_FixPRG(); - VRC24_FixCHR(); -} - -void VRC24_Power(void) { - VRC24_Reset(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, VRC24_Write); - - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, VRC24WRAMRead); - SetWriteHandler(0x6000, 0x7FFF, VRC24WRAMWrite); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } else if (!vrc24.VRC4) { - /* microwire interface */ - SetReadHandler(0x6000, 0x6FFF, VRC24LatchRead); - SetWriteHandler(0x6000, 0x6FFF, VRC24LatchWrite); - } - - if (!CHR_ROM_SIZE) { - setchr8(0); - } -} - -static void StateRestore(int version) { - VRC24_FixPRG(); - VRC24_FixCHR(); - VRC24_FixMIR(); -} - -void VRC24_Close(void) { -} - -void VRC24_Init(CartInfo *info, uint8 vrc4, uint32 A0, uint32 A1, int wram, int irqRepeated) { - VRC24_FixPRG = GENFIXPRG; - VRC24_FixCHR = GENFIXCHR; - VRC24_FixMIR = GENFIXMIR; - - VRC24_pwrap = GENPWRAP; - VRC24_cwrap = GENCWRAP; - VRC24_miscWrite = NULL; - - vrc24.A0 = A0; - vrc24.A1 = A1; - vrc24.VRC4 = vrc4; - - if (wram) { - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } else { - WRAMSIZE = 8192; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } - } - - AddExState(StateRegs, ~0, 0, NULL); - - info->Power = VRC24_Power; - info->Close = VRC24_Close; - GameStateRestore = StateRestore; - - VRCIRQ_Init(irqRepeated); - MapIRQHook = VRCIRQ_CPUHook; - AddExState(&VRCIRQ_StateRegs, ~0, 0, 0); -} diff --git a/src/mappers/hw/vrc24.h b/src/mappers/hw/vrc24.h deleted file mode 100644 index 797b2efba..000000000 --- a/src/mappers/hw/vrc24.h +++ /dev/null @@ -1,74 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _VRC24_H -#define _VRC24_H - -typedef enum { - VRC2a = 1, /* Mapper 22 */ - VRC2b, /* Mapper 23 */ - VRC2c, /* Mapper 25 */ - VRC4a, /* Mapper 21 */ - VRC4b, /* Mapper 25 */ - VRC4c, /* Mapper 21 */ - VRC4d, /* Mapper 25 */ - VRC4e, /* Mapper 23 */ - VRC4f, /* Mapper 23 */ - VRC4_544, - VRC4_559 -} VRC24Type; - -enum { - VRC2 = 0, - VRC4 -}; - -typedef struct __VRC24 { - uint8 prg[2]; - uint16 chr[8]; - uint8 cmd; - uint8 mirr; - uint8 latch; /* VRC2 $6000-$6FFF */ - - uint8 VRC4; /* type */ - uint16 A0; - uint16 A1; -} VRC24; - -extern VRC24 vrc24; - -DECLFW(VRC24_Write); - -void VRC24_IRQCPUHook(int a); -void VRC24_Reset(void); -void VRC24_Power(void); -void VRC24_Close(void); - -void VRC24_Init(CartInfo *info, uint8 vrc4, uint32 A0, uint32 A1, int wram, int irqRepeated); - -extern void (*VRC24_FixPRG)(void); -extern void (*VRC24_FixCHR)(void); -extern void (*VRC24_FixMIR)(void); - -extern void (*VRC24_pwrap)(uint16 A, uint16 V); -extern void (*VRC24_cwrap)(uint16 A, uint16 V); -extern void (*VRC24_miscWrite)(uint16 A, uint8 V); - -#endif /* _VRC24_H */ diff --git a/src/mappers/hw/vrc6.c b/src/mappers/hw/vrc6.c deleted file mode 100644 index 447b64c5d..000000000 --- a/src/mappers/hw/vrc6.c +++ /dev/null @@ -1,203 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * VRC-6 - * - */ - -#include "mapinc.h" -#include "vrc6.h" -#include "vrcirq.h" -#include "vrc6sound.h" - -static uint32 vrc6_A0; -static uint32 vrc6_A1; - -VRC6 vrc6; - -void (*VRC6_pwrap)(uint16 A, uint16 V); -void (*VRC6_cwrap)(uint16 A, uint16 V); - -static SFORMAT StateRegs[] = -{ - { vrc6.prg, 2, "PRG" }, - { vrc6.chr, 8, "CHR" }, - { &vrc6.mirr, 1, "MIRR" }, - - { 0 } -}; - -static void GENPWRAP(uint16 A, uint16 V) { - setprg8(A, V & 0x3F); -} - -static void GENCWRAP(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -void VRC6_FixMIR(void) { - switch (vrc6.mirr & 3) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -void VRC6_FixPRG(void) { - VRC6_pwrap(0x8000, (vrc6.prg[0] << 1) | 0x00); - VRC6_pwrap(0xa000, (vrc6.prg[0] << 1) | 0x01); - VRC6_pwrap(0xc000, vrc6.prg[1]); - VRC6_pwrap(0xe000, ~0); -} - -void VRC6_FixCHR(void) { - int i; - - for (i = 0; i < 8; i++) { - VRC6_cwrap(i << 10, vrc6.chr[i]); - } -} - -DECLFW(VRC6_Write) { - int index; - - A = (A & 0xF000) | ((A & vrc6_A1) ? 0x02 : 0x00) | ((A & vrc6_A0) ? 0x01 : 0x00); - switch (A & 0xF000) { - case 0x8000: - vrc6.prg[0] = V; - VRC6_pwrap(0x8000, (V << 1) | 0x00); - VRC6_pwrap(0xA000, (V << 1) | 0x01); - break; - case 0x9000: - VRC6Sound_Write(A, V); - break; - case 0xA000: - VRC6Sound_Write(A, V); - break; - case 0xB000: - VRC6Sound_Write(A, V); - if ((A & 0x03) == 0x03) { - vrc6.mirr = (V >> 2) & 3; - VRC6_FixMIR(); - } - break; - case 0xC000: - vrc6.prg[1] = V; - VRC6_pwrap(0xC000, V); - break; - case 0xD000: - case 0xE000: - index = ((A - 0xD000) >> 10) | (A & 0x03); - vrc6.chr[index] = V; - VRC6_cwrap(index << 10, V); - break; - case 0xF000: - index = A & 0x03; - switch (index) { - case 0x00: VRCIRQ_Latch(V); break; - case 0x01: VRCIRQ_Control(V); break; - case 0x02: VRCIRQ_Acknowledge(); break; - } - } -} - -void VRC6_IRQCPUHook(int a) { - VRCIRQ_CPUHook(a); -} - -void VRC6_Reset(void) { - vrc6.prg[0] = 0; - vrc6.prg[1] = 1; - - vrc6.chr[0] = 0; - vrc6.chr[1] = 1; - vrc6.chr[2] = 2; - vrc6.chr[3] = 3; - vrc6.chr[4] = 4; - vrc6.chr[5] = 5; - vrc6.chr[6] = 6; - vrc6.chr[7] = 7; - - vrc6.mirr = 0; - - VRC6_FixPRG(); - VRC6_FixCHR(); - VRC6_FixMIR(); -} - -void VRC6_Power(void) { - VRC6_Reset(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, VRC6_Write); - - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } -} - -void VRC6_Close(void) { -} - -void VRC6_Restore(int version) { - VRC6_FixPRG(); - VRC6_FixCHR(); - VRC6_FixMIR(); -} - -void VRC6_Init(CartInfo *info, uint32 A0, uint32 A1, int wram) { - VRC6_pwrap = GENPWRAP; - VRC6_cwrap = GENCWRAP; - - vrc6_A0 = A0; - vrc6_A1 = A1; - - if (wram) { - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } else if (info->mapper == 26) { - WRAMSIZE = 8192; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } - } - AddExState(StateRegs, ~0, 0, NULL); - - info->Power = VRC6_Power; - info->Close = VRC6_Close; - GameStateRestore = VRC6_Restore; - - VRCIRQ_Init(TRUE); - MapIRQHook = VRC6_IRQCPUHook; - AddExState(&VRCIRQ_StateRegs, ~0, 0, 0); - - VRC6Sound_ESI(); - VRC6Sound_AddStateInfo(); -} diff --git a/src/mappers/hw/vrc6.h b/src/mappers/hw/vrc6.h deleted file mode 100644 index 59f709082..000000000 --- a/src/mappers/hw/vrc6.h +++ /dev/null @@ -1,49 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _VRC6_H -#define _VRC6_H - -typedef struct __VRC6 { - uint8 prg[2]; - uint8 chr[8]; - uint8 mirr; -} VRC6; - -extern VRC6 vrc6; - -DECLFW(VRC6_Write); - -void VRC6_Power(void); -void VRC6_Reset(void); -void VRC6_Close(void); -void VRC6_Restore(int version); -void VRC6_IRQCPUHook(int a); - -void VRC6_Init(CartInfo *info, uint32 A0, uint32 A1, int wram); - -void VRC6_FixPRG(void); -void VRC6_FixCHR(void); -void VRC6_FixMIR(void); - -extern void (*VRC6_pwrap)(uint16 A, uint16 V); -extern void (*VRC6_cwrap)(uint16 A, uint16 V); - -#endif /* _VRC6_H */ diff --git a/src/mappers/hw/vrc7.c b/src/mappers/hw/vrc7.c deleted file mode 100644 index 47590431e..000000000 --- a/src/mappers/hw/vrc7.c +++ /dev/null @@ -1,185 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "vrcirq.h" -#include "vrc7sound.h" -#include "vrc7.h" - -static uint32 vrc7_A0; -static uint32 vrc7_A1; - -VRC7 vrc7; - -void (*VRC7_pwrap)(uint16 A, uint16 V); -void (*VRC7_cwrap)(uint16 A, uint16 V); -void (*VRC7_mwrap)(uint8 V); - -static SFORMAT StateRegs[] = -{ - { vrc7.prg, 3, "PREG" }, - { vrc7.chr, 8, "CREG" }, - { &vrc7.mirr, 1, "MIRR" }, - - { 0 } -}; - -static void GENPWRAP(uint16 A, uint16 V) { - setprg8(A, V & 0x3F); -} - -static void GENCWRAP(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -static void GENMWRAP(uint8 V) { - vrc7.mirr = V; - - switch (vrc7.mirr & 3) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -void VRC7_FixPRG(void) { - setprg8r(0x10, 0x6000, 0); - VRC7_pwrap(0x8000, vrc7.prg[0]); - VRC7_pwrap(0xa000, vrc7.prg[1]); - VRC7_pwrap(0xc000, vrc7.prg[2]); - VRC7_pwrap(0xe000, ~0); -} - -void VRC7_FixCHR(void) { - int i; - for (i = 0; i < 8; i++) { - VRC7_cwrap(i << 10, vrc7.chr[i]); - } - - if (VRC7_mwrap) { - VRC7_mwrap(vrc7.mirr); - } -} - -DECLFW(VRC7_Write) { - int index; - switch (A & 0xF000) { - case 0x8000: - case 0x9000: - index = ((A >> 11) & 0x02) | ((A & vrc7_A0) ? 0x01 : 0x00); - switch (index) { - case 0x00: - case 0x01: - case 0x02: - vrc7.prg[index] = V; - VRC7_FixPRG(); - break; - default: - VRC7Sound_Write(A, V); - break; - } - break; - - case 0xA000: - case 0xB000: - case 0xC000: - case 0xD000: - index = ((A - 0xA000) >> 11) | ((A & vrc7_A0) ? 0x01 : 0x00); - vrc7.chr[index] = V; - VRC7_FixCHR(); - break; - - case 0xE000: - case 0xF000: - index = ((A >> 11) & 0x02) | ((A & vrc7_A0) ? 0x01 : 0x00); - switch (index) { - case 0x00: if (VRC7_mwrap) VRC7_mwrap(V); break; - case 0x01: VRCIRQ_Latch(V); break; - case 0x02: VRCIRQ_Control(V); break; - case 0x03: VRCIRQ_Acknowledge(); break; - } - break; - } -} - -void VRC7_Power(void) { - vrc7.prg[0] = 0; - vrc7.prg[1] = 1; - vrc7.prg[2] = ~1; - - vrc7.chr[0] = 0; - vrc7.chr[1] = 1; - vrc7.chr[2] = 2; - vrc7.chr[3] = 3; - vrc7.chr[4] = 4; - vrc7.chr[5] = 5; - vrc7.chr[6] = 6; - vrc7.chr[7] = 7; - - vrc7.mirr = 0; - - VRC7_FixPRG(); - VRC7_FixCHR(); - - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, VRC7_Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -void VRC7_Close(void) { -} - -static void StateRestore(int version) { - VRC7_FixPRG(); - VRC7_FixCHR(); -} - -void VRC7_Init(CartInfo *info, uint32 A0, uint32 A1) { - VRC7_pwrap = GENPWRAP; - VRC7_cwrap = GENCWRAP; - VRC7_mwrap = GENMWRAP; - - vrc7_A0 = A0; - vrc7_A1 = A1; - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - AddExState(StateRegs, ~0, 0, NULL); - - info->Power = VRC7_Power; - info->Close = VRC7_Close; - GameStateRestore = StateRestore; - - VRCIRQ_Init(TRUE); - MapIRQHook = VRCIRQ_CPUHook; - AddExState(&VRCIRQ_StateRegs, ~0, 0, 0); - - VRC7Sound_ESI(); - VRC7Sound_AddStateInfo(); -} diff --git a/src/mappers/hw/vrc7.h b/src/mappers/hw/vrc7.h deleted file mode 100644 index 4d0788052..000000000 --- a/src/mappers/hw/vrc7.h +++ /dev/null @@ -1,46 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _VRC7_H -#define _VRC7_H - -typedef struct __VRC7 { - uint8 prg[4]; - uint8 chr[8]; - uint8 mirr; -} VRC7; - -extern VRC7 vrc7; - -DECLFW(VRC7_Write); - -void VRC7_Power(void); -void VRC7_Close(void); - -void VRC7_Init(CartInfo *info, uint32 A0, uint32 A1); - -void VRC7_FixPRG(void); -void VRC7_FixCHR(void); - -extern void (*VRC7_pwrap)(uint16 A, uint16 V); -extern void (*VRC7_cwrap)(uint16 A, uint16 V); -extern void (*VRC7_mwrap)(uint8 V); - -#endif /* _VRC7_H */ diff --git a/src/mappers/hw/vrcirq.c b/src/mappers/hw/vrcirq.c deleted file mode 100644 index f0396a874..000000000 --- a/src/mappers/hw/vrcirq.c +++ /dev/null @@ -1,117 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "vrcirq.h" - -static int16 IRQPrescaler; -static uint8 IRQCount, IRQLatch, IRQd, IRQa, IRQm, IRQr; - -static uint8 IRQScanPos; -static uint8 IRQScanLut[3] = { 113, 113, 112 }; - -SFORMAT VRCIRQ_StateRegs[] = { - { &IRQPrescaler, 2, "PREC" }, - { &IRQCount, 1, "IRQC" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQd, 1, "IRQD" }, - { &IRQa, 1, "IRQA" }, - { &IRQm, 1, "IRQM" }, - { &IRQr, 1, "IRQR" }, - { &IRQScanPos, 1, "IPOS" }, - { 0 } -}; - -static void VRCIRQ_Clock(void) { - if (IRQCount == 0xFF) { - X6502_IRQBegin(FCEU_IQEXT); - IRQCount = IRQLatch; - } else { - IRQCount++; - } -} - -void VRCIRQ_CPUHook(int a) { - if (!IRQa) { - return; - } - - while (a--) { - if (IRQm) { /* cycle mode */ - VRCIRQ_Clock(); - } else { - if (IRQPrescaler >= IRQScanLut[IRQScanPos]) { - VRCIRQ_Clock(); - IRQScanPos++; - if (IRQScanPos >= 3) IRQScanPos = 0; - IRQPrescaler = 0; - } else { - IRQPrescaler++; - } - } - } -} - -void VRCIRQ_Latch(uint8 V) { - IRQLatch = V; -} - -void VRCIRQ_LatchNibble(uint8 V, uint8 highBit) { - if (highBit) { - IRQLatch &= 0x0F; - IRQLatch |= V << 4; - } else { - IRQLatch &= 0xF0; - IRQLatch |= V & 0xF; - } -} - -void VRCIRQ_Control(uint8 V) { - IRQd = (V & 0x01) == 0x01; - IRQa = (V & 0x02) == 0x02; - IRQm = (V & 0x04) == 0x04; - - if (IRQa) { - IRQCount = IRQLatch; - IRQPrescaler = 0; - IRQScanPos = 0; - } - - X6502_IRQEnd(FCEU_IQEXT); -} - -void VRCIRQ_Acknowledge(void) { - if (IRQr == TRUE) { - IRQa = IRQd; - } - - X6502_IRQEnd(FCEU_IQEXT); -} - -void VRCIRQ_Init(int irqRepeated) { - IRQPrescaler = 0; - IRQCount = 0; - IRQLatch = 0; - IRQd = 0; - IRQa = 0; - IRQm = 0; - IRQr = irqRepeated ? TRUE : FALSE; - IRQScanPos = 0; -} diff --git a/src/mappers/hw/vrcirq.h b/src/mappers/hw/vrcirq.h deleted file mode 100644 index 87f989729..000000000 --- a/src/mappers/hw/vrcirq.h +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _VRCIRQ_H -#define _VRCIRQ_H - -void VRCIRQ_Init(int irqRepeated); -void VRCIRQ_Latch(uint8 V); -void VRCIRQ_LatchNibble(uint8 V, uint8 highBit); -void VRCIRQ_Control(uint8 V); -void VRCIRQ_Acknowledge(void); -void VRCIRQ_CPUHook(int a); - -extern SFORMAT VRCIRQ_StateRegs[]; - -#endif /* _VRCIRQ_H */ diff --git a/src/mappers/m468/468.c b/src/mappers/m468/468.c deleted file mode 100644 index ee623d024..000000000 --- a/src/mappers/m468/468.c +++ /dev/null @@ -1,270 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 NewRisingSun - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* BlazePro CPLD-based multicarts - - Unsolved issue: how is CHR RAM write-protection triggered? - - Known problems: - - Forever Duo of NES 852-in-1 (rev1): - #A370 Time Lord: Hangs with glitchy status bar on NTSC and PAL but not Dendy - #A133 Galactic Crusader: Wrong mirroring - #A249 Mission Cobra: Wrong mirroring - - Legendary Games of NES 509-in-1: - #189 Huang Di Battle of Zhuolu: Wrong mirroring during intro - #227 Kid Niki Niki 2: Title screen animation flickers and looks strange - #234 Klax: Screen in wrong position during options screen - #365 Rocman X: Graphical garbage in waterfall (middle) level - #403 Star Wars: Blank tiles due to lack of CHR RAM write-protection - #404 The Empire Strikes Back: Blank tiles due to lack of CHR RAM write-protection - #460 Twin Dragons: Wrong mirroring - - Unlicensed Collection 142-in-1: - #59 Huang Di: Wrong mirroring during intro - #84 Ms. Pac-Man: Wrong mirroring - #102 Rocman X: Graphical garbage in waterfall (middle) level - #132 Trolls on Treasure Island: Wrong mirroring during map - - Unreleased Collection 73-in-1 (v1.01): - #38 Holy Diver: Wrong mirroring during first scene -*/ - -#include "mapinc.h" -#include "state.h" - -static uint8 submapper; -static uint8 eeprom[16], eep_clock, state, command, output; /* Some strange serial EEPROM */ - -static int prevSFEXINDEX; -extern int SFEXINDEX; -extern SFORMAT SFMDATA[64]; - -static uint8 mapper; /* 5700 MSB >>4 OR'd with submapper <<4 */ -static uint8 mapperFlags; /* 5700 LSB */ -static uint8 misc; /* 5601 */ -static uint8 misc2; /* 5702 */ -static void (*sync)(); - -static uint16 prgOR; -static uint8 prgAND; - -static uint8 regByte[16]; -static int16 regWord[9]; - -#include "468_mmc1.h" -#include "468_mmc24.h" -#include "468_mmc3.h" -#include "468_vrc1.h" -#include "468_vrc24.h" -#include "468_vrc3.h" -#include "468_vrc6.h" -#include "468_vrc7.h" -#include "468_fme7.h" -#include "468_discrete.h" -#include "468_cnrom.h" -#include "468_if12.h" -#include "468_lf36.h" -#include "468_nanjing.h" - -static SFORMAT stateRegs[] = { - { &mapper, 1, "SUP0" }, - { &mapperFlags, 1, "SUP1" }, - { &misc, 1, "SUP2" }, - { &misc2, 1, "SUP3" }, - { &prgOR, 2, "SUP4" }, - { &prgAND, 1, "SUP5" }, - { eeprom, 16,"EEPR" }, - { &eep_clock, 1, "EEP0" }, - { &state, 1, "EEP1" }, - { &command, 1, "EEP2" }, - { &output, 1, "EEP3" }, - { regByte, 16,"REGB" }, - { regWord, 16,"REGW" }, - { 0 } -}; - -static const uint16 lut509[512] ={ /* Strange look-up table, used only by Legendary Games of NES 509-in-1 */ - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 0, 1, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 4, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 2, 3, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 5, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 256, 6, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, - 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, - 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 512, 513, 514, 515, 516, 517 -}; - -void setPins(uint8 select, uint8 newClock, uint8 newData) { /* Serial EEPROM */ - if (select) - state =0; - else - if (!eep_clock && !!newClock) { - if (state <8) { - command =command <<1 | !!(newData)*1; - if (++state ==8 && (command &0xF0) !=0x50 && (command &0xF0) !=0xA0) state =0; - } else { - int mask =1 <<(15 -state); - int address =command &0x0F; - if ((command &0xF0) ==0xA0) { - eeprom[address] =eeprom[address] &~mask | !!(newData)*mask; - /* The "write" command also silently returns the content of a strange lookup table */ - output =!!(lut509[eeprom[0] | eeprom[1] | eeprom[2] <<8 &0x1FF] >>(address &1? 0: 8) &mask); - } else - if ((command &0xF0) ==0x50) - output =!!(eeprom[address] &mask); - - if (++state ==16) state =0; - } - } - eep_clock =newClock; -} - -static DECLFR(readReg); -static DECLFW(writeReg); -static void setMapper(uint8 clearRegs) { - int i; - if (clearRegs) { - for (i =0; i <16; i++) regByte[i] =0; - for (i =0; i < 8; i++) regWord[i] =0; - X6502_IRQEnd(FCEU_IQEXT); - } - SetReadHandler(0x5000, 0x5FFF, readReg); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, writeReg); - SetWriteHandler(0x6000, 0xFFFF, CartBW); - MapIRQHook = NULL; - PPU_hook = NULL; - GameHBIRQHook = NULL; - setprg8r(0x10, 0x6000, 0); - - switch(mapper) { /* 5700 MSB >>4 OR'd with submapper <<4 */ - case 0x00: case 0x01: case 0x32: MMC1_reset(clearRegs); break; - case 0x0A: MMC2_reset(clearRegs); break; - case 0x10: case 0x11: case 0x12: MMC3_reset(clearRegs); break; - case 0x08: MMC4_reset(clearRegs); break; - case 0x40: VRC1_reset(clearRegs); break; - case 0x20: case 0x21: case 0x22: case 0x23: VRC24_reset(clearRegs); break; - case 0x44: VRC3_reset(clearRegs); break; - case 0x30: case 0x31: VRC6_reset(clearRegs); break; - case 0x41: VRC7_reset(clearRegs); break; - case 0x07: LF36_reset(clearRegs); break; - case 0x50: FME7_reset(clearRegs); break; - case 0x0E: case 0x1E: NANJING_reset(clearRegs); break; - case 0x09: case 0x0B: case 0x17: case 0x37: UNROM_IF12_reset(clearRegs); break; - case 0x04: case 0x06: case 0x14: case 0x16: ANROM_BNROM_reset(clearRegs); break; - case 0x05: case 0x15: CNROM_BF9097_reset(clearRegs); break; - case 0x0C: case 0x0D: case 0x1C: case 0x1D: GNROM_reset(clearRegs); break; - default: break; - } - sync(); -} - -static DECLFR(readReg) { - switch(A) { - case 0x5301: case 0x5601: - return output? 0x80: 0x00; - default: - return 0xFF; - } -} - -static DECLFW(writeReg) { - switch(A) { - case 0x5301: - if (submapper ==0) setPins(!!(V &0x04), !!(V &0x02), !!(V &0x01)); - break; - case 0x5601: - if (~misc &0x80) { - misc =V; - if (submapper !=1) { - prgOR =prgOR &~0x2000 | V <<9 &0x2000; - sync(); - } - } - if (submapper ==1) setPins(!!(V &0x10), !!(V &0x02), !!(V &0x01)); - break; - case 0x5700: - mapper =V >>4 | submapper <<4; - mapperFlags =V &0xF; - prgOR =prgOR &~0x0010 | V <<4 &0x0010; - setMapper(1); - break; - case 0x5701: - prgOR =prgOR &~0x1FE0 | V <<5 &0x1FE0; - sync(); - break; - case 0x5702: - if (submapper ==1) { - misc2 =V; - prgOR =prgOR &~0x2000 | V <<9 &0x2000; - setMapper(0); /* The misc2 value is required for prgAND by MMC3 and UNROM */ - } - break; - } -} - -static void reset(void) { - mapper =submapper <<4; - mapperFlags =0x0F; - misc =0; - misc2 =0; - prgOR =0x7FF0; - eep_clock =command =output =1; - command =state =0; - setMapper(1); -} - -static void power(void) { - int i; - for (i =0; i <16; i++) eeprom[i] =0; - reset(); -} - -static void close(void) { - if (WRAM) - FCEU_gfree(WRAM); - WRAM = NULL; -} - -static void stateRestore(int version) { - setMapper(0); -} - -void Mapper468_Init(CartInfo *info) { - submapper =info->submapper; - info->Reset =reset; - info->Power =power; - info->Close =close; - GameStateRestore =stateRestore; - - WRAMSIZE =8192; - WRAM =(uint8*) FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - AddExState(stateRegs, ~0, 0, 0); - prevSFEXINDEX =SFEXINDEX; -} diff --git a/src/mappers/m468/468_cnrom.h b/src/mappers/m468/468_cnrom.h deleted file mode 100644 index 00dc2dcb8..000000000 --- a/src/mappers/m468/468_cnrom.h +++ /dev/null @@ -1,45 +0,0 @@ -#define CNROM_reg regByte - -static void CNROM_sync () { - int OR =prgOR >>1; - if (mapperFlags &2) { - setprg16(0x8000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF); - setprg16(0xC000, CNROM_reg[2] <<1 &0xE | mapperFlags &1 | OR &~0xF); - setchr8(CNROM_reg[0] &0x03); - } else { - OR >>=1; - setprg32(0x8000, CNROM_reg[2] &0x7 | OR &~0x7); - setchr8(CNROM_reg[0] &0x0F); - } - if (mapperFlags &8) - setmirror(mapperFlags &0x04? MI_H: MI_V); - else - setmirror(CNROM_reg[1] &0x10? MI_1: MI_0); -} - -static DECLFW(CNROM_writeReg) { - switch(A &0xE000) { - case 0x8000: case 0xA000: - CNROM_reg[0] =V; - break; - case 0xE000: - CNROM_reg[2] =V; - break; - } - sync(); -} - -static DECLFW(BF9097_writeMirroring) { - CNROM_reg[1] =V; - sync(); -} - -void CNROM_BF9097_reset(uint8 clearRegs) { /* This strange mapper is used for both (C)NROM games and FireHawk. What an absurd combination!*/ - sync =CNROM_sync; - SetWriteHandler(0x8000, 0xFFFF, CNROM_writeReg); - if (~mapperFlags &8) - SetWriteHandler(0x9000, 0x9FFF, BF9097_writeMirroring); - sync(); -} - -#undef CNROM_reg diff --git a/src/mappers/m468/468_discrete.h b/src/mappers/m468/468_discrete.h deleted file mode 100644 index e42c438b4..000000000 --- a/src/mappers/m468/468_discrete.h +++ /dev/null @@ -1,73 +0,0 @@ -#define latch regByte[0] - -static void ANROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2; - setprg32(0x8000, latch &AND | OR &~AND); - setchr8(0); - setmirror(latch &0x10? MI_1: MI_0); -} - -static void BNROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2; - setprg32(0x8000, latch &AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static void GNROM_sync () { - int AND =prgAND >>2; - int OR =prgOR >>2 | (mapperFlags &4? 2: 0); - setprg32(0x8000, latch >>4 &AND | OR &~AND); - setchr8(latch &0x0F); - setmirror(mapper &1? MI_H: MI_V); -} - -static void UNROM_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, latch &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(DISCRETE_writeLatch) { - latch =V; - sync(); -} - -static DECLFW(Portopia_writeLatch) { - DISCRETE_writeLatch(A, A ==0xA000 && V ==0x00? 0x06: V); /* Strange hack, needed to get #282 "Portopia Serial Murder Case" on 852-in-1 running */ -} - -static DECLFW(ColorDreams_writeLatch) { - DISCRETE_writeLatch(A, V >>4 &0xF | V <<4 &0xF0); /* Sswap nibbles to mimic GNROM */ -} - - -void ANROM_BNROM_reset(uint8 clearRegs) { - sync =mapperFlags &8? BNROM_sync: ANROM_sync; - prgAND =(mapper ==0x06 || mapper ==0x16)? 0x3F: mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, DISCRETE_writeLatch); - latch =0; - sync(); -} - -void GNROM_reset(uint8 clearRegs) { - sync =GNROM_sync; - prgAND =mapperFlags &8? 0x07: 0x0F; - SetWriteHandler(0x8000, 0xFFFF, misc &0x10 && mapper &~0x10? DISCRETE_writeLatch: ColorDreams_writeLatch); - latch =0; - sync(); -} - -void UNROM_reset(uint8 clearRegs) { - sync =UNROM_sync; - prgAND =mapper ==0x0B || misc2 &0x10? 0x3F: mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, mapper ==0x09 && mapperFlags ==0xE? Portopia_writeLatch: DISCRETE_writeLatch); - sync(); -} - -#undef latch diff --git a/src/mappers/m468/468_fme7.h b/src/mappers/m468/468_fme7.h deleted file mode 100644 index 0e3d31166..000000000 --- a/src/mappers/m468/468_fme7.h +++ /dev/null @@ -1,72 +0,0 @@ -#define FME7_reg regByte -#define FME7_index regByte[15] -#define FME7_counter regWord[0] - -static void FME7_sync() { - int AND =mapperFlags &8? 0xFF: 0x7F; - switch(FME7_reg[8] &0xC0) { - case 0x00: case 0x80: - setprg8(0x6000, FME7_reg[0x8] &prgAND | prgOR &~prgAND); - break; - case 0x40: - /* Open Bus */ - break; - case 0xC0: - setprg8r(0x10, 0x6000, 0); - break; - } - - setprg8(0x8000, FME7_reg[0x9] &prgAND | prgOR &~prgAND); - setprg8(0xA000, FME7_reg[0xA] &prgAND | prgOR &~prgAND); - setprg8(0xC000, FME7_reg[0xB] &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, FME7_reg[0x0] &AND); - setchr1(0x0400, FME7_reg[0x1] &AND); - setchr1(0x0800, FME7_reg[0x2] &AND); - setchr1(0x0C00, FME7_reg[0x3] &AND); - setchr1(0x1000, FME7_reg[0x4] &AND); - setchr1(0x1400, FME7_reg[0x5] &AND); - setchr1(0x1800, FME7_reg[0x6] &AND); - setchr1(0x1C00, FME7_reg[0x7] &AND); - setmirror(FME7_reg[0xC] &3 ^(FME7_reg[0xC] &2? 0: 1)); -} - -static DECLFW(FME7_writeIndex) { - FME7_index =V &0xF; -} - -static DECLFW(FME7_writeReg) { - switch(FME7_index) { - case 0xE: - FME7_counter =FME7_counter &0xFF00 |V; - break; - case 0xF: - FME7_counter =FME7_counter &0x00FF |V <<8; - break; - case 0xD: - X6502_IRQEnd(FCEU_IQEXT); - /* Falling through */ - default: - FME7_reg[FME7_index] =V; - sync(); - } -} - -static void FP_FASTAPASS(1) FME7_cpuCycle(int a) { - while (a--) { - if (FME7_reg[0xD] &0x80 && !--FME7_counter && FME7_reg[0xD] &0x01) X6502_IRQBegin(FCEU_IQEXT); - } -} - -void FME7_reset(uint8 clearRegs) { - sync =FME7_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - MapIRQHook =FME7_cpuCycle; - SetWriteHandler(0x8000, 0x9FFF, FME7_writeIndex); - SetWriteHandler(0xA000, 0xBFFF, FME7_writeReg); - sync(); -} - -#undef FME7_reg -#undef FME7_index -#undef FME7_counter diff --git a/src/mappers/m468/468_if12.h b/src/mappers/m468/468_if12.h deleted file mode 100644 index 12ec1e7fb..000000000 --- a/src/mappers/m468/468_if12.h +++ /dev/null @@ -1,31 +0,0 @@ -#define IF12_reg regByte - -static void IF12_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, IF12_reg[1] &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr8(IF12_reg[0] >>1 &0xF); - setmirror(IF12_reg[0] &1? MI_H: MI_V); -} - -static DECLFW(IF12_writeReg) { - IF12_reg[A >>14 &1] =V; - sync(); -} - -void IF12_reset(uint8 clearRegs) { - sync =IF12_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - SetWriteHandler(0x8000, 0xFFFF, IF12_writeReg); - sync(); -} - -void UNROM_IF12_reset(uint8 clearRegs) { - if (mapperFlags &8) - UNROM_reset(clearRegs); - else - IF12_reset(clearRegs); -} - -#undef IF12_reg diff --git a/src/mappers/m468/468_lf36.h b/src/mappers/m468/468_lf36.h deleted file mode 100644 index 73f9407f2..000000000 --- a/src/mappers/m468/468_lf36.h +++ /dev/null @@ -1,46 +0,0 @@ -#define LF36_prg regByte[0] -#define LF36_irq regByte[1] -#define LF36_counter regWord[0] - -static void LF36_sync () { - int OR =prgOR | mapperFlags &0x08; - setprg8(0x8000, 0x04 | OR); - setprg8(0xA000, 0x05 | OR); - setprg8(0xC000, LF36_prg &0x07 | OR); - setprg8(0xE000, 0x07 | OR); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(LF36_writeReg) { - switch (A &0xE000) { - case 0x8000: LF36_irq =0; break; - case 0xA000: LF36_irq =1; break; - case 0XE000: LF36_prg =V; sync(); break; - } -} - -static void FP_FASTAPASS(1) LF36_cpuCycle(int a) { - while (a--) { - if (LF36_irq) { - if (++LF36_counter &0x1000) - X6502_IRQBegin(FCEU_IQEXT); - else - X6502_IRQEnd(FCEU_IQEXT); - } else { - X6502_IRQEnd(FCEU_IQEXT); - LF36_counter =0; - } - } -} - -void LF36_reset(uint8 clearRegs) { - sync =LF36_sync; - MapIRQHook =LF36_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, LF36_writeReg); - sync(); -} - -#undef LF36_prg -#undef LF36_irq -#undef LF36_counter diff --git a/src/mappers/m468/468_mmc1.h b/src/mappers/m468/468_mmc1.h deleted file mode 100644 index b780ce210..000000000 --- a/src/mappers/m468/468_mmc1.h +++ /dev/null @@ -1,72 +0,0 @@ -#define MMC1_reg regByte -#define MMC1_control regByte[0] -#define MMC1_chr0 regByte[1] -#define MMC1_chr1 regByte[2] -#define MMC1_prg regByte[3] -#define MMC1_shift regByte[4] -#define MMC1_count regByte[5] -#define MMC1_filter regByte[6] - -static void MMC1_sync () { - int AND =prgAND >>1; - int OR =prgOR >>1 | (mapper &0x01? (MMC1_chr0 &0x10): (mapperFlags &0x06)); - if (MMC1_control &0x08) { /* 16 KiB mode */ - if (MMC1_control &0x04) { /* OR logic */ - setprg16(0x8000, MMC1_prg &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - } else { /* AND logic */ - setprg16(0x8000, 0 &AND | OR &~AND); - setprg16(0xC000, MMC1_prg &AND | OR &~AND); - } - } else - setprg32(0x8000, (MMC1_prg &AND | OR &~AND) >>1); - - AND =mapper &0x01? 0x0F: 0x1F; /* SUROM needs to have the upper PRG bank bit, which is in the CHR registers, masked off */ - if (MMC1_control &0x10) { /* 4 KiB mode */ - setchr4(0x0000, MMC1_chr0 &AND); - setchr4(0x1000, MMC1_chr1 &AND); - } else /* 8 KiB mode */ - setchr8(MMC1_chr0 >>1 &(AND >>1)); - - setmirror(MMC1_control &2? (MMC1_control &1? MI_H: MI_V): (MMC1_control &1? MI_1: MI_0)); -} - -static DECLFW(MMC1_writeReg) { - if (V &0x80) { - MMC1_shift =MMC1_count =0; - MMC1_control |=0x0C; - sync(); - } else - if (!MMC1_filter) { - MMC1_shift |=(V &1) <>13 &3] =MMC1_shift; - MMC1_count =0; - MMC1_shift =0; - sync(); - } - } - MMC1_filter =2; -} - -static void FP_FASTAPASS(1) MMC1_cpuCycle(int a) { - while (a--) if (MMC1_filter) MMC1_filter--; -} - -void MMC1_reset(uint8 clearRegs) { - sync =MMC1_sync; - MapIRQHook =MMC1_cpuCycle; - prgAND =mapperFlags &2? (mapperFlags &8? 0x07: 0x0F): 0x1F; - SetWriteHandler(0x8000, 0xFFFF, MMC1_writeReg); - if (clearRegs) MMC1_control =0x0C; - sync(); -} - -#undef MMC1_reg -#undef MMC1_control -#undef MMC1_chr0 -#undef MMC1_chr1 -#undef MMC1_prg -#undef MMC1_shift -#undef MMC1_count -#undef MMC1_filter diff --git a/src/mappers/m468/468_mmc24.h b/src/mappers/m468/468_mmc24.h deleted file mode 100644 index 398fcc09b..000000000 --- a/src/mappers/m468/468_mmc24.h +++ /dev/null @@ -1,67 +0,0 @@ -#define MMC24_reg regByte - -static void MMC2_sync() { - setprg8(0x8000, MMC24_reg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, 0xFD &prgAND | prgOR &~prgAND); - setprg8(0xC000, 0xFE &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]); - setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]); - setmirror(MMC24_reg[5] &1? MI_H: MI_V); -} - -static void MMC4_sync() { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, MMC24_reg[0] &AND | OR &~AND); - setprg16(0xC000, 0xFF &AND | OR &~AND); - setchr4(0x0000, MMC24_reg[1 +MMC24_reg[6]]); - setchr4(0x1000, MMC24_reg[3 +MMC24_reg[7]]); - setmirror(MMC24_reg[5] &1? MI_H: MI_V); -} - -static DECLFW(MMC24_writeReg) { - MMC24_reg[(A >>12) -0xA] =V; - sync(); -} - -static void FP_FASTAPASS(1) MMC24_ppuHook(uint32 A) { - uint8 l, h = A >> 8; - if (h >= 0x20 || ((h & 0xF) != 0xF)) return; - l = A & 0xF0; - if (h < 0x10) { - if (l == 0xD0) { - MMC24_reg[6] =0; - sync(); - } else if (l == 0xE0) { - MMC24_reg[6] =1; - sync(); - } - } else { - if (l == 0xD0) { - MMC24_reg[7] =0; - sync(); - } else if (l == 0xE0) { - MMC24_reg[7] =1; - sync(); - } - } -} - -void MMC2_reset(uint8 clearRegs) { - sync =MMC2_sync; - prgAND =0x0F; - PPU_hook =MMC24_ppuHook; - SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg); - sync(); -} - -void MMC4_reset(uint8 clearRegs) { - sync =MMC4_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - PPU_hook =MMC24_ppuHook; - SetWriteHandler(0xA000, 0xFFFF, MMC24_writeReg); - sync(); -} - -#undef MMC24_reg diff --git a/src/mappers/m468/468_mmc3.h b/src/mappers/m468/468_mmc3.h deleted file mode 100644 index f46c64d7a..000000000 --- a/src/mappers/m468/468_mmc3.h +++ /dev/null @@ -1,80 +0,0 @@ -#define MMC3_reg regByte -#define MMC3_index regByte[8] -#define MMC3_mirroring regByte[9] -#define MMC3_wram regByte[10] -#define MMC3_reload regByte[11] -#define MMC3_count regByte[12] -#define MMC3_irq regByte[13] -#define MMC3_lastReg regByte[14] - -static void MMC3_sync () { - int chrAND =mapper &0x01? 0xFF: 0x7F; - int OR =prgOR | (misc2 &1? 12: 0); - setprg8(0x8000 ^(MMC3_index <<8 &0x4000), MMC3_reg[6] &prgAND | OR &~prgAND); - setprg8(0xA000, MMC3_reg[7] &prgAND | OR &~prgAND); - setprg8(0xC000 ^(MMC3_index <<8 &0x4000), 0xFE &prgAND | OR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | OR &~prgAND); - setchr1(0x0000 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] &0xFE)&chrAND); - setchr1(0x0400 ^(MMC3_index <<5 &0x1000),(MMC3_reg[0] |0x01)&chrAND); - setchr1(0x0800 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] &0xFE)&chrAND); - setchr1(0x0C00 ^(MMC3_index <<5 &0x1000),(MMC3_reg[1] |0x01)&chrAND); - setchr1(0x1000 ^(MMC3_index <<5 &0x1000), MMC3_reg[2] &chrAND); - setchr1(0x1400 ^(MMC3_index <<5 &0x1000), MMC3_reg[3] &chrAND); - setchr1(0x1800 ^(MMC3_index <<5 &0x1000), MMC3_reg[4] &chrAND); - setchr1(0x1C00 ^(MMC3_index <<5 &0x1000), MMC3_reg[5] &chrAND); - - if (mapper &2) switch(MMC3_mirroring &3) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); break; - case 3: setmirror(MI_1); break; - } else - setmirror(MMC3_mirroring &1? MI_H: MI_V); -} - -static DECLFW(MMC3_writeReg) { - switch(A &0xE001) { - case 0x8000: MMC3_index =V; sync(); break; - case 0x8001: MMC3_reg[MMC3_index &7] =V; sync(); break; - case 0xA000: MMC3_mirroring =V; sync(); break; - case 0xA001: MMC3_wram =V; sync(); break; - case 0xC000: MMC3_reload =V; break; - case 0xC001: MMC3_count =0; break; - case 0xE000: MMC3_irq =0; X6502_IRQEnd(FCEU_IQEXT); break; - case 0xE001: MMC3_irq =1; break; - } -} - -static void MMC3_horizontalBlanking(void) { - MMC3_count =!MMC3_count? MMC3_reload: --MMC3_count; - if (!MMC3_count && MMC3_irq) X6502_IRQBegin(FCEU_IQEXT); -} - -static void FP_FASTAPASS(1) MMC3_ppuHook(uint32 A) { - A &=0x1FFF; - if (MMC3_index &0x80) A ^=0x1000; - if (A <0x1000) - MMC3_lastReg =A >>11; - else - MMC3_lastReg =(A >>10) -2; - if ((MMC3_mirroring &3) ==2) setmirror(MMC3_reg[MMC3_lastReg] &0x80? MI_1: MI_0); -} - -void MMC3_reset(uint8 clearRegs) { - sync =MMC3_sync; - GameHBIRQHook =MMC3_horizontalBlanking; - if (mapper &2) PPU_hook =MMC3_ppuHook; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? (misc2 &2? 0x07: 0x0F): 0x1F): 0x3F): 0x7F; - SetWriteHandler(0x8000, 0xFFFF, MMC3_writeReg); - MMC3_mirroring =1; /* "Legendary Games of NES' 509-in-1"'s menu runs as MMC3 with H mirroring and expects that setting to stay when running a mapper 206 game such as Legend of Valkyrie. */ - sync(); -} - -#undef MMC3_reg -#undef MMC3_index -#undef MMC3_mirroring -#undef MMC3_wram -#undef MMC3_reload -#undef MMC3_count -#undef MMC3_irq -#undef MMC3_lastReg diff --git a/src/mappers/m468/468_nanjing.h b/src/mappers/m468/468_nanjing.h deleted file mode 100644 index fa5f55517..000000000 --- a/src/mappers/m468/468_nanjing.h +++ /dev/null @@ -1,29 +0,0 @@ -#define NANJING_reg regByte - -static void NANJING_sync () { - setprg32(0x8000, NANJING_reg[2] <<4 &0x30 | NANJING_reg[0] &0x0F | (NANJING_reg[3] &4? 0x00: 0x03) | prgOR >>2); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(NANJING_writeReg) { - NANJING_reg[A >>8 &3] =V; - sync(); -} - -static void NANJING_horizontalBlanking(void) { - if (NANJING_reg[0] &0x80 && scanline <239) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on PA13 rises. This does not seem possible with the current PPU emulation however. */ - setchr4(0x0000, scanline >=127? 1: 0); - setchr4(0x1000, scanline >=127? 1: 0); - } else - setchr8(0); -} - -void NANJING_reset(uint8 clearRegs) { - sync =NANJING_sync; - GameHBIRQHook = NANJING_horizontalBlanking; - SetWriteHandler(0x5000, 0x53FF, NANJING_writeReg); - sync(); -} - -#undef NANJING_reg diff --git a/src/mappers/m468/468_vrc1.h b/src/mappers/m468/468_vrc1.h deleted file mode 100644 index 087e65eac..000000000 --- a/src/mappers/m468/468_vrc1.h +++ /dev/null @@ -1,25 +0,0 @@ -#define VRC1_reg regByte - -static void VRC1_sync () { - setprg8(0x8000, VRC1_reg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC1_reg[2] &prgAND | prgOR &~prgAND); - setprg8(0xC000, VRC1_reg[4] &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr4(0x0000, VRC1_reg[6] &0x0F | VRC1_reg[1] <<3 &0x10); - setchr4(0x1000, VRC1_reg[7] &0x0F | VRC1_reg[1] <<2 &0x10); - setmirror(VRC1_reg[1] &1? MI_H: MI_V); -} - -static DECLFW(VRC1_writeReg) { - VRC1_reg[A >>12 &7] =V; - sync(); -} - -void VRC1_reset(uint8 clearRegs) { - sync =VRC1_sync; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F; - SetWriteHandler(0x8000, 0xFFFF, VRC1_writeReg); - sync(); -} - -#undef VRC1_reg diff --git a/src/mappers/m468/468_vrc24.h b/src/mappers/m468/468_vrc24.h deleted file mode 100644 index 9916147bc..000000000 --- a/src/mappers/m468/468_vrc24.h +++ /dev/null @@ -1,92 +0,0 @@ -#define VRC24_prg regByte -#define VRC24_mirroring regByte[2] -#define VRC24_misc regByte[3] -#define VRC24_chr regWord -#define VRCIRQ_latch regByte[13] -#define VRCIRQ_mode regByte[14] -#define VRCIRQ_count regByte[15] -#define VRCIRQ_cycles regWord[8] - -static void VRC24_sync() { - setprg8(0x8000 ^(VRC24_misc <<13 &0x4000), VRC24_prg[0] &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC24_prg[1] &prgAND | prgOR &~prgAND); - setprg8(0xC000 ^(VRC24_misc <<13 &0x4000), 0xFE &prgAND | prgOR &~prgAND); - setprg8(0xE000, 0xFF &prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC24_chr[0]); - setchr1(0x0400, VRC24_chr[1]); - setchr1(0x0800, VRC24_chr[2]); - setchr1(0x0C00, VRC24_chr[3]); - setchr1(0x1000, VRC24_chr[4]); - setchr1(0x1400, VRC24_chr[5]); - setchr1(0x1800, VRC24_chr[6]); - setchr1(0x1C00, VRC24_chr[7]); - setmirror(VRC24_mirroring &3 ^(VRC24_mirroring &2? 0: 1)); -} - -static DECLFW(VRC24_writeReg) { - uint8 index; - A =A &0xF000 | (mapper &2? ((A &0xA? 1: 0) | (A &0x5? 2: 0)): ((A &0x5? 1: 0) | (A &0xA? 2: 0))); - switch (A &0xF000) { - case 0x8000: case 0xA000: - VRC24_prg[A >>13 &1] =V; - sync(); - break; - case 0x9000: - if (~A &2) - VRC24_mirroring =V & (mapper &1? 3: 1); - else - if (~A &1 && mapper &1) - VRC24_misc =V; - sync(); - break; - case 0xF000: - if (mapper &1) switch (A &3) { - case 0: VRCIRQ_latch =VRCIRQ_latch &0xF0 | V &0x0F; break; - case 1: VRCIRQ_latch =VRCIRQ_latch &0x0F | V <<4; break; - case 2: VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - break; - default: - index =(A -0xB000) >>11 | A >>1 &1; - if (A &1) - VRC24_chr[index] =VRC24_chr[index] & 0x0F | V <<4; - else - VRC24_chr[index] =VRC24_chr[index] &~0x0F | V &0x0F; - sync(); - break; - } -} - -static void FP_FASTAPASS(1) VRCIRQ_cpuCycle(int a) { - while (a--) { - if (VRCIRQ_mode &0x02 && (VRCIRQ_mode &0x04 || (VRCIRQ_cycles -=3) <=0)) { - if (~VRCIRQ_mode &0x04) VRCIRQ_cycles +=341; - if (!++VRCIRQ_count) { - VRCIRQ_count =VRCIRQ_latch; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -void VRC24_reset(uint8 clearRegs) { - sync =VRC24_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - if (mapper &1) MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC24_writeReg); - sync(); -} - -#undef VRC24_prg -#undef VRC24_mirroring -#undef VRC24_misc -#undef VRC24_chr diff --git a/src/mappers/m468/468_vrc3.h b/src/mappers/m468/468_vrc3.h deleted file mode 100644 index 5553b2356..000000000 --- a/src/mappers/m468/468_vrc3.h +++ /dev/null @@ -1,63 +0,0 @@ -#define VRC3_prg regByte[0] -#define VRC3_latch regWord[0] -#define VRC3_mode regByte[1] -#define VRC3_count regWord[1] - -static void VRC3_sync() { - int AND =prgAND >>1; - int OR =prgOR >>1; - setprg16(0x8000, VRC3_prg &AND | OR &~AND); - setprg16(0xC000, AND | OR &~AND); - setchr8(0); - setmirror(mapperFlags &4? MI_H: MI_V); -} - -static DECLFW(VRC3_writeReg) { - int shift; - switch(A &0xF000) { - case 0x8000: case 0x9000: case 0xA000: case 0xB000: - V &=0xF; - shift =A >>10 &0xC; - VRC3_latch =VRC3_latch &~(0xF <>1; - int OR =prgOR >>1; - setprg16(0x8000, VRC6_prg16 & AND | OR & ~AND); - setprg8(0xC000, VRC6_prg8 &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC6_chr[0]); - setchr1(0x0400, VRC6_chr[1]); - setchr1(0x0800, VRC6_chr[2]); - setchr1(0x0C00, VRC6_chr[3]); - setchr1(0x1000, VRC6_chr[4]); - setchr1(0x1400, VRC6_chr[5]); - setchr1(0x1800, VRC6_chr[6]); - setchr1(0x1C00, VRC6_chr[7]); - setmirror((VRC6_misc &0xC ^(VRC6_misc &0x8? 0: 0x4)) >>2); -} - -static DECLFW(VRC6_writeReg) { - uint8 index; - switch (A &0xF003) { - case 0x8000: case 0x8001: case 0x8002: case 0x8003: - VRC6_prg16 =V; - sync(); - break; - case 0xB003: - VRC6_misc =V; - sync(); - break; - case 0xC000: case 0xC001: case 0xC002: case 0xC003: - VRC6_prg8 =V; - sync(); - break; - case 0xD000: case 0xD001: case 0xD002: case 0xD003: case 0xE000: case 0xE001: case 0xE002: case 0xE003: - index =(A -0xD000) >>10 | A &3; - VRC6_chr[index] =V; - sync(); - break; - case 0xF000: - VRCIRQ_latch =V; - break; - case 0xF001: - VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xF002: - VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -void VRC6_reset(uint8 clearRegs) { - sync =VRC6_sync; - prgAND =mapperFlags &2? 0x0F: 0x1F; - MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC6_writeReg); - sync(); -} - -#undef VRC6_chr -#undef VRC6_prg16 -#undef VRC6_prg8 -#undef VRC6_misc diff --git a/src/mappers/m468/468_vrc7.h b/src/mappers/m468/468_vrc7.h deleted file mode 100644 index 24e5938e7..000000000 --- a/src/mappers/m468/468_vrc7.h +++ /dev/null @@ -1,82 +0,0 @@ -#define VRC7_chr regByte -#define VRC7_prg0 regByte[8] -#define VRC7_prg1 regByte[9] -#define VRC7_prg2 regByte[10] -#define VRC7_misc regByte[11] - -static void VRC7_sync() { - setprg8(0x8000, VRC7_prg0 &prgAND | prgOR &~prgAND); - setprg8(0xA000, VRC7_prg1 &prgAND | prgOR &~prgAND); - setprg8(0xC000, VRC7_prg2 &prgAND | prgOR &~prgAND); - setprg8(0xE000, prgAND | prgOR &~prgAND); - setchr1(0x0000, VRC7_chr[0]); - setchr1(0x0400, VRC7_chr[1]); - setchr1(0x0800, VRC7_chr[2]); - setchr1(0x0C00, VRC7_chr[3]); - setchr1(0x1000, VRC7_chr[4]); - setchr1(0x1400, VRC7_chr[5]); - setchr1(0x1800, VRC7_chr[6]); - setchr1(0x1C00, VRC7_chr[7]); - setmirror(VRC7_misc &3 ^(VRC7_misc &2? 0: 1)); -} - -static DECLFW(VRC7_writeReg) { - uint8 index; - A =A &0xF000 | (A &0x18? 1: 0) | (A &0x20? 2: 0); - switch (A &0xF003) { - case 0x8000: - VRC7_prg0 =V; - sync(); - break; - case 0x8001: - VRC7_prg1 =V; - sync(); - break; - case 0x9000: - VRC7_prg2 =V; - sync(); - break; - case 0x9001: case 0x9002: - /* sound */ - break; - case 0xA000: case 0xA001: case 0xB000: case 0xB001: case 0xC000: case 0xC001: case 0xD000: case 0xD001: - index =(A -0xA000) >>11 | A &1; - VRC7_chr[index] =V; - sync(); - break; - case 0xE000: - VRC7_misc =V; - sync(); - break; - case 0xE001: - VRCIRQ_latch =V; - break; - case 0xF000: - VRCIRQ_mode =V; - if (VRCIRQ_mode &0x02) { - VRCIRQ_count =VRCIRQ_latch; - VRCIRQ_cycles =341; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xF001: - VRCIRQ_mode =VRCIRQ_mode &~0x02 | VRCIRQ_mode <<1 &0x02; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -void VRC7_reset(uint8 clearRegs) { - sync =VRC7_sync; - prgAND =mapperFlags &8? (mapperFlags &4? (mapperFlags &2? 0x0F: 0x1F): 0x3F): 0x7F; - MapIRQHook =VRCIRQ_cpuCycle; - SetWriteHandler(0x8000, 0xFFFF, VRC7_writeReg); - sync(); -} - -#undef VRC7_chr -#undef VRC7_prg0 -#undef VRC7_prg1 -#undef VRC7_prg2 -#undef VRC7_misc - diff --git a/src/mappers/mapinc.h b/src/mappers/mapinc.h deleted file mode 100644 index 187e37863..000000000 --- a/src/mappers/mapinc.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _MAPINC_H -#define _MAPINC_H - -#include "../fceu-types.h" -#include "../x6502.h" -#include "../fceu.h" -#include "../ppu.h" -#include "../fceu-memory.h" -#include "../sound.h" -#include "../state.h" -#include "../cart.h" -#include "../cheat.h" -#include "../unif.h" -#include "../ines.h" -#include "../nsf.h" -#include "../x6502.h" -#include -#include - -#define CPU_OPENBUS X.DB - -#define PRG_PAGE_SIZE (16 * 1024) -#define CHR_PAGE_SIZE ( 8 * 1024) - -#define PRG_ROM_PTR ROM -#define PRG_ROM_SIZE (ROM_size * PRG_PAGE_SIZE) - -#define CHR_ROM_PTR VROM -#define CHR_ROM_SIZE (VROM_size * CHR_PAGE_SIZE) - -#define PRG_BANK_COUNT(x) (PRG_ROM_SIZE / ((x) * 1024)) -#define CHR_BANK_COUNT(x) (CHR_ROM_SIZE / ((x) * 1024)) - -#define MISC_ROM_PTR miscROM -#define MISC_ROM_SIZE miscROMSIZE - -#endif /* _MAPINC_H */ diff --git a/src/mappers/mapper.c b/src/mappers/mapper.c deleted file mode 100644 index ad210bfec..000000000 --- a/src/mappers/mapper.c +++ /dev/null @@ -1,10 +0,0 @@ -#include "mapinc.h" - -uint8 *WRAM; -uint32 WRAMSIZE; - -uint8 *CHRRAM; -uint32 CHRRAMSIZE; - -uint8 *miscROM; -uint32 miscROMSIZE; diff --git a/src/mappers/mapper000.c b/src/mappers/mapper000.c deleted file mode 100644 index 82f210eec..000000000 --- a/src/mappers/mapper000.c +++ /dev/null @@ -1,73 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static void NROMClose(void) { -} - -static void NROMPower(void) { - if (PRG_ROM_SIZE == (48 * 1024)) { /* NROM-368 */ - setprg16(0x4000, 0); - setprg16(0x8000, 1); - setprg16(0xC000, 2); - SetReadHandler(0x4800, 0xFFFF, CartBR); - } else { - setprg32(0x8000, 0); - SetReadHandler(0x8000, 0xFFFF, CartBR); - - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, 0); /* Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB */ - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } - } - - setchr8(0); -} - -void Mapper000_Init(CartInfo *info) { - info->Power = NROMPower; - info->Close = NROMClose; - - WRAMSIZE = 8192; - - if (info->submapper) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } - - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } - - if ((info->CRC32 == 0x4233B70E) || ((info->PRGCRC32 == 0x17E013A2) && CHR_ROM_SIZE)) { - /* BADDUMP: A variant of Wild Ball with chrrom when its suppose to use chrram */ - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 1); - } -} diff --git a/src/mappers/mapper001.c b/src/mappers/mapper001.c deleted file mode 100644 index 3a18b3758..000000000 --- a/src/mappers/mapper001.c +++ /dev/null @@ -1,67 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc1.h" - -static int DetectMMC1WRAMSize(CartInfo *info, int *saveRAM) { - int workRAM = 8; - - if (info->iNES2) { - workRAM = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; - *saveRAM = info->PRGRamSaveSize / 1024; - /* we only support sizes between 8K and 32K */ - if (workRAM > 0 && workRAM < 8) - workRAM = 8; - if (workRAM > 32) - workRAM = 32; - if (*saveRAM > 0 && *saveRAM < 8) - *saveRAM = 8; - if (*saveRAM > 32) - *saveRAM = 32; - /* save ram cannot be bigger than workram */ - if (*saveRAM > workRAM) { - *saveRAM = workRAM; - workRAM = 0; - } - } else if (info->battery) { - *saveRAM = 8; - } - if (workRAM > 8) { - FCEU_printf(" >8KB external WRAM present. Use NES 2.0 if you hack the ROM image.\n"); - } - return workRAM; -} - -static void M001PW(uint16 A, uint16 V) { - if (iNESCart.submapper == 5) { - setprg32(0x8000, 0); - } else { - setprg16(A, (MMC1_GetCHRBank(0) & 0x10) | (V & 0x0F)); - } -} - -void Mapper001_Init(CartInfo *info) { - int bs = 0; - int ws = DetectMMC1WRAMSize(info, &bs); - MMC1_Init(info, ws, bs); - MMC1_pwrap = M001PW; - mmc1_type = (info->submapper == 3) ? MMC1A : MMC1B; -} diff --git a/src/mappers/mapper002.c b/src/mappers/mapper002.c deleted file mode 100644 index 7c329069c..000000000 --- a/src/mappers/mapper002.c +++ /dev/null @@ -1,34 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, latch.data); - setprg16(0xC000, ~0); - setchr8(0); -} - -void Mapper002_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, (info->submapper == 2)); -} diff --git a/src/mappers/mapper003.c b/src/mappers/mapper003.c deleted file mode 100644 index 9a460a310..000000000 --- a/src/mappers/mapper003.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); /* Hayauchy IGO uses 2Kb or RAM */ - setprg32(0x8000, 0); - setchr8(latch.data); -} - -void Mapper003_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, (info->submapper == 2)); -} diff --git a/src/mappers/mapper004.c b/src/mappers/mapper004.c deleted file mode 100644 index 4376fe2e8..000000000 --- a/src/mappers/mapper004.c +++ /dev/null @@ -1,70 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" -#include "mmc6.h" - -static void M004PW(uint16 A, uint16 V) { - setprg8(A, V & 0xFF); -} - -static void M004CW(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -void Mapper004_Init(CartInfo *info) { - int ws = 8; - - if (info->submapper == 1) { - MMC6_Init(info); - return; - } - - if (info->submapper == 5) { - Mapper249_Init(info); - return; - } - - if (!info->iNES2) { - if ((info->CRC32 == 0x93991433) || (info->CRC32 == 0xaf65aa84)) { - FCEU_printf( - "Low-G-Man can not work normally in the iNES format.\nThis game has been recognized by its CRC32 " - "value, and the appropriate changes will be made so it will run.\nIf you wish to hack this game, " - "you should use the UNIF format for your hack.\n\n"); - ws = 0; - } - } else { - ws = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; - } - - if ((info->submapper == 4) || (info->CRC32 == 0x97b6cb19)) { - isRevB = 0; /* MMC3A */ - } - - if ((info->CRC32 == 0x762653B1) && (ws < 8)) { - /* Mickey Mouse III - Dream Balloon [NikcDC v1.1] */ - ws = 8; - } - - MMC3_Init(info, ws, info->battery); - MMC3_pwrap = M004PW; - MMC3_cwrap = M004CW; -} diff --git a/src/mappers/mapper005.c b/src/mappers/mapper005.c deleted file mode 100644 index 8af73d339..000000000 --- a/src/mappers/mapper005.c +++ /dev/null @@ -1,807 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* None of this code should use any of the iNES bank switching wrappers. */ - -#include "mapinc.h" -#include "mmc5sound.h" - -static INLINE void MMC5SPRVROM_BANK1(uint32 A, uint32 V) { - if (CHRptr[0]) { - V &= CHRmask1[0]; - MMC5SPRVPage[A >> 10] = &CHRptr[0][V << 10] - A; - } -} - -static INLINE void MMC5BGVROM_BANK1(uint32 A, uint32 V) { - if (CHRptr[0]) { - V &= CHRmask1[0]; MMC5BGVPage[A >> 10] = &CHRptr[0][V << 10] - A; - } -} - -static INLINE void MMC5SPRVROM_BANK2(uint32 A, uint32 V) { - if (CHRptr[0]) { - V &= CHRmask2[0]; MMC5SPRVPage[A >> 10] = MMC5SPRVPage[(A >> 10) + 1] = &CHRptr[0][V << 11] - A; - } -} - -static INLINE void MMC5BGVROM_BANK2(uint32 A, uint32 V) { - if (CHRptr[0]) { - V &= CHRmask2[0]; MMC5BGVPage[A >> 10] = MMC5BGVPage[(A >> 10) + 1] = &CHRptr[0][V << 11] - A; - } -} - -static INLINE void MMC5SPRVROM_BANK4(uint32 A, uint32 V) { - if (CHRptr[0]) { - V &= CHRmask4[0]; MMC5SPRVPage[A >> 10] = MMC5SPRVPage[(A >> 10) + 1] = MMC5SPRVPage[(A >> 10) + 2] = MMC5SPRVPage[(A >> 10) + 3] = &CHRptr[0][V << 12] - A; - } -} - -static INLINE void MMC5BGVROM_BANK4(uint32 A, uint32 V) { - if (CHRptr[0]) { - V &= CHRmask4[0]; MMC5BGVPage[A >> 10] = MMC5BGVPage[(A >> 10) + 1] = MMC5BGVPage[(A >> 10) + 2] = MMC5BGVPage[(A >> 10) + 3] = &CHRptr[0][V << 12] - A; - } -} - -static INLINE void MMC5SPRVROM_BANK8(uint32 V) { - if (CHRptr[0]) { - V &= CHRmask8[0]; MMC5SPRVPage[0] = MMC5SPRVPage[1] = MMC5SPRVPage[2] = MMC5SPRVPage[3] = MMC5SPRVPage[4] = MMC5SPRVPage[5] = MMC5SPRVPage[6] = MMC5SPRVPage[7] = &CHRptr[0][V << 13]; - } -} - -static INLINE void MMC5BGVROM_BANK8(uint32 V) { - if (CHRptr[0]) { - V &= CHRmask8[0]; MMC5BGVPage[0] = MMC5BGVPage[1] = MMC5BGVPage[2] = MMC5BGVPage[3] = MMC5BGVPage[4] = MMC5BGVPage[5] = MMC5BGVPage[6] = MMC5BGVPage[7] = &CHRptr[0][V << 13]; - } -} - -static uint8 PRGBanks[4]; -static uint8 WRAMPage; -static uint16 CHRBanksA[8], CHRBanksB[4]; -static uint8 WRAMMaskEnable[2]; -uint8 mmc5ABMode; /* A=0, B=1 */ - -static uint8 IRQScanline, IRQEnable; -static uint8 CHRMode, NTAMirroring, NTFill, ATFill; - -static uint8 MMC5IRQR; -static uint8 MMC5LineCounter; -static uint8 mmc5psize, mmc5vsize; -static uint8 mul[2]; - -static uint8 *MMC5fill = NULL; -static uint8 *ExRAM = NULL; -static uint8 MMC5battery = 0; - -static uint8 MMC5WRAMsize; /* configuration, not state */ -static uint8 MMC5WRAMIndex[8]; /* configuration, not state */ - -static uint8 MMC5ROMWrProtect[4]; -static uint8 MMC5MemIn[5]; - -static SFORMAT MMC5_StateRegs[] = { - { PRGBanks, 4, "PREG" }, - { CHRBanksA, 16, "CHRA" }, - { CHRBanksB, 8, "CHRB" }, - { &WRAMPage, 1, "WRMP" }, - { WRAMMaskEnable, 2, "WRMK" }, - { &mmc5ABMode, 1, "ABMD" }, - { &IRQScanline, 1, "IRQS" }, - { &IRQEnable, 1, "IRQE" }, - { &CHRMode, 1, "CHRM" }, - { &NTAMirroring, 1, "NTAM" }, - { &NTFill, 1, "NTFL" }, - { &ATFill, 1, "ATFL" }, - { &MMC5IRQR, 1, "IRQR" }, - { &MMC5LineCounter, 1, "LCTR" }, - { &mmc5psize, 1, "PSIZ" }, - { &mmc5vsize, 1, "VSIZ" }, - { mul, 2, "MUL0" }, - { MMC5ROMWrProtect, 4, "PROT" }, - { MMC5MemIn, 5, "MEMN" }, - - { 0 } -}; - -uint8 *MMC5BGVRAMADR(uint32 A) { -#ifdef NEWPPU - if (newppu) { - if (Sprite16) { - bool isPattern = PPUON != 0; - if (ppuphase == PPUPHASE_OBJ && isPattern) { - return &ABANKS[(A) >> 10][(A)]; - } - if (ppuphase == PPUPHASE_BG && isPattern) { - return &BBANKS[(A) >> 10][(A)]; - } else if (mmc5ABMode == 0) { - return &ABANKS[(A) >> 10][(A)]; - } else { - return &BBANKS[(A) >> 10][(A)]; - } - } else { - return &ABANKS[(A) >> 10][(A)]; - } - } -#endif /* NEWPPU */ - - if (!Sprite16) { - if (mmc5ABMode == 0) { - return &ABANKS[(A) >> 10][(A)]; - } else { - return &BBANKS[(A) >> 10][(A)]; - } - } else { - return &BBANKS[(A) >> 10][(A)]; - } -} - -extern uint8 PALRAM[0x20]; -extern uint8 UPALRAM[0x03]; -extern uint32 NTRefreshAddr; - -#ifdef NEWPPU -static void mmc5_PPUWrite(uint32 A, uint8 V) { - uint32 tmp = A; - - if (tmp >= 0x3F00) { - if (!(tmp & 3)) { - if (!(tmp & 0xC)) { - PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F; - PALRAM[0x10] = PALRAM[0x14] = PALRAM[0x18] = PALRAM[0x1C] = V & 0x3F; - } else { - UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F; - } - } else { - PALRAM[tmp & 0x1F] = V & 0x3F; - } - } else if (tmp < 0x2000) { - if (PPUCHRRAM & (1 << (tmp >> 10))) { - VPage[tmp >> 10][tmp] = V; - } - } else { - if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) { - vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; - } - } -} - -uint8 mmc5_PPURead(uint32 A) { - bool split = false; - - if (newppu) { - if ((MMC5HackSPMode & 0x80) && !(MMC5HackCHRMode & 2)) { - int target = MMC5HackSPMode & 0x1f; - int side = MMC5HackSPMode & 0x40; - int ht = NTRefreshAddr & 31; - - if (side == 0) { - if (ht < target) { - split = true; - } - } else { - if (ht >= target) { - split = true; - } - } - } - } - - if (A < 0x2000) { - if (Sprite16) { - bool isPattern = !!PPUON; - - if (ppuphase == PPUPHASE_OBJ && isPattern) { - return ABANKS[(A) >> 10][(A)]; - } - if (ppuphase == PPUPHASE_BG && isPattern) { - if (split) { - return MMC5HackVROMPTR[MMC5HackSPPage * 0x1000 + (A & 0xFFF)]; - } - - /* uhhh call through to this more sophisticated function, only - * if it's really needed? we should probably reuse it - * completely, if we can - */ - if (MMC5HackCHRMode == 1) { - return *FCEUPPU_GetCHR(A, NTRefreshAddr); - } - - return BBANKS[(A) >> 10][(A)]; - } else if (mmc5ABMode == 0) { - return ABANKS[(A) >> 10][(A)]; - } else { - return BBANKS[(A) >> 10][(A)]; - } - } else { - if (ppuphase == PPUPHASE_BG && ScreenON) { - if (split) { - return MMC5HackVROMPTR[MMC5HackSPPage * 0x1000 + (A & 0xFFF)]; - } - - /* uhhh call through to this more sophisticated function, only - * if it's really needed? we should probably reuse it - * completely, if we can - */ - if (MMC5HackCHRMode == 1) { - return *FCEUPPU_GetCHR(A, NTRefreshAddr); - } - } - - return ABANKS[(A) >> 10][(A)]; - } - } else { - if (split) { - static const int kHack = -1; /* dunno if theres science to this or if it just fixes SDF - (cant be bothered to think about it) */ - int linetile = (newppu_get_scanline() + kHack) / 8 + MMC5HackSPScroll; - - /* REF NT: return 0x2000 | (v << 0xB) | (h << 0xA) | (vt << 5) | ht; - REF AT: return 0x2000 | (v << 0xB) | (h << 0xA) | 0x3C0 | ((vt & - 0x1C) << 1) | ((ht & 0x1C) >> 2); */ - - if ((A & 0x3FF) >= 0x3C0) { - A &= ~(0x1C << 1); /* mask off VT */ - A |= (linetile & 0x1C) << 1; /* mask on adjusted VT */ - return ExRAM[A & 0x3FF]; - } else { - A &= ~((0x1F << 5) | (1 << 0xB)); /* mask off VT and V */ - A |= (linetile & 31) << 5; /* mask on adjusted VT (V doesnt make */ - /* any sense, I think) */ - return ExRAM[A & 0x3FF]; - } - } - - if (MMC5HackCHRMode == 1) { - if ((A & 0x3FF) >= 0x3C0) { - uint8 byte = ExRAM[NTRefreshAddr & 0x3ff]; - - /* get attribute part and paste it 4x across the byte */ - byte >>= 6; - byte *= 0x55; - return byte; - } - } - - return vnapage[(A >> 10) & 0x3][A & 0x3FF]; - } -} -#endif /* NEWPPU */ - -static void BuildWRAMSizeTable(void) { - int x; - for (x = 0; x < 8; x++) { - switch (MMC5WRAMsize) { - case 0: MMC5WRAMIndex[x] = 255; break; /* X,X,X,X,X,X,X,X */ - case 1: MMC5WRAMIndex[x] = (x > 3) ? 255 : 0; break; /* 0,0,0,0,X,X,X,X */ - case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; /* 0,0,0,0,1,1,1,1 */ - case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; /* 0,1,2,3,X,X,X,X */ - case 8: MMC5WRAMIndex[x] = x; break; /* 0,1,2,3,4,5,6,7 */ - } - } -} - -static void MMC5CHRA(void) { - int x; - switch (mmc5vsize & 3) { - case 0: - setchr8(CHRBanksA[7]); - MMC5SPRVROM_BANK8(CHRBanksA[7]); - break; - case 1: - setchr4(0x0000, CHRBanksA[3]); - setchr4(0x1000, CHRBanksA[7]); - MMC5SPRVROM_BANK4(0x0000, CHRBanksA[3]); - MMC5SPRVROM_BANK4(0x1000, CHRBanksA[7]); - break; - case 2: - setchr2(0x0000, CHRBanksA[1]); - setchr2(0x0800, CHRBanksA[3]); - setchr2(0x1000, CHRBanksA[5]); - setchr2(0x1800, CHRBanksA[7]); - MMC5SPRVROM_BANK2(0x0000, CHRBanksA[1]); - MMC5SPRVROM_BANK2(0x0800, CHRBanksA[3]); - MMC5SPRVROM_BANK2(0x1000, CHRBanksA[5]); - MMC5SPRVROM_BANK2(0x1800, CHRBanksA[7]); - break; - case 3: - for (x = 0; x < 8; x++) { - setchr1(x << 10, CHRBanksA[x]); - MMC5SPRVROM_BANK1(x << 10, CHRBanksA[x]); - } - break; - } -} - -static void MMC5CHRB(void) { - int x; - switch (mmc5vsize & 3) { - case 0: - setchr8(CHRBanksB[3]); - MMC5BGVROM_BANK8(CHRBanksB[3]); - break; - case 1: - setchr4(0x0000, CHRBanksB[3]); - setchr4(0x1000, CHRBanksB[3]); - MMC5BGVROM_BANK4(0x0000, CHRBanksB[3]); - MMC5BGVROM_BANK4(0x1000, CHRBanksB[3]); - break; - case 2: - setchr2(0x0000, CHRBanksB[1]); - setchr2(0x0800, CHRBanksB[3]); - setchr2(0x1000, CHRBanksB[1]); - setchr2(0x1800, CHRBanksB[3]); - MMC5BGVROM_BANK2(0x0000, CHRBanksB[1]); - MMC5BGVROM_BANK2(0x0800, CHRBanksB[3]); - MMC5BGVROM_BANK2(0x1000, CHRBanksB[1]); - MMC5BGVROM_BANK2(0x1800, CHRBanksB[3]); - break; - case 3: - for (x = 0; x < 8; x++) { - setchr1(x << 10, CHRBanksB[x & 3]); - MMC5BGVROM_BANK1(x << 10, CHRBanksB[x & 3]); - } - break; - } -} - -static void MMC5WRAM(uint32 A, uint32 V) { - V = MMC5WRAMIndex[V & 7]; - if (V != 255) { - setprg8r(0x10, A, V); - FCEU_CheatAddRAM(8, 0x6000, (WRAM + ((V * 8192) & (WRAMSIZE - 1)))); - MMC5MemIn[(A - 0x6000) >> 13] = 1; - } else { - MMC5MemIn[(A - 0x6000) >> 13] = 0; - } -} - -static void MMC5PRG(void) { - int x; - switch (mmc5psize & 3) { - case 0: - MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1; - setprg32(0x8000, ((PRGBanks[3] & 0x7F) >> 2)); - for (x = 0; x < 4; x++) { - MMC5MemIn[1 + x] = 1; - } - break; - case 1: - if (PRGBanks[1] & 0x80) { - MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 1; - setprg16(0x8000, (PRGBanks[1] >> 1)); - MMC5MemIn[1] = MMC5MemIn[2] = 1; - } else { - MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0; - MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE); - MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1); - } - MMC5MemIn[3] = MMC5MemIn[4] = 1; - MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1; - setprg16(0xC000, (PRGBanks[3] & 0x7F) >> 1); - break; - case 2: - if (PRGBanks[1] & 0x80) { - MMC5MemIn[1] = MMC5MemIn[2] = 1; - MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 1; - setprg16(0x8000, (PRGBanks[1] & 0x7F) >> 1); - } else { - MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0; - MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE); - MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1); - } - if (PRGBanks[2] & 0x80) { - MMC5ROMWrProtect[2] = 1; - MMC5MemIn[3] = 1; - setprg8(0xC000, PRGBanks[2] & 0x7F); - } else { - MMC5ROMWrProtect[2] = 0; - MMC5WRAM(0xC000, PRGBanks[2] & 7); - } - MMC5MemIn[4] = 1; - MMC5ROMWrProtect[3] = 1; - setprg8(0xE000, PRGBanks[3] & 0x7F); - break; - case 3: - for (x = 0; x < 3; x++) { - if (PRGBanks[x] & 0x80) { - MMC5ROMWrProtect[x] = 1; - setprg8(0x8000 + (x << 13), PRGBanks[x] & 0x7F); - MMC5MemIn[1 + x] = 1; - } else { - MMC5ROMWrProtect[x] = 0; - MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & 7); - } - } - MMC5MemIn[4] = 1; - MMC5ROMWrProtect[3] = 1; - setprg8(0xE000, PRGBanks[3] & 0x7F); - break; - } -} - -static void MMC5MIRR(void) { - int x; - for (x = 0; x < 4; x++) { - switch ((NTAMirroring >> (x << 1)) & 3) { - case 0: PPUNTARAM |= 1 << x; vnapage[x] = NTARAM; break; - case 1: PPUNTARAM |= 1 << x; vnapage[x] = NTARAM + 0x400; break; - case 2: PPUNTARAM |= 1 << x; vnapage[x] = ExRAM; break; - case 3: PPUNTARAM &= ~(1 << x); vnapage[x] = MMC5fill; break; - } - } -} - -DECLFW(Mapper5_write) { - switch (A) { - case 0x5100: - mmc5psize = V; - MMC5PRG(); - break; - case 0x5101: - mmc5vsize = V; - if (!mmc5ABMode) { - MMC5CHRB(); - MMC5CHRA(); - } else { - MMC5CHRA(); - MMC5CHRB(); - } - break; - case 0x5102: - WRAMMaskEnable[0] = V; - break; - case 0x5103: - WRAMMaskEnable[1] = V; - break; - case 0x5104: - CHRMode = V; - MMC5HackCHRMode = V & 3; - break; - case 0x5105: - NTAMirroring = V; - MMC5MIRR(); - break; - case 0x5106: - if (V != NTFill) { - FCEU_dwmemset(MMC5fill, (V | (V << 8) | (V << 16) | (V << 24)), 0x3c0); - } - NTFill = V; - break; - case 0x5107: - if (V != ATFill) { - unsigned char moop = V | (V << 2) | (V << 4) | (V << 6); - FCEU_dwmemset(MMC5fill + 0x3c0, moop | (moop << 8) | (moop << 16) | (moop << 24), 0x40); - } - ATFill = V; - break; - case 0x5113: - WRAMPage = V; - MMC5WRAM(0x6000, V & 7); - break; - case 0x5114: - case 0x5115: - case 0x5116: - case 0x5117: - PRGBanks[A & 3] = V; - MMC5PRG(); - break; - case 0x5120: - case 0x5121: - case 0x5122: - case 0x5123: - case 0x5124: - case 0x5125: - case 0x5126: - case 0x5127: - mmc5ABMode = 0; - CHRBanksA[A & 7] = V | ((MMC50x5130 & 0x3) << 8); - MMC5CHRA(); - break; - case 0x5128: - case 0x5129: - case 0x512a: - case 0x512b: - mmc5ABMode = 1; - CHRBanksB[A & 3] = V | ((MMC50x5130 & 0x3) << 8); - MMC5CHRB(); - break; - case 0x5130: - MMC50x5130 = V; - break; - case 0x5200: - MMC5HackSPMode = V; - break; - case 0x5201: - MMC5HackSPScroll = (V >> 3) & 0x1F; - break; - case 0x5202: - MMC5HackSPPage = V & 0x3F; - break; - case 0x5203: - X6502_IRQEnd(FCEU_IQEXT); - IRQScanline = V; - break; - case 0x5204: - X6502_IRQEnd(FCEU_IQEXT); - IRQEnable = V & 0x80; - break; - case 0x5205: - mul[0] = V; - break; - case 0x5206: - mul[1] = V; - break; - } -} - -static DECLFR(MMC5_ReadROMRAM) { - if (MMC5MemIn[(A - 0x6000) >> 13]) { - return Page[A >> 11][A]; - } - return CPU_OPENBUS; -} - -static DECLFW(MMC5_WriteROMRAM) { - if ((A >= 0x8000) && (MMC5ROMWrProtect[(A - 0x8000) >> 13])) { - return; - } - if (MMC5MemIn[(A - 0x6000) >> 13]) { - if (((WRAMMaskEnable[0] & 3) | ((WRAMMaskEnable[1] & 3) << 2)) == 6) { - Page[A >> 11][A] = V; - } - } -} - -DECLFW(MMC5_ExRAMWr) { - if (MMC5HackCHRMode != 3) { - ExRAM[A & 0x3ff] = V; - } -} - -static DECLFR(MMC5_ExRAMRd) { - return ExRAM[A & 0x3ff]; -} - -static DECLFR(MMC5_read) { - uint8 ret = CPU_OPENBUS; - switch (A) { - case 0x5204: - X6502_IRQEnd(FCEU_IQEXT); - ret = MMC5IRQR; -#ifdef FCEUDEF_DEBUGGER - if (!fceuindbg) -#endif - MMC5IRQR &= 0x40; - return ret; - case 0x5205: - return ((uint32)(mul[0] * mul[1]) & 0xFF); - case 0x5206: - return ((uint32)(mul[0] * mul[1]) >> 8); - } - return ret; -} - -static void MMC5Synco(void) { - uint8 moop; - - MMC5PRG(); - MMC5MIRR(); - MMC5WRAM(0x6000, WRAMPage & 7); - if (!mmc5ABMode) { - MMC5CHRB(); - MMC5CHRA(); - } else { - MMC5CHRA(); - MMC5CHRB(); - } - - /* in case the fill register changed, we need to overwrite the fill buffer */ - FCEU_dwmemset(MMC5fill, NTFill | (NTFill << 8) | (NTFill << 16) | (NTFill << 24), 0x3c0); - moop = ATFill | (ATFill << 2) | (ATFill << 4) | (ATFill << 6); - FCEU_dwmemset(MMC5fill + 0x3c0, moop | (moop << 8) | (moop << 16) | (moop << 24), 0x40); - - MMC5HackCHRMode = CHRMode & 3; - - /* zero 17-apr-2013 - why the heck should this happen here? anything in a `synco` should be depending on the state. - * im going to leave it commented out to see what happens - */ - /* X6502_IRQEnd(FCEU_IQEXT); */ -} - -void MMC5_hb(int cur_scanline) { - /* zero 24-jul-2014 - revised for newer understanding, to fix metal slader glory credits. see r7371 in bizhawk */ - int sl = cur_scanline + 1; - int ppuon = (PPU[1] & 0x18); - - if (!ppuon || sl >= 241) { - /* whenever rendering is off for any reason (vblank or forced disable - * the irq counter resets, as well as the inframe flag (easily verifiable from software) - */ - MMC5IRQR &= ~0x40; - MMC5IRQR &= ~0x80; - MMC5LineCounter = 0; - X6502_IRQEnd(FCEU_IQEXT); - return; - } - - if (!(MMC5IRQR & 0x40)) { - MMC5IRQR |= 0x40; - MMC5IRQR &= ~0x80; - MMC5LineCounter = 0; - X6502_IRQEnd(FCEU_IQEXT); - } else { - MMC5LineCounter++; - if (MMC5LineCounter == IRQScanline) { - MMC5IRQR |= 0x80; - if (IRQEnable & 0x80) { - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void MMC5_StateRestore(int version) { - MMC5Synco(); -} - -static void GenMMC5Power(void) { - int x; - uint8 nval; - uint8 aval; - - for (x = 0; x < 4; x++) PRGBanks[x] = ~0; - for (x = 0; x < 8; x++) CHRBanksA[x] = ~0; - for (x = 0; x < 4; x++) CHRBanksB[x] = ~0; - for (x = 0; x < 2; x++) WRAMMaskEnable[x] = ~0; - for (x = 0; x < 4; x++) MMC5ROMWrProtect[x] = 0; - for (x = 0; x < 5; x++) MMC5MemIn[x] = 0; - for (x = 0; x < 2; x++) mul[x] = 0; - - WRAMPage = 0; - CHRMode = 0; - mmc5ABMode = 0; - mmc5psize = mmc5vsize = 3; - - IRQScanline = 0; - IRQEnable = 0; - MMC5IRQR = 0; - MMC5LineCounter = 0; - - NTAMirroring = NTFill = ATFill = 0xFF; - - /* MMC5fill is and 8-bit tile index, and a 2-bit attribute implented as a mirrored nametable */ - nval = MMC5fill[0x000]; - aval = MMC5fill[0x3C0] & 3; aval = aval | (aval << 2) | (aval << 4) | (aval << 6); - FCEU_dwmemset(MMC5fill + 0x000, nval | (nval<<8) | (nval<<16) | (nval<<24), 0x3C0); - FCEU_dwmemset(MMC5fill + 0x3C0, aval | (aval<<8) | (aval<<16) | (aval<<24), 0x040); - - if (MMC5battery == 0) { - FCEU_MemoryRand(WRAM, MMC5WRAMsize * 8 * 1024); - FCEU_MemoryRand(MMC5fill, 1024); - FCEU_MemoryRand(ExRAM, 1024); - } - - MMC5Synco(); - - SetWriteHandler(0x4020, 0x5bff, Mapper5_write); - SetReadHandler(0x4020, 0x5bff, MMC5_read); - - SetWriteHandler(0x5c00, 0x5fff, MMC5_ExRAMWr); - SetReadHandler(0x5c00, 0x5fff, MMC5_ExRAMRd); - - SetWriteHandler(0x6000, 0xFFFF, MMC5_WriteROMRAM); - SetReadHandler(0x6000, 0xFFFF, MMC5_ReadROMRAM); - - SetWriteHandler(0x5000, 0x5015, MMC5Sound_Write); - SetWriteHandler(0x5205, 0x5206, Mapper5_write); - SetReadHandler(0x5205, 0x5206, MMC5_read); - -/* GameHBIRQHook=MMC5_hb; */ -/* FCEU_CheatAddRAM(8, 0x6000, WRAM); */ - FCEU_CheatAddRAM(1, 0x5c00, ExRAM); - -#ifdef NEW_PPU - FFCEUX_PPURead = mmc5_PPURead; - FFCEUX_PPUWrite = mmc5_PPUWrite; -#endif -} - -static void GenMMC5_Init(CartInfo *info, int wsize, int battery) { - if (wsize) { - WRAM = (uint8 *)FCEU_gmalloc(wsize * 1024); - SetupCartPRGMapping(0x10, WRAM, wsize * 1024, 1); - AddExState(WRAM, wsize * 1024, 0, "WRAM"); - } - - MMC5fill = (uint8 *)FCEU_gmalloc(1024); - ExRAM = (uint8 *)FCEU_gmalloc(1024); - - FCEU_MemoryRand(MMC5fill, 1024); - FCEU_MemoryRand(ExRAM, 1024); - - AddExState(ExRAM, 1024, 0, "ERAM"); - AddExState(&MMC5HackSPMode, 1, 0, "SPLM"); - AddExState(&MMC5HackSPScroll, 1, 0, "SPLS"); - AddExState(&MMC5HackSPPage, 1, 0, "SPLP"); - AddExState(&MMC50x5130, 1, 0, "5130"); - AddExState(MMC5_StateRegs, ~0, 0, 0); - - MMC5WRAMsize = wsize ? (wsize / 8) : 0; - BuildWRAMSizeTable(); - GameStateRestore = MMC5_StateRestore; - info->Power = GenMMC5Power; - - MMC5battery = battery; - if (battery) { - uint32 saveramsize; - if (info->iNES2) { - saveramsize = info->PRGRamSaveSize; - } else { - if (wsize <= 16) saveramsize = 8 * 1024; - else if (wsize >= 64) saveramsize = 64 * 1024; - else saveramsize = 32 * 1024; - } - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = saveramsize; - } - - MMC5HackVROMMask = CHRmask4[0]; - MMC5HackExNTARAMPtr = ExRAM; - MMC5Hack = TRUE; - MMC5HackVROMPTR = CHRptr[0]; - MMC5HackCHRMode = 0; - MMC5HackSPMode = MMC5HackSPScroll = MMC5HackSPPage = 0; - - MMC5Sound_ESI(); - MMC5Sound_AddStateInfo(); -} - -void Mapper005_Init(CartInfo *info) { - WRAMSIZE = 64; - if (info->iNES2) { - WRAMSIZE = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; - if (WRAMSIZE && WRAMSIZE < 8) WRAMSIZE = 8; - else if (WRAMSIZE > 64) WRAMSIZE = 64; - } - GenMMC5_Init(info, WRAMSIZE, info->battery); -} - -/* ELROM seems to have 0KB of WRAM - * EKROM seems to have 8KB of WRAM, battery-backed - * ETROM seems to have 16KB of WRAM, battery-backed - * EWROM seems to have 32KB of WRAM, battery-backed - */ - -void ELROM_Init(CartInfo *info) { - GenMMC5_Init(info, 0, 0); -} - -void EKROM_Init(CartInfo *info) { - GenMMC5_Init(info, 8, info->battery); -} - -void ETROM_Init(CartInfo *info) { - GenMMC5_Init(info, 16, info->battery); -} - -void EWROM_Init(CartInfo *info) { - GenMMC5_Init(info, 32, info->battery); -} diff --git a/src/mappers/mapper006.c b/src/mappers/mapper006.c deleted file mode 100644 index db8480929..000000000 --- a/src/mappers/mapper006.c +++ /dev/null @@ -1,486 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Front Fareast Magic Card 1M or 2M RAM cartridges - * - */ - -#include "mapinc.h" -#include "mapper006.h" - -static uint8 mode_1m; -static uint8 mode_2m; -static uint8 mode_smc; - -static uint8 prg[4]; -static uint8 chr[8]; -static uint8 nt[4]; -static uint8 chr_mmc4latch[2]; -static uint8 latch; -static uint8 chr_lock; - -static uint8 smc_irq_enabled; -static uint32 smc_irq_counter; - -static uint8 fds_control; -static int16 fds_irq_counter; - -static uint8 scratch[0x1000]; - -static SFORMAT StateRegs[] = { - { &mode_1m, 1, "MC1M" }, - { &mode_2m, 1, "MC2M" }, - { &mode_smc, 1, "SMCM" }, - - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { nt, 4, "NTAR" }, - { chr_mmc4latch, 2, "MMC4" }, - { &latch, 1, "LATC" }, - { &chr_lock, 1, "CHRL" }, - - { &smc_irq_enabled, 1, "IRQA" }, - { &smc_irq_enabled, 4, "IRQC" }, - - { &fds_control, 1, "FDSI" }, - { &fds_irq_counter, 4, "FDSC" }, - - { 0 }, -}; - -static void SyncPRG(void) { - uint8 prg_writable = !(mode_1m & 0x02); - - SetupCartPRGMapping(0, PRGptr[0], PRGsize[0], prg_writable); - - if (!(mode_2m & 0x01)) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, prg[3]); - } else { - switch (mode_1m >> 5) { - case 0: - setprg16(0x8000, latch & 0x07); - setprg16(0xC000, 0x07); - break; - case 1: - setprg16(0x8000, (latch >> 2) & 0x0F); - setprg16(0xC000, 0x07); - break; - case 2: - setprg16(0x8000, latch & 0x0F); - setprg16(0xC000, 0x0F); - break; - case 3: - setprg16(0x8000, 0x0F); - setprg16(0xC000, latch & 0x0F); - break; - case 4: - setprg32(0x8000, (latch >> 4) & 0x03); - break; - case 5: - case 6: - case 7: - setprg32(0x8000, 0x03); - break; - } - } -} - -static void SyncCHR(void) { - uint8 chr_writable = !(((mode_1m & 0xE1) >= 0x81) || chr_lock); - - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], chr_writable); - - if (mode_smc & 0x01) { - if (mode_smc & 0x04) { - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - } else { - setchr4(0x0000, chr[0 | chr_mmc4latch[0]] >> 2); - setchr4(0x1000, chr[4 | chr_mmc4latch[1]] >> 2); - } - } else { - switch (mode_1m >> 5) { - case 0: - case 2: - setchr8(0); - break; - case 1: - case 4: - case 5: - setchr8(latch & 0x03); - break; - case 3: - setchr8((latch >> 4) & 0x03); - break; - case 6: - setchr8(latch & 0x01); - break; - case 7: - setchr8(0x03); - break; - } - } -} - -static void SyncMIR(void) { - if (mode_smc & 0x02) { - switch (mode_1m & 0x11) { - case 0x00: setmirror(MI_0); break; - case 0x10: setmirror(MI_1); break; - case 0x01: setmirror(MI_V); break; - case 0x11: setmirror(MI_H); break; - } - } else { - setntamem(CHRptr[0] + 0x400 * (nt[0] & CHRmask1[0]), 1, 0); - setntamem(CHRptr[0] + 0x400 * (nt[1] & CHRmask1[0]), 1, 1); - setntamem(CHRptr[0] + 0x400 * (nt[2] & CHRmask1[0]), 1, 2); - setntamem(CHRptr[0] + 0x400 * (nt[3] & CHRmask1[0]), 1, 3); - } -} - -static void Sync(void) { - setprg4r(0x11, 0x5000, 0); - setprg8r(0x10, 0x6000, 0); - - SyncPRG(); - SyncCHR(); - SyncMIR(); -} - -static DECLFR(M006ReadREG) { - return mode_smc; -} - -static DECLFW(M006WriteREG) { - switch (A) { - case 0x4024: - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x4025: - X6502_IRQEnd(FCEU_IQEXT); - if (!smc_irq_enabled) { - fds_control = V; - if (V & 0x42) { - fds_irq_counter = 0; - } - } - break; - case 0x42FC: - case 0x42FD: - case 0x42FE: - case 0x42FF: - mode_1m = (V & 0xF0) | (A & 0x03); - if (mode_1m >= 0x80) { - chr_lock = FALSE; - } - SyncPRG(); - SyncCHR(); - SyncMIR(); - break; - case 0x43FC: - case 0x43FD: - case 0x43FE: - case 0x43FF: - mode_2m = (V & 0xF0) | (A & 0x03); - latch = V; - SyncPRG(); - SyncCHR(); - break; - case 0x4500: - mode_smc = V; - SyncCHR(); - SyncMIR(); - break; - case 0x4501: - smc_irq_enabled = FALSE; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x4502: - smc_irq_counter = (smc_irq_counter & 0xFF00) | V; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x4503: - smc_irq_enabled = TRUE; - smc_irq_counter = (smc_irq_counter & 0x00FF) | (V << 8); - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x4504: - case 0x4505: - case 0x4506: - case 0x4507: - if (mode_2m & 0x02) { - V >>= 2; - } - prg[A & 0x03] = V; - SyncPRG(); - break; - case 0x4510: - case 0x4511: - case 0x4512: - case 0x4513: - case 0x4514: - case 0x4515: - case 0x4516: - case 0x4517: - chr[A & 0x07] = V; - SyncCHR(); - break; - case 0x4518: - case 0x4519: - case 0x451A: - case 0x451B: - nt[A & 0x03] = V; - SyncMIR(); - break; - } -} - -static DECLFW(M006WriteLatch) { - if (mode_1m & 0x02) { - latch = V; - if (mode_2m & 0x03) { - prg[(A >> 13) & 0x03] = V >> 2; - } - SyncPRG(); - SyncCHR(); - } else { - CartBW(A, V); - } -} - -static void M006Reset(void) { - smc_irq_enabled = FALSE; - smc_irq_counter = 0; - fds_control = 0; - fds_irq_counter = 0; - Sync(); -} - -static uint32 prg_size_8K = 0; -static void SetTrainer(void) { - int nmiHandler; - - #define PRGPAGE_DMR(a) Page[(a) >> 11][(a)] - #define PRGPAGE_DMW(a, d) Page[(a) >> 11][(a)] = (d) - - nmiHandler = PRGPAGE_DMR(0xFFFA) | (PRGPAGE_DMR(0xFFFB) << 8); - if (nmiHandler == 0x5032) { - PRGPAGE_DMW(0xFFFA, scratch[0x4F]); - PRGPAGE_DMW(0xFFFB, scratch[0x50]); - } - memcpy(&scratch[0], &smc5000[0], sizeof(smc5000)); - scratch[0x4F] = PRGPAGE_DMR(0xFFFA); - scratch[0x50] = PRGPAGE_DMR(0xFFFB); - if (iNESCart.mapper == 17) { - PRGPAGE_DMW(0xFFFA, 0x32); - PRGPAGE_DMW(0xFFFB, 0x50); - } - if (iNESCart.HasTrainer && WRAM) { - int i; - uint8 *trainerData = 0; - uint16 trainerAddr = - iNESCart.mapper != 17 ? 0x7000 : - iNESCart.submapper == 0 ? 0x7000 : - iNESCart.submapper << 8 | 0x5C00; - - for (i = 0; i < (int)MISC_ROM_SIZE; i++) { - PRGPAGE_DMW((trainerAddr & 0x7F00) + i, MISC_ROM_PTR[i]); - } - - X6502_SetNewPC((iNESCart.mapper == 17) ? trainerAddr : 0x5000); - } - (GetWriteHandler(0x4017))(0x4017, 0x40); - - #undef PRGPAGE_DMR - #undef PRGPAGE_DMW -} - -static void M006Power(void) { - mode_1m = (((iNESCart.mapper == 6) ? iNESCart.submapper : 1) << 5) | - ((iNESCart.mirror & MI_V) ? 0x01 : 0x11) | - 0x02; - chr_lock = FALSE; - - mode_2m = ((iNESCart.mapper == 12) || - (iNESCart.mapper == 17)) ? 0x00 : 0x03; - mode_smc = (iNESCart.mapper == 17) ? 0x47 : 0x42; - latch = 0; - - prg[0] = prg_size_8K - 4; - prg[1] = prg_size_8K - 3; - prg[2] = prg_size_8K - 2; - prg[3] = prg_size_8K - 1; - - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - chr[4] = 4; - chr[5] = 5; - chr[6] = 6; - chr[7] = 7; - - M006Reset(); - - SetReadHandler(0x5000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x7FFF, CartBW); - - SetReadHandler (0x4500, 0x4500, M006ReadREG); - SetWriteHandler(0x4024, 0x451B, M006WriteREG); - SetWriteHandler(0x8000, 0xFFFF, M006WriteLatch); - - SetTrainer(); -} - -static void ClockSMCCounter(void) { - if (smc_irq_enabled) { - smc_irq_counter++; - if (smc_irq_counter >= 0x10000 ) { - smc_irq_counter = 0; - smc_irq_enabled = FALSE; - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void M006CPUHook(int a) { - while (a--) { - fds_irq_counter += 3; - while ((fds_irq_counter >= 448) && (fds_control & 0x80)) { - X6502_IRQBegin(FCEU_IQEXT); - fds_irq_counter -= 448; - } - - if (!(mode_smc & 0x08)) { - ClockSMCCounter(); - } - } -} - -static void M006HBHook(void) { - if (mode_smc & 0x08) { - int i; - for (i = 0; i < 8; i++) { - ClockSMCCounter(); - } - } -} - -static void M006PPUHook(uint32 A) { - if ((A & 0x3000) != 0x2000) { - int needsync = FALSE; - - if ((mode_1m >= 0xA0) && !(mode_1m & 0x01)) { - chr_lock = (mode_1m & 0x10) != 0; - needsync = TRUE; - } - - if ((mode_smc & 0x05) == 0x01) { - uint8 value = (A >> 4) & 0x02; - uint8 bank = (A >> 12) & 0x01; - - switch (A & 0x0FF0) { - case 0x0FD0: - case 0x0FE0: - if (chr_mmc4latch[bank] != value) { - chr_mmc4latch[bank] = value; - needsync = TRUE; - } - break; - } - } - if (needsync) { - Sync(); - } - } -} - -static void Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper006_Init(CartInfo *info) { - int ws = info->PRGRamSize + info->PRGRamSaveSize; - - info->Power = M006Power; - info->Reset = M006Reset; - - MapIRQHook = M006CPUHook; - PPU_hook = M006PPUHook; - GameHBIRQHook2 = M006HBHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = ws ? ws : 8192; - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - - SetupCartPRGMapping(0x11, scratch, 4096, TRUE); - AddExState(scratch, 4096, 0, "SRAM"); - - prg_size_8K = PRG_BANK_COUNT(8); - - if (CHR_ROM_SIZE) { - if (info->mapper == 12) { - int i; - size_t ssize, prgsize; - - prgsize = 512 * 1024; - PRG_ROM_PTR = realloc(PRG_ROM_PTR, prgsize); - for (i = 0; i < ((CHR_ROM_SIZE < (256 * 1024)) ? CHR_ROM_SIZE : (256 * 1024)); i++) { - PRG_ROM_PTR[(256 * 1024) + i] = CHR_ROM_PTR[i]; - } - SetupCartPRGMapping(0, PRG_ROM_PTR, prgsize, TRUE); - - memset(CHR_ROM_PTR, 0, CHR_ROM_SIZE); - ssize = info->CHRRamSize ? info->CHRRamSize : (32 * 1024); - SetupCartCHRMapping(0, CHR_ROM_PTR, ssize, TRUE); - AddExState(CHR_ROM_PTR, ssize, 0, "CHRR"); - VROM_size = 0; - } else { - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], TRUE); - AddExState(CHR_ROM_PTR, CHR_ROM_SIZE, 0, "CHRR"); - } - } - - if ((iNESCart.iNES2 == 0) && (iNESCart.mapper == 6)) { - iNESCart.submapper = 1; - } - - if (iNESCart.mapper == 8) { - iNESCart.mapper = 6; - iNESCart.submapper = 4; - } -} diff --git a/src/mappers/mapper006.h b/src/mappers/mapper006.h deleted file mode 100644 index 3061f0b69..000000000 --- a/src/mappers/mapper006.h +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef _MAPPER006_H -#define _MAPPER006_H - -const uint8_t smc5000[4096] ={ - 0x20, 0x03, 0x70, 0x6C, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xDD, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x08, 0x2C, 0x00, 0x45, 0x30, 0x19, 0x50, 0x17, 0x2C, 0x2F, 0x50, 0x10, 0x0E, 0x8D, - 0x44, 0x58, 0xA5, 0xFA, 0x0A, 0x09, 0xE0, 0x8D, 0xFD, 0x42, 0xAD, 0x44, 0x58, 0x28, 0x4C, 0x11, - 0x11, 0x8D, 0x44, 0x58, 0x8E, 0x45, 0x58, 0x8C, 0x46, 0x58, 0xBA, 0x8E, 0x47, 0x58, 0xAD, 0x00, - 0x58, 0x8D, 0x40, 0x58, 0x29, 0x7F, 0x8D, 0x00, 0x20, 0xAD, 0x01, 0x58, 0x8D, 0x41, 0x58, 0xAD, - 0x00, 0x45, 0x8D, 0x42, 0x58, 0xAD, 0x01, 0x45, 0x8D, 0x43, 0x58, 0xA2, 0x1F, 0xBD, 0x00, 0x50, - 0x9D, 0x48, 0x58, 0xBD, 0x00, 0x55, 0x9D, 0x68, 0x58, 0xCA, 0x10, 0xF1, 0xA9, 0x00, 0x8D, 0x01, - 0x45, 0x8D, 0x10, 0x40, 0x8D, 0x11, 0x40, 0x8D, 0x15, 0x40, 0xA9, 0x01, 0x8D, 0x31, 0x50, 0x20, - 0xCE, 0x53, 0xAD, 0xCA, 0x53, 0xF0, 0xF8, 0xA9, 0x72, 0x8D, 0x00, 0x45, 0xA2, 0x00, 0xB5, 0x00, - 0x9D, 0x00, 0x60, 0xBD, 0x00, 0x01, 0x9D, 0x00, 0x61, 0xBD, 0x00, 0x02, 0x9D, 0x00, 0x62, 0xBD, - 0x00, 0x03, 0x9D, 0x00, 0x63, 0xBD, 0x00, 0x04, 0x9D, 0x00, 0x64, 0xBD, 0x00, 0x05, 0x9D, 0x00, - 0x65, 0xBD, 0x00, 0x06, 0x9D, 0x00, 0x66, 0xBD, 0x00, 0x07, 0x9D, 0x00, 0x67, 0xE8, 0xD0, 0xCE, - 0xA9, 0x00, 0x8D, 0x00, 0x20, 0x8D, 0x01, 0x20, 0xA2, 0x07, 0x9D, 0x10, 0x45, 0xCA, 0x10, 0xFA, - 0x20, 0xF8, 0x51, 0x20, 0xB6, 0x52, 0x20, 0x24, 0x53, 0x20, 0xE7, 0x52, 0x20, 0x18, 0x53, 0xA9, - 0x00, 0x8D, 0x00, 0x45, 0xA0, 0x02, 0x8C, 0x31, 0x50, 0x4C, 0x3D, 0xF0, 0xAD, 0x31, 0x50, 0xC9, - 0x01, 0xF0, 0x01, 0x60, 0x4C, 0xA7, 0x50, 0xAD, 0x31, 0x50, 0xC9, 0x02, 0xF0, 0x01, 0x60, 0xA9, - 0x00, 0x8D, 0x31, 0x50, 0x8D, 0x00, 0x20, 0x8D, 0x01, 0x20, 0x20, 0x52, 0x53, 0x20, 0x88, 0x52, - 0x20, 0x80, 0x53, 0x20, 0xAE, 0x53, 0xA9, 0x00, 0x8D, 0xFC, 0x43, 0xA2, 0x03, 0xBD, 0x6C, 0x58, - 0x9D, 0x04, 0x45, 0xCA, 0x10, 0xF7, 0xA2, 0x0B, 0xBD, 0x78, 0x58, 0x9D, 0x10, 0x45, 0xCA, 0x10, - 0xF7, 0xA2, 0x00, 0xBD, 0x48, 0x58, 0x9D, 0x00, 0x40, 0xE8, 0xE0, 0x10, 0xD0, 0xF5, 0xAD, 0x5D, - 0x58, 0x8D, 0x15, 0x40, 0xAD, 0x5E, 0x58, 0x8D, 0x16, 0x40, 0xAD, 0x5F, 0x58, 0x8D, 0x17, 0x40, - 0xA9, 0x72, 0x8D, 0x00, 0x45, 0xA2, 0x00, 0xBD, 0x00, 0x60, 0x95, 0x00, 0xBD, 0x00, 0x61, 0x9D, - 0x00, 0x01, 0xBD, 0x00, 0x62, 0x9D, 0x00, 0x02, 0xBD, 0x00, 0x63, 0x9D, 0x00, 0x03, 0xBD, 0x00, - 0x64, 0x9D, 0x00, 0x04, 0xBD, 0x00, 0x65, 0x9D, 0x00, 0x05, 0xBD, 0x00, 0x66, 0x9D, 0x00, 0x06, - 0xBD, 0x00, 0x67, 0x9D, 0x00, 0x07, 0xE8, 0xD0, 0xCE, 0xAD, 0x68, 0x58, 0x8D, 0x00, 0x45, 0xAD, - 0x42, 0x58, 0x29, 0x03, 0xAA, 0xAD, 0x42, 0x58, 0x0A, 0x0A, 0x9D, 0xFC, 0x42, 0xAD, 0x43, 0x58, - 0x29, 0x03, 0xAA, 0xAD, 0x43, 0x58, 0x4A, 0x4A, 0x9D, 0xFC, 0x43, 0xAD, 0x02, 0x20, 0x10, 0xFB, - 0xAD, 0x02, 0x20, 0x10, 0xFB, 0x2C, 0x00, 0x45, 0x10, 0x03, 0x2C, 0x0A, 0x45, 0xAE, 0x47, 0x58, - 0x9A, 0xAC, 0x46, 0x58, 0xAE, 0x45, 0x58, 0xAD, 0x41, 0x58, 0x8D, 0x01, 0x20, 0xAD, 0x40, 0x58, - 0x8D, 0x00, 0x20, 0xAD, 0x44, 0x58, 0x28, 0x40, 0xA9, 0x20, 0x8D, 0xFD, 0x42, 0x8D, 0xFC, 0x43, - 0xA9, 0x00, 0x85, 0x00, 0xA9, 0x80, 0xA0, 0x04, 0x20, 0x2D, 0x52, 0x8E, 0x6C, 0x58, 0xA9, 0xA0, - 0xA0, 0x05, 0x20, 0x2D, 0x52, 0x8E, 0x6D, 0x58, 0xA9, 0xC0, 0xA0, 0x06, 0x20, 0x2D, 0x52, 0x8E, - 0x6E, 0x58, 0xA9, 0xE0, 0xA0, 0x07, 0x20, 0x2D, 0x52, 0x8E, 0x6F, 0x58, 0x60, 0x85, 0x01, 0x8C, - 0x56, 0x52, 0xA0, 0x00, 0xB1, 0x00, 0x8D, 0xC7, 0x53, 0xC8, 0xB1, 0x00, 0x8D, 0xC8, 0x53, 0xC8, - 0xB1, 0x00, 0x8D, 0xC9, 0x53, 0xA9, 0x49, 0x91, 0x00, 0x88, 0xA9, 0x53, 0x91, 0x00, 0x88, 0xA9, - 0x4A, 0x91, 0x00, 0xA2, 0x00, 0x8E, 0x04, 0x45, 0xA0, 0x00, 0xB1, 0x00, 0xC9, 0x4A, 0xD0, 0x0E, - 0xC8, 0xB1, 0x00, 0xC9, 0x53, 0xD0, 0x07, 0xC8, 0xB1, 0x00, 0xC9, 0x49, 0xF0, 0x08, 0xE8, 0xE0, - 0x80, 0xD0, 0xE2, 0x4C, 0x73, 0x52, 0xAD, 0xC9, 0x53, 0x91, 0x00, 0x88, 0xAD, 0xC8, 0x53, 0x91, - 0x00, 0x88, 0xAD, 0xC7, 0x53, 0x91, 0x00, 0x60, 0x2C, 0x2F, 0x50, 0x10, 0x15, 0xA2, 0x0C, 0xA0, - 0x01, 0x20, 0xA3, 0x52, 0xA2, 0x0D, 0xA0, 0x02, 0x20, 0xA3, 0x52, 0xA2, 0x0E, 0xA0, 0x03, 0x20, - 0xA3, 0x52, 0x60, 0x8E, 0x07, 0x45, 0x8C, 0xFC, 0x43, 0xA9, 0x02, 0x8D, 0x00, 0x45, 0xA9, 0x20, - 0x8D, 0xFD, 0x42, 0x4C, 0xC5, 0x52, 0xA9, 0x62, 0x8D, 0x00, 0x45, 0xA9, 0x00, 0x8D, 0xFC, 0x43, - 0xA9, 0x20, 0x8D, 0xFF, 0x42, 0x2C, 0x02, 0x20, 0xA0, 0x00, 0x8C, 0x06, 0x20, 0x8C, 0x06, 0x20, - 0xA9, 0x60, 0x8D, 0xDD, 0x52, 0xAD, 0x07, 0x20, 0xAD, 0x07, 0x20, 0x99, 0x00, 0x60, 0xC8, 0xD0, - 0xF7, 0xEE, 0xDD, 0x52, 0x10, 0xF2, 0x60, 0xA9, 0x72, 0x8D, 0x00, 0x45, 0xA9, 0x20, 0x8D, 0xFF, - 0x42, 0x2C, 0x02, 0x20, 0xA0, 0x20, 0x8C, 0x06, 0x20, 0xA0, 0x00, 0x8C, 0x06, 0x20, 0xA9, 0x68, - 0x8D, 0x0D, 0x53, 0xA2, 0x08, 0xAD, 0x07, 0x20, 0xAD, 0x07, 0x20, 0x99, 0x00, 0x68, 0xC8, 0xD0, - 0xF7, 0xEE, 0x0D, 0x53, 0xCA, 0xD0, 0xF1, 0x60, 0xA2, 0x1F, 0xBD, 0x20, 0x58, 0x9D, 0x88, 0x58, - 0xCA, 0x10, 0xF7, 0x60, 0x2C, 0x2F, 0x50, 0x10, 0x15, 0xA2, 0x0C, 0xA0, 0x01, 0x20, 0x3F, 0x53, - 0xA2, 0x0D, 0xA0, 0x02, 0x20, 0x3F, 0x53, 0xA2, 0x0E, 0xA0, 0x03, 0x20, 0x3F, 0x53, 0x60, 0x8E, - 0x07, 0x45, 0x8C, 0xFC, 0x43, 0xA9, 0x02, 0x8D, 0x00, 0x45, 0xA9, 0x20, 0x8D, 0xFD, 0x42, 0x4C, - 0x61, 0x53, 0xA9, 0x62, 0x8D, 0x00, 0x45, 0xA9, 0x00, 0x8D, 0xFC, 0x43, 0xA9, 0x20, 0x8D, 0xFF, - 0x42, 0x2C, 0x02, 0x20, 0xA0, 0x00, 0x8C, 0x06, 0x20, 0x8C, 0x06, 0x20, 0xA9, 0x60, 0x8D, 0x73, - 0x53, 0xB9, 0x00, 0x60, 0x8D, 0x07, 0x20, 0xC8, 0xD0, 0xF7, 0xEE, 0x73, 0x53, 0x10, 0xF2, 0x60, - 0xA9, 0x72, 0x8D, 0x00, 0x45, 0xA9, 0x20, 0x8D, 0xFF, 0x42, 0x2C, 0x02, 0x20, 0xA0, 0x20, 0x8C, - 0x06, 0x20, 0xA0, 0x00, 0x8C, 0x06, 0x20, 0xA9, 0x68, 0x8D, 0xA0, 0x53, 0xA2, 0x08, 0xB9, 0x00, - 0x68, 0x8D, 0x07, 0x20, 0xC8, 0xD0, 0xF7, 0xEE, 0xA0, 0x53, 0xCA, 0xD0, 0xF1, 0x60, 0x2C, 0x02, - 0x20, 0xA9, 0x3F, 0x8D, 0x06, 0x20, 0xA2, 0x00, 0x8E, 0x06, 0x20, 0xBD, 0x88, 0x58, 0x8D, 0x07, - 0x20, 0xE8, 0xE0, 0x20, 0x90, 0xF5, 0x60, 0x00, 0x11, 0x22, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, - 0x45, 0x10, 0x03, 0x20, 0x21, 0x55, 0xA2, 0x01, 0x8E, 0x16, 0x40, 0xCA, 0x8E, 0x16, 0x40, 0xA2, - 0x08, 0xAD, 0x16, 0x40, 0x4A, 0x2E, 0xCA, 0x53, 0x4A, 0x2E, 0xCC, 0x53, 0xAD, 0x17, 0x40, 0x4A, - 0x2E, 0xCB, 0x53, 0x4A, 0x2E, 0xCD, 0x53, 0xCA, 0xD0, 0xE7, 0xAD, 0xCC, 0x53, 0x0D, 0xCA, 0x53, - 0x8D, 0xCA, 0x53, 0xAD, 0xCD, 0x53, 0x0D, 0xCB, 0x53, 0x8D, 0xCB, 0x53, 0x60, 0xA9, 0x00, 0x8D, - 0x00, 0x45, 0x4C, 0x25, 0xEF, 0xA9, 0x00, 0x8D, 0x01, 0x20, 0xA9, 0x88, 0x8D, 0x00, 0x45, 0xAD, - 0xFC, 0xFF, 0xC9, 0xFF, 0xD0, 0x15, 0xAD, 0xFD, 0xFF, 0xC9, 0xFF, 0xD0, 0x0E, 0xA9, 0x02, 0x8D, - 0x00, 0x45, 0x20, 0x00, 0xE4, 0xA9, 0x0A, 0x8D, 0x01, 0x20, 0x60, 0x6C, 0xFC, 0xFF, 0xA9, 0x00, - 0x8D, 0x01, 0x20, 0xA9, 0x88, 0x8D, 0x00, 0x45, 0xAD, 0xE0, 0xE6, 0xC9, 0x49, 0xD0, 0xDE, 0xAD, - 0xE1, 0xE6, 0xC9, 0x4E, 0xD0, 0xD7, 0xAD, 0xE2, 0xE6, 0xC9, 0x2A, 0xD0, 0xD0, 0xA2, 0x88, 0xA0, - 0x00, 0xA9, 0x0F, 0x8D, 0x07, 0x45, 0x8E, 0x00, 0x45, 0xB9, 0x00, 0xE0, 0x8D, 0xFF, 0x43, 0x99, - 0x00, 0x60, 0xC8, 0xD0, 0xF1, 0xEE, 0x6B, 0x54, 0xEE, 0x71, 0x54, 0x10, 0xE9, 0xA0, 0x06, 0xB9, - 0x9B, 0x54, 0x99, 0x03, 0x06, 0x88, 0x10, 0xF7, 0xA9, 0xC0, 0x8D, 0x20, 0x50, 0xA9, 0xF0, 0x8D, - 0x21, 0x50, 0x8D, 0x27, 0x50, 0x8D, 0x2F, 0x50, 0x4C, 0x13, 0xEE, 0xA9, 0xF0, 0x8D, 0xFD, 0x42, - 0x60, 0xAD, 0x2E, 0x57, 0x8D, 0xCA, 0x53, 0xAD, 0x2F, 0x57, 0x8D, 0xCB, 0x53, 0x68, 0x68, 0x68, - 0x68, 0x60, 0xC9, 0x00, 0xD0, 0x03, 0x4C, 0x0D, 0x54, 0xC9, 0x01, 0xD0, 0x03, 0x4C, 0x13, 0xEE, - 0xC9, 0x02, 0xD0, 0x03, 0x4C, 0x15, 0x54, 0xC9, 0x03, 0xD0, 0x03, 0x4C, 0x0C, 0x51, 0xC9, 0x04, - 0xD0, 0x03, 0x4C, 0x17, 0x51, 0xC9, 0x05, 0xD0, 0x03, 0x4C, 0xA1, 0x54, 0x60, 0x78, 0xD8, 0xAD, - 0x00, 0x55, 0x8D, 0x68, 0x58, 0xAD, 0x07, 0x55, 0x8D, 0x6F, 0x58, 0xA9, 0x02, 0x8D, 0x00, 0x45, - 0x20, 0x73, 0xD6, 0xAA, 0xAD, 0x68, 0x58, 0x8D, 0x00, 0x45, 0xAD, 0x6F, 0x58, 0x8D, 0x07, 0x45, - 0x2C, 0x00, 0x45, 0x10, 0x03, 0x2C, 0x0A, 0x45, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x60, 0xAD, 0x00, 0x55, 0x29, 0xF7, 0x8D, 0x00, 0x45, 0x20, 0x03, 0x57, 0xC9, 0xD5, 0xD0, 0xF0, - 0x20, 0x03, 0x57, 0xC9, 0xAA, 0xD0, 0xF5, 0x20, 0x03, 0x57, 0xC9, 0x96, 0xF0, 0x07, 0xC9, 0xAD, - 0xD0, 0xEA, 0x4C, 0xB5, 0x56, 0x20, 0xF1, 0x56, 0xA2, 0x00, 0x20, 0x03, 0x57, 0x9D, 0x2B, 0x57, - 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0xE8, 0xE0, 0x05, 0x90, 0xEF, 0x20, 0xF7, 0x56, 0xF0, 0x03, - 0x4C, 0xE1, 0x56, 0xAD, 0x2C, 0x57, 0x8D, 0x28, 0x57, 0xAD, 0x2D, 0x57, 0x8D, 0x29, 0x57, 0xAD, - 0x2B, 0x57, 0xC9, 0x00, 0xD0, 0x5C, 0x20, 0xF1, 0x56, 0xA0, 0x00, 0xAD, 0x2F, 0x57, 0xF0, 0x2B, - 0xAD, 0x29, 0x57, 0x8D, 0x96, 0x55, 0xAD, 0x28, 0x57, 0x8D, 0x95, 0x55, 0x2C, 0x00, 0x45, 0x10, - 0xFB, 0xAD, 0x0A, 0x45, 0x99, 0x00, 0x00, 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0xC8, 0xD0, 0xEC, - 0xEE, 0x29, 0x57, 0xEE, 0x96, 0x55, 0xCE, 0x2F, 0x57, 0xD0, 0xE1, 0xAE, 0x2E, 0x57, 0xF0, 0x1C, - 0xA9, 0x8D, 0x8D, 0x27, 0x57, 0x2C, 0x00, 0x45, 0x10, 0xFB, 0xAD, 0x0A, 0x45, 0x20, 0x27, 0x57, - 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0xEE, 0x28, 0x57, 0xCA, 0xD0, 0xE9, 0x20, 0xF7, 0x56, 0x4C, - 0xE5, 0x56, 0xC9, 0x01, 0xD0, 0x54, 0x20, 0xF1, 0x56, 0xA0, 0x00, 0xAD, 0x2F, 0x57, 0xF0, 0x1E, - 0xA9, 0xB9, 0x8D, 0x27, 0x57, 0x20, 0x27, 0x57, 0x48, 0x20, 0x0C, 0x57, 0x68, 0x4D, 0x30, 0x57, - 0x8D, 0x30, 0x57, 0xC8, 0xD0, 0xEF, 0xEE, 0x29, 0x57, 0xCE, 0x2F, 0x57, 0xD0, 0xE7, 0xAE, 0x2E, - 0x57, 0xF0, 0x19, 0xA9, 0xAD, 0x8D, 0x27, 0x57, 0x20, 0x27, 0x57, 0x48, 0x20, 0x0C, 0x57, 0x68, - 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0xEE, 0x28, 0x57, 0xCA, 0xD0, 0xEC, 0xAD, 0x30, 0x57, 0x20, - 0x0C, 0x57, 0x2C, 0x00, 0x45, 0x30, 0xFB, 0x4C, 0xEB, 0x56, 0xC9, 0x02, 0xD0, 0x29, 0x20, 0xAA, - 0x56, 0xAD, 0x29, 0x57, 0x8D, 0x06, 0x20, 0xAD, 0x28, 0x57, 0x8D, 0x06, 0x20, 0x20, 0xF1, 0x56, - 0x20, 0x03, 0x57, 0x8D, 0x07, 0x20, 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0x20, 0xD0, 0x56, 0xD0, - 0xEF, 0x20, 0xF7, 0x56, 0x4C, 0xE5, 0x56, 0xC9, 0x03, 0xD0, 0x36, 0x20, 0xAA, 0x56, 0xAD, 0x29, - 0x57, 0x8D, 0x06, 0x20, 0xAD, 0x28, 0x57, 0x8D, 0x06, 0x20, 0xAD, 0x07, 0x20, 0x20, 0xF1, 0x56, - 0xAD, 0x07, 0x20, 0x48, 0x20, 0x0C, 0x57, 0x68, 0x4D, 0x30, 0x57, 0x8D, 0x30, 0x57, 0x20, 0xD0, - 0x56, 0xD0, 0xED, 0xAD, 0x30, 0x57, 0x20, 0x0C, 0x57, 0x2C, 0x00, 0x45, 0x30, 0xFB, 0x4C, 0xEB, - 0x56, 0xC9, 0x04, 0xD0, 0x08, 0xA9, 0x4C, 0x8D, 0x27, 0x57, 0x4C, 0x27, 0x57, 0xC9, 0x05, 0xD0, - 0x44, 0xAD, 0x2C, 0x57, 0x20, 0xB2, 0x54, 0x4C, 0xEB, 0x56, 0x2C, 0x02, 0x20, 0x30, 0xFB, 0x2C, - 0x02, 0x20, 0x10, 0xFB, 0x60, 0xA9, 0xAD, 0x8D, 0x27, 0x57, 0x20, 0x27, 0x57, 0x20, 0x0C, 0x57, - 0xEE, 0x28, 0x57, 0xD0, 0x03, 0xEE, 0x29, 0x57, 0x2C, 0x00, 0x45, 0x30, 0xFB, 0x4C, 0xEB, 0x56, - 0xAD, 0x2E, 0x57, 0xD0, 0x03, 0xCE, 0x2F, 0x57, 0xCE, 0x2E, 0x57, 0xD0, 0x03, 0xAD, 0x2F, 0x57, - 0x60, 0xA9, 0x01, 0xD0, 0x08, 0xF0, 0x04, 0xA9, 0x02, 0xD0, 0x02, 0xA9, 0x00, 0x8D, 0x31, 0x57, - 0x60, 0xA9, 0x81, 0x8D, 0x30, 0x57, 0x60, 0x2C, 0x00, 0x45, 0x10, 0xFB, 0xAD, 0x0A, 0x45, 0x4D, - 0x30, 0x57, 0x60, 0x2C, 0x00, 0x45, 0x10, 0xFB, 0xAD, 0x0A, 0x45, 0x60, 0x2C, 0x00, 0x45, 0x30, - 0xFB, 0x8D, 0x0A, 0x45, 0x2C, 0x0A, 0x45, 0x4A, 0x4A, 0x4A, 0x4A, 0x2C, 0x00, 0x45, 0x30, 0xFB, - 0x8D, 0x0A, 0x45, 0x2C, 0x0A, 0x45, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -#endif /* _MAPPER006_H */ \ No newline at end of file diff --git a/src/mappers/mapper007.c b/src/mappers/mapper007.c deleted file mode 100644 index 3191b0063..000000000 --- a/src/mappers/mapper007.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.data); - setchr8(0); - setmirror(MI_0 + ((latch.data >> 4) & 0x01)); -} - -void Mapper007_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, (info->submapper == 2)); -} diff --git a/src/mappers/mapper009.c b/src/mappers/mapper009.c deleted file mode 100644 index c3398cc8d..000000000 --- a/src/mappers/mapper009.c +++ /dev/null @@ -1,38 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "mmc2.h" - -static void M009PW(uint16 A, uint16 V) { - setprg8(A, V & 0x0F); -} - -static void M009CW(uint16 A, uint16 V) { - setchr4(A, V & 0x1F); -} - -void Mapper009_Init(CartInfo *info) { - int ws = info->iNES2 ? ((info->PRGRamSize + info->PRGRamSaveSize) / 1024) : (info->battery ? 8 : 0); - MMC2_Init(info, ws, info->battery); - MMC2_pwrap = M009PW; - MMC2_cwrap = M009CW; -} diff --git a/src/mappers/mapper010.c b/src/mappers/mapper010.c deleted file mode 100644 index 449eef3f5..000000000 --- a/src/mappers/mapper010.c +++ /dev/null @@ -1,38 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "mmc4.h" - -static void M010PW(uint16 A, uint16 V) { - setprg16(A, V & 0x0F); -} - -static void M010CW(uint16 A, uint16 V) { - setchr4(A, V & 0x1F); -} - -void Mapper010_Init(CartInfo *info) { - int ws = info->iNES2 ? ((info->PRGRamSize + info->PRGRamSaveSize) / 1024) : (info->battery ? 8 : 0); - MMC4_Init(info, ws, info->battery); - MMC4_pwrap = M010PW; - MMC4_cwrap = M010CW; -} \ No newline at end of file diff --git a/src/mappers/mapper011.c b/src/mappers/mapper011.c deleted file mode 100644 index a5c42cbcc..000000000 --- a/src/mappers/mapper011.c +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.data); - setchr8(latch.data >> 4); -} - -void Mapper011_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper012.c b/src/mappers/mapper012.c deleted file mode 100644 index 51adafa30..000000000 --- a/src/mappers/mapper012.c +++ /dev/null @@ -1,74 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static void M012CW(uint16 A, uint16 V) { - uint16 base = reg << ((A & 0x1000) ? 4 : 8); - - setchr1(A, (base & 0x100) | (V & 0xFF)); -} - -static DECLFW(M012Write) { - if (A & 0x100) { - reg = V; - MMC3_FixCHR(); - } -} - -static DECLFR(M012Read) { - if (A & 0x100) { - return dipsw; - } - return CartBR(A); -} - -static void M012Power(void) { - reg = 0; - dipsw = 1; /* chinese is default */ - MMC3_Power(); - SetWriteHandler(0x4100, 0x4FFF, M012Write); - SetReadHandler(0x4100, 0x4FFF, M012Read); -} - -static void M012Reset(void) { - reg = 0; - dipsw ^= 1; - MMC3_Reset(); -} - -void Mapper012_Init(CartInfo *info) { - if (info->submapper == 1) { - Mapper006_Init(info); - } else { - MMC3_Init(info, 8, info->battery); - MMC3_cwrap = M012CW; - isRevB = 0; - - info->Power = M012Power; - info->Reset = M012Reset; - AddExState(®, 1, 0, "EXPR"); - AddExState(&dipsw, 1, 0, "DPSW"); - } -} diff --git a/src/mappers/mapper013.c b/src/mappers/mapper013.c deleted file mode 100644 index e60acf483..000000000 --- a/src/mappers/mapper013.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, 0); - setchr4(0x0000, 0); - setchr4(0x1000, latch.data); -} - -void Mapper013_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper014.c b/src/mappers/mapper014.c deleted file mode 100644 index 445db598a..000000000 --- a/src/mappers/mapper014.c +++ /dev/null @@ -1,107 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * SL1632 2-in-1 protected board, similar to SL12 - * Samurai Spirits Rex (Full) - * - */ - -#include "mapinc.h" -#include "mmc3.h" -#include "vrc24.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 }, -}; - -static uint8 GetChrBase(uint16 A) { - if (A & 0x1000) { - if (A & 0x800) { - return ((reg & 0x80) >> 7); - } else { - return ((reg & 0x20) >> 5); - } - } - return ((reg & 0x08) >> 3); -} - -static void M014MMC3CW(uint16 A, uint16 V) { - uint16 mask = 0xFF; - uint16 base = GetChrBase(A) << 8; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M014VRC24CW(uint16 A, uint16 V) { - uint16 mask = 0xFF; - uint16 base = GetChrBase(A) << 8; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M014Write) { - if (A == 0xA131) { - reg = V; - if (reg & 0x02) { - MMC3_FixCHR(); - } else { - VRC24_FixCHR(); - } - } - if (reg & 0x02) { - MMC3_Write(A, V); - } else { - VRC24_Write(A, V); - } -} - -static void StateRestore(int version) { - if (reg & 0x02) { - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } else { - VRC24_FixPRG(); - VRC24_FixCHR(); - VRC24_FixMIR(); - } -} - -static void M014Power(void) { - reg = 0; - VRC24_Power(); - SetWriteHandler(0x8000, 0xFFFF, M014Write); -} - -void Mapper014_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M014MMC3CW; - - VRC24_Init(info, VRC2, 0x01, 0x02, FALSE, TRUE); - VRC24_cwrap = M014VRC24CW; - - info->Power = M014Power; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper015.c b/src/mappers/mapper015.c deleted file mode 100644 index 8f3ef3754..000000000 --- a/src/mappers/mapper015.c +++ /dev/null @@ -1,56 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = latch.data & 0x3F; - - setprg8r(0x10, 0x6000, 0); - switch (latch.addr & 0x03) { - case 0: - setprg32(0x8000, prg >> 1); - break; - case 1: - setprg16(0x8000, prg); - setprg16(0xC000, prg | 0x07); - break; - case 2: - setprg8(0x8000, (prg << 1) | (latch.data >> 7)); - setprg8(0xA000, (prg << 1) | (latch.data >> 7)); - setprg8(0xC000, (prg << 1) | (latch.data >> 7)); - setprg8(0xE000, (prg << 1) | (latch.data >> 7)); - break; - case 3: - setprg16(0x8000, prg); - setprg16(0xC000, prg); - break; - } - setchr8(0); - setmirror(((latch.data >> 6) & 0x01) ^ 0x01); -} - -void Mapper015_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper016.c b/src/mappers/mapper016.c deleted file mode 100644 index 4e9b610ec..000000000 --- a/src/mappers/mapper016.c +++ /dev/null @@ -1,51 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "eeprom_x24c0x.h" -#include "bandai.h" - -static void M016PW(uint16 A, uint16 V) { - setprg16(A, V & 0x0F); -} - -static void M016CW(uint16 A, uint16 V) { - setchr1(A, V); -} - -void Mapper016_Init(CartInfo *info) { - switch (info->submapper) { - case 4: - BANDAI_Init(info, EEPROM_NONE, TRUE); - break; - case 5: - if (info->battery || ((info->PRGRamSaveSize > 0) && (info->PRGRamSaveSize <= 256))) { - BANDAI_Init(info, EEPROM_X24C02, FALSE); break; - } else { - BANDAI_Init(info, EEPROM_NONE, FALSE); break; - } - break; - default: - BANDAI_Init(info, EEPROM_NONE, TRUE); - break; - } - BANDAI_pwrap = M016PW; - BANDAI_cwrap = M016CW; -} diff --git a/src/mappers/mapper018.c b/src/mappers/mapper018.c deleted file mode 100644 index 8e85062c7..000000000 --- a/src/mappers/mapper018.c +++ /dev/null @@ -1,163 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[4], chr[8]; -static uint8 IRQa, mirr; -static int32 IRQCount, IRQLatch; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { &mirr, 1, "MIRR" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 4, "IRQC" }, - { &IRQLatch, 4, "IRQL" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, ~0); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - if (mirr & 2) - setmirror(MI_0); - else - setmirror(mirr & 0x01); -} - -static DECLFW(M018WriteIRQ) { - switch (A & 0xF003) { - case 0xE000: - IRQLatch &= 0xFFF0; - IRQLatch |= (V & 0x0F) << 0x00; - break; - case 0xE001: - IRQLatch &= 0xFF0F; - IRQLatch |= (V & 0x0F) << 0x04; - break; - case 0xE002: - IRQLatch &= 0xF0FF; - IRQLatch |= (V & 0x0F) << 0x08; - break; - case 0xE003: - IRQLatch &= 0x0FFF; - IRQLatch |= (V & 0x0F) << 0x0C; - break; - case 0xF000: - IRQCount = IRQLatch; - break; - case 0xF001: - IRQa = V & 0x01; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xF002: - mirr = V & 0x03; - Sync(); - break; - } -} - -static DECLFW(M018WritePrg) { - uint32 i = ((A >> 1) & 1) | ((A - 0x8000) >> 11); - - if (A & 0x01) { - prg[i] = (prg[i] & 0x0F) | (V << 4); - } else { - prg[i] = (prg[i] & 0xF0) | (V & 0x0F); - } - Sync(); -} - -static DECLFW(M018WriteChr) { - uint32 i = ((A >> 1) & 1) | ((A - 0xA000) >> 11); - - if (A & 0x01) { - chr[i] = (chr[i] & 0x0F) | (V << 4); - } else { - chr[i] = (chr[i] & 0xF0) | (V & 0x0F); - } - Sync(); -} - -static void M018Power(void) { - IRQa = 0; - prg[0] = 0; - prg[1] = 1; - prg[2] = ~1; - prg[3] = ~0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0x9FFF, M018WritePrg); - SetWriteHandler(0xA000, 0xDFFF, M018WriteChr); - SetWriteHandler(0xE000, 0xFFFF, M018WriteIRQ); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M018IRQHook(int a) { - if (IRQa && IRQCount) { - IRQCount -= a; - if (IRQCount <= 0) { - X6502_IRQBegin(FCEU_IQEXT); - IRQCount = 0; - IRQa = 0; - } - } -} - -static void M018Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper018_Init(CartInfo *info) { - info->Power = M018Power; - info->Close = M018Close; - MapIRQHook = M018IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } -} diff --git a/src/mappers/mapper019.c b/src/mappers/mapper019.c deleted file mode 100644 index 53b552861..000000000 --- a/src/mappers/mapper019.c +++ /dev/null @@ -1,252 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "n163sound.h" - -static uint8 prg[4]; -static uint8 chr[8]; -static uint8 nt[4]; -static uint8 wram_protect; - -static uint16 IRQCount; -static uint8 IRQa; - -static SFORMAT N163_StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { nt, 4, "NMTA" }, - { &IRQCount, 2, "IRQC" }, - { &IRQa, 1, "IRQA" }, - { &wram_protect, 1, "WPRT" }, - - { 0 } -}; - -static void SyncPRG(void) { - setprg8(0x8000, prg[0] & 0x3F); - setprg8(0xa000, prg[1] & 0x3F); - setprg8(0xc000, prg[2] & 0x3F); - setprg8(0xe000, prg[3] & 0x3F); -} - -static void DoCHRRAMROM(int x, uint8 V) { - chr[x] = V; - if (((prg[1] >> ((x >> 2) + 6)) & 1) || (V < 0xE0)) { - setchr1(x << 10, V); - } -} - -static void FixCRR(void) { - int x; - for (x = 0; x < 8; x++) { - DoCHRRAMROM(x, chr[x]); - } -} - -static void DoNTARAMROM(int w, uint8 V) { - nt[w] = V; - if (V < 0xE0) { - V &= CHRmask1[0]; - setntamem(CHRptr[0] + (V << 10), 0, w); - } else { - setntamem(NTARAM + ((V & 1) << 10), 1, w); - } -} - -static void FixNTAR(void) { - int x; - for (x = 0; x < 4; x++) { - DoNTARAMROM(x, nt[x]); - } -} - -static void NamcoIRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount >= 0x7FFF) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - IRQCount = 0x7FFF; - } - } -} - -static DECLFR(AWRAM) { - return WRAM[A - 0x6000]; -} - -static DECLFW(BWRAM) { - if (((A >= 0x6000) && (A <= 0x67FF) && ((wram_protect & 0xF1) == 0x40)) || - ((A >= 0x6800) && (A <= 0x6FFF) && ((wram_protect & 0xF2) == 0x40)) || - ((A >= 0x7000) && (A <= 0x77FF) && ((wram_protect & 0xF4) == 0x40)) || - ((A >= 0x7800) && (A <= 0x7FFF) && ((wram_protect & 0xF8) == 0x40))) { - WRAM[A - 0x6000] = V; - } -} - -static DECLFR(M019Read) { - switch (A & 0xF800) { - case 0x4800: - return N163Sound_Read(A); - case 0x5000: - return IRQCount & 0xFF; - case 0x5800: - return IRQCount >> 8; - } - - return 0; -} - -static DECLFW(M019Write) { - switch (A & 0xF800) { - case 0x4800: - N163Sound_Write(A, V); - break; - case 0x5000: - IRQCount &= 0xFF00; - IRQCount |= V; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x5800: - IRQCount &= 0x00ff; - IRQCount |= (V & 0x7F) << 8; - IRQa = V & 0x80; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x8000: - case 0x8800: - case 0x9000: - case 0x9800: - case 0xA000: - case 0xA800: - case 0xB000: - case 0xB800: - DoCHRRAMROM((A - 0x8000) >> 11, V); - break; - case 0xC000: - case 0xC800: - case 0xD000: - case 0xD800: - DoNTARAMROM((A - 0xC000) >> 11, V); - break; - case 0xE000: - prg[0] = V; - SyncPRG(); - break; - case 0xE800: - prg[1] = V; - SyncPRG(); - FixCRR(); - break; - case 0xF000: - prg[2] = V; - SyncPRG(); - break; - case 0xF800: - wram_protect = V; - N163Sound_Write(A, V); - break; - } -} - -static void StateRestore(int version) { - SyncPRG(); - FixNTAR(); - FixCRR(); -} - -static int battery = 0; - -static void N163_Power(void) { - prg[0] = ~3; - prg[1] = ~2; - prg[2] = ~1; - prg[3] = ~0; - - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - chr[4] = 4; - chr[5] = 5; - chr[6] = 6; - chr[7] = 7; - - nt[0] = 0xE0; - nt[1] = 0xE1; - nt[2] = 0xE0; - nt[3] = 0xE1; - - wram_protect = 0xFF; - - SyncPRG(); - FixCRR(); - FixNTAR(); - - SetReadHandler(0x4800, 0x5FFF, M019Read); - SetWriteHandler(0x4800, 0x5FFF, M019Write); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M019Write); - - if (WRAMSIZE) { - SetReadHandler(0x6000, 0x7FFF, AWRAM); - SetWriteHandler(0x6000, 0x7FFF, BWRAM); - FCEU_CheatAddRAM(8, 0x6000, WRAM); - } - - if (!battery) { - FCEU_MemoryRand(WRAM, sizeof(WRAM)); - FCEU_MemoryRand(GetIRAM_ptr(), GetIRAM_size()); - } -} - -void Mapper019_Init(CartInfo *info) { - battery = info->battery; - info->Power = N163_Power; - - MapIRQHook = NamcoIRQHook; - GameStateRestore = StateRestore; - AddExState(N163_StateRegs, ~0, 0, 0); - - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } else if (info->battery) { - WRAMSIZE = 8192; - } - - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = 8192; - info->SaveGame[1] = GetIRAM_ptr(); - info->SaveGameLen[1] = GetIRAM_size(); - } - - N163Sound_ESI(); - N163Sound_AddStateInfo(); -} diff --git a/src/mappers/mapper021.c b/src/mappers/mapper021.c deleted file mode 100644 index 8bddb7535..000000000 --- a/src/mappers/mapper021.c +++ /dev/null @@ -1,31 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "vrc24.h" - -void Mapper021_Init(CartInfo *info) { - /* Mapper 21 - VRC4a, VRC4c */ - switch (info->submapper) { - case 1: VRC24_Init(info, VRC4, 0x02, 0x04, 1, 1); break; - case 2: VRC24_Init(info, VRC4, 0x40, 0x80, 1, 1); break; - default: VRC24_Init(info, VRC4, 0x42, 0x84, 1, 1); break; - } -} diff --git a/src/mappers/mapper022.c b/src/mappers/mapper022.c deleted file mode 100644 index fae114a0b..000000000 --- a/src/mappers/mapper022.c +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "vrc24.h" - -static void M22CW(uint16 A, uint16 V) { - setchr1(A, (V & 0xFF) >> 1); -} - -void Mapper022_Init(CartInfo *info) { - /* Mapper 22 - VRC2a */ - VRC24_Init(info, VRC2, 0x02, 0x01, 0, 1); - VRC24_cwrap = M22CW; -} diff --git a/src/mappers/mapper023.c b/src/mappers/mapper023.c deleted file mode 100644 index ae341063d..000000000 --- a/src/mappers/mapper023.c +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "vrc24.h" - -void Mapper023_Init(CartInfo *info) { - /* Mapper 23 - VRC2b, VRC4e, VRC4f */ - switch (info->submapper) { - case 1: VRC24_Init(info, VRC4, 0x01, 0x02, 1, 1); break; - case 2: VRC24_Init(info, VRC4, 0x04, 0x08, 1, 1); break; - case 3: VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); break; - default: VRC24_Init(info, VRC4, 0x05, 0x0A, 1, 1); break; - } -} diff --git a/src/mappers/mapper024.c b/src/mappers/mapper024.c deleted file mode 100644 index 183c0b5d1..000000000 --- a/src/mappers/mapper024.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - */ - -#include "mapinc.h" -#include "vrc6.h" - -static void M024PW(uint16 A, uint16 V) { - setprg8(A, V & 0x3F); -} - -static void M024CW(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -void Mapper024_Init(CartInfo *info) { - int wram = 0; - if (info->iNES2 && (info->PRGRamSize || info->PRGRamSaveSize)) { - wram = 1; - } else if (info->battery) { - wram = 1; - } - VRC6_Init(info, 0x01, 0x02, wram); - VRC6_pwrap = M024PW; - VRC6_cwrap = M024CW; -} diff --git a/src/mappers/mapper025.c b/src/mappers/mapper025.c deleted file mode 100644 index 3cc05b39f..000000000 --- a/src/mappers/mapper025.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "vrc24.h" - -static void M025CW(uint16 A, uint16 V) { - setchr1(A, V & 0xFFF); -} - -void Mapper025_Init(CartInfo *info) { - /* Mapper 25 - VRC2c, VRC4b, VRC4d */ - switch (info->submapper) { - case 1: VRC24_Init(info, VRC4, 0x02, 0x01, 1, 1); break; - case 2: VRC24_Init(info, VRC4, 0x08, 0x04, 1, 1); break; - case 3: VRC24_Init(info, VRC2, 0x02, 0x01, 0, 1); break; - default: VRC24_Init(info, VRC4, 0x0A, 0x05, 1, 1); break; - } - VRC24_cwrap = M025CW; -} diff --git a/src/mappers/mapper026.c b/src/mappers/mapper026.c deleted file mode 100644 index f2bdda3c9..000000000 --- a/src/mappers/mapper026.c +++ /dev/null @@ -1,38 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - */ - -#include "mapinc.h" -#include "vrc6.h" - -static void M026PW(uint16 A, uint16 V) { - setprg8(A, V & 0x3F); -} - -static void M026CW(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -void Mapper026_Init(CartInfo *info) { - VRC6_Init(info, 0x02, 0x01, 1); - VRC6_pwrap = M026PW; - VRC6_cwrap = M026CW; -} diff --git a/src/mappers/mapper027.c b/src/mappers/mapper027.c deleted file mode 100644 index 0813e713f..000000000 --- a/src/mappers/mapper027.c +++ /dev/null @@ -1,34 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2013 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, 0); - setchr4(0x0000, ((latch.addr << 1) & 0x02) | (latch.addr & 0x01)); - setchr4(0x1000, ((latch.addr << 1) & 0x02) | (latch.addr & 0x01)); - setmirror(MI_0 + (latch.addr & 0x01)); -} - -void Mapper027_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper028.c b/src/mappers/mapper028.c deleted file mode 100644 index 5b9c54ef9..000000000 --- a/src/mappers/mapper028.c +++ /dev/null @@ -1,107 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* added 2019-5-23 - * Mapper 28 - Action 53 - * http://wiki.nesdev.com/w/index.php/INES_Mapper_028 */ - -#include "mapinc.h" - -static uint8 cmd; -static uint8 reg[4]; - -static SFORMAT StateRegs[] = { - {&cmd, 1, "REG"}, - {reg, 4, "REGS"}, - {0} -}; - -static uint8 bank_size_masks[4] = { 0x01, 0x03, 0x07, 0x0F }; -static uint16 GetPRGBank(int V) { - uint16 cpu_a14 = V & 0x01; - uint16 outer_bank = reg[3] << 1; - uint16 bank_mode = reg[2] >> 2; /* discard mirroring bits */ - uint16 current_bank = reg[1]; - uint16 bank_size_mask = 0; - - if (((bank_mode ^ cpu_a14) & 0x03) == 0x02) { /* in UNROM fixed bank? */ - bank_mode = 0; /* if so, treat as NROM */ - } - if ((bank_mode & 0x02) == 0) { /* in 32K bank mode? */ - current_bank = (current_bank << 1) | cpu_a14; - } - bank_size_mask = bank_size_masks[(bank_mode >> 2) & 3]; - return ((current_bank & bank_size_mask) | (outer_bank & ~bank_size_mask)); -} - -static void Sync(void) { - setprg16(0x8000, GetPRGBank(0)); - setprg16(0xC000, GetPRGBank(1)); - setchr8(reg[0] & 0x03); - switch (reg[2] & 0x03) { - case 0: setmirror(MI_0); break; - case 1: setmirror(MI_1); break; - case 2: setmirror(MI_V); break; - case 3: setmirror(MI_H); break; - } -} - -static DECLFW(WriteCMD) { - cmd = ((V >> 6) & 0x02) | (V & 0x01); -} - -static DECLFW(WriteREG) { - reg[cmd] = V; - if (!(cmd & 0x02) && !(reg[2] & 0x02)) { - reg[2] &= ~0x01; - reg[2] |= (V >> 4) & 0x01; - } - Sync(); -} - -static void M028Power(void) { - reg[0] = ~0; - reg[1] = ~0; - reg[2] = ~0; - reg[3] = ~0; - Sync(); - - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetReadHandler(0x8000, 0xFFFF, CartBR); - - SetWriteHandler(0x5000, 0x5FFF, WriteCMD); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, WriteREG); -} - -static void M028Reset(void) { - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper028_Init(CartInfo *info) { - info->Power = M028Power; - info->Reset = M028Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper029.c b/src/mappers/mapper029.c deleted file mode 100644 index a0b038e70..000000000 --- a/src/mappers/mapper029.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Mapper 28, used by homebrew game Glider - * https://wiki.nesdev.com/w/index.php/INES_Mapper_029 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.data >> 2); - setprg16(0xc000, ~0); - setprg8r(0x10, 0x6000, 0); - setchr8r(0, latch.data & 3); -} - -void Mapper029_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, FALSE); -} diff --git a/src/mappers/mapper030.c b/src/mappers/mapper030.c deleted file mode 100644 index cbfb7495c..000000000 --- a/src/mappers/mapper030.c +++ /dev/null @@ -1,144 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2014 CaitSith2, 2022 Cluster - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * Roms still using NES 1.0 format should be loaded as 8K CHR RAM. - * Roms defined under NES 2.0 should use the VRAM size field, defining 7, 8 or 9, based on how much VRAM should be - * present. UNIF doesn't have this problem, because unique board names can define this information. The UNIF names are - * UNROM-512-8K, UNROM-512-16K and UNROM-512-32K - * - * The battery flag in the NES header enables flash, Mirrror mode 2 Enables MI_0 and MI_1 mode. - * Known games to use this board are: - * Battle Kid 2: Mountain of Torment (512K PRG, 8K CHR RAM, Horizontal Mirroring, Flash disabled) - * Study Hall (128K PRG (in 512K flash chip), 8K CHR RAM, Horizontal Mirroring, Flash enabled) - * Nix: The Paradox Relic (512 PRG, 8K CHR RAM, Vertical Mirroring, Flash enabled) - * Although Xmas 2013 uses a different board, where LEDs can be controlled (with writes to the $8000-BFFF space), - * it otherwise functions identically. - */ - -#include "mapinc.h" -#include "latch.h" -#include "flashrom.h" - -#define ROM_CHIP 0x00 -#define FLASH_CHIP 0x10 - -static uint8 flash_save; -static uint8 *flash_data; - -static void M030Sync(void) { - int chip = flash_save ? FLASH_CHIP : ROM_CHIP; - - setprg16r(chip, 0x8000, latch.data); - setprg16r(chip, 0xC000, ~0); - setchr8(latch.data >> 5); - switch (iNESCart.submapper) { - case 1: - /* Mega Man II (30th Anniversary Edition) */ - setmirror((latch.data >> 7) & 0x01); - break; - default: - setmirror(MI_0 + ((latch.data >> 7) & 0x01)); - break; - } -} - -static void M030CPUHook(int a) { - FlashROM_CPUCyle(a); -} - -static DECLFR(M030Read) { - if ((A < 0xC000) && flash_save) { - return FlashROM_Read(A); - } - return CartBR(A); -} - -static DECLFW(M030Write) { - if ((A < 0xC000) && flash_save) { - FlashROM_Write(A, V); - } else { - Latch_Write(A, V); - } -} - -static void M030Power(void) { - Latch_Power(); - SetReadHandler(0x8000, 0xFFFF, M030Read); - SetWriteHandler(0x8000, 0xBFFF, M030Write); -} - -static void M030Close(void) { - Latch_Close(); - if (flash_data) { - FCEU_gfree(flash_data); - } - flash_data = NULL; -} - -void Mapper030_Init(CartInfo *info) { - int mirror2bits = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2); - - flash_save = info->battery; - Latch_Init(info, M030Sync, NULL, 0, !flash_save); - - if (!info->submapper && (info->PRGCRC32 == 0x891C14BC)) { - info->submapper = 0x01; - } - - if (!(info->submapper & 1)) { - switch (mirror2bits) { - case 0: /* hard horizontal, internal */ - SetupCartMirroring(MI_H, 1, NULL); - break; - case 1: /* hard vertical, internal */ - SetupCartMirroring(MI_V, 1, NULL); - break; - case 2: /* switchable 1-screen, internal (flags: 4-screen + horizontal) */ - SetupCartMirroring(MI_0, 0, NULL); - break; - case 3: /* hard four screen, last 8k of 32k RAM (flags: 4-screen + vertical) */ - SetupCartMirroring(4, 1, CHR_ROM_PTR + (info->CHRRamSize - 8192)); - break; - } - } - - info->Power = M030Power; - info->Close = M030Close; - - if (flash_save) { - uint32 i, ssize; - /* Allocate memory for flash */ - ssize = PRGsize[0]; - flash_data = (uint8 *)FCEU_gmalloc(ssize); - /* Copy ROM to flash data */ - for (i = 0; i < ssize; i++) { - flash_data[i] = PRGptr[ROM_CHIP][i % ssize]; - } - SetupCartPRGMapping(FLASH_CHIP, flash_data, ssize, 1); - AddExState(flash_data, ssize, 0, "FLSH"); - info->SaveGame[0] = flash_data; - info->SaveGameLen[0] = ssize; - - FlashROM_Init(flash_data, ssize, 0xBF, 0xB7, 4096, 0x5555, 0x2AAA); - MapIRQHook = M030CPUHook; - } -} diff --git a/src/mappers/mapper031.c b/src/mappers/mapper031.c deleted file mode 100644 index 489dc81f7..000000000 --- a/src/mappers/mapper031.c +++ /dev/null @@ -1,74 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* added 2019-5-23 - * Mapper 31 - custom mapper by infiniteneslives - * https://wiki.nesdev.com/w/index.php/INES_Mapper_031 */ - -#include "mapinc.h" - -static uint8 prg[8]; - -static SFORMAT StateRegs[] = { - { prg, 8, "PREG" }, - { 0 } -}; - -static void Sync(void) { - setprg4(0x8000, prg[0]); - setprg4(0x9000, prg[1]); - setprg4(0xA000, prg[2]); - setprg4(0xB000, prg[3]); - setprg4(0xC000, prg[4]); - setprg4(0xD000, prg[5]); - setprg4(0xE000, prg[6]); - setprg4(0xF000, prg[7]); - setchr8(0); -} - -static DECLFW(M031Write) { - prg[A & 0x07] = V; - Sync(); -} - -static void M031Power(void) { - prg[0] = ~7; - prg[1] = ~6; - prg[2] = ~5; - prg[3] = ~4; - prg[4] = ~3; - prg[5] = ~2; - prg[6] = ~1; - prg[7] = ~0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, M031Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper031_Init(CartInfo *info) { - info->Power = M031Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper032.c b/src/mappers/mapper032.c deleted file mode 100644 index 4abd47eb0..000000000 --- a/src/mappers/mapper032.c +++ /dev/null @@ -1,132 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[2], chr[8], prgMode, mirr; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { &prgMode, 1, "MODE" }, - { &mirr, 1, "mirr" }, - { 0 } -}; - -static void Sync(void) { - if (prgMode == 0) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); - } else { - setprg8(0x8000, ~1); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[0]); - setprg8(0xE000, ~0); - } - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - if (iNESCart.submapper == 1) { - setmirror(MI_1); - } else { - setmirror((mirr & 0x01) ^ 0x01); - } -} - -static DECLFW(M032Write) { - switch (A & 0xF000) { - case 0x8000: - case 0xA000: - prg[(A >> 13) & 0x01] = V; - Sync(); - break; - case 0x9000: - mirr = (V & 0x01) != 0; - prgMode = (V & 0x02) != 0; - if (iNESCart.submapper == 1) { - prgMode = 0; - } - Sync(); - break; - case 0xB000: - chr[A & 0x07] = V; - Sync(); - break; - } -} - -static void M032Power(void) { - prg[0] = 0; - prg[1] = 1; - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - chr[4] = 4; - chr[5] = 5; - chr[6] = 6; - chr[7] = 7; - prgMode = 0; - Sync(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M032Write); - - if (WRAM) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } -} - -static void M032Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper032_Init(CartInfo *info) { - info->Power = M032Power; - info->Close = M032Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } -} diff --git a/src/mappers/mapper033.c b/src/mappers/mapper033.c deleted file mode 100644 index a8f57b24e..000000000 --- a/src/mappers/mapper033.c +++ /dev/null @@ -1,86 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 33 - Taito TC0190/TC0350 */ - -#include "mapinc.h" - -static uint8 prg[2], chr[6]; - -static SFORMAT StateRegs[] = { - { prg, 2, "PREG" }, - { chr, 6, "CREG" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg16(0xC000, ~0); - - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr1(0x1000, chr[2]); - setchr1(0x1400, chr[3]); - setchr1(0x1800, chr[4]); - setchr1(0x1C00, chr[5]); - - setmirror(((prg[0] >> 6) & 0x01) ^ 0x01); -} - -static DECLFW(M033Write) { - switch (A & 0xE003) { - case 0x8000: - case 0x8001: - prg[A & 0x01] = V; - Sync(); - break; - case 0x8002: - case 0x8003: - chr[A & 0x01] = V; - Sync(); - break; - case 0xA000: - case 0xA001: - case 0xA002: - case 0xA003: - chr[2 + (A & 0x03)] = V; - Sync(); - break; - } -} - -static void M33Power(void) { - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xBFFF, M033Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper033_Init(CartInfo *info) { - info->Power = M33Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} - diff --git a/src/mappers/mapper034.c b/src/mappers/mapper034.c deleted file mode 100644 index fee51679c..000000000 --- a/src/mappers/mapper034.c +++ /dev/null @@ -1,149 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Many-in-one hacked mapper crap. - * - * Original BNROM is actually AxROM variations without mirroring control, - * and haven't SRAM on-board, so it must be removed from here - * - * Difficult banking is what NINA board doing, most hacks for 34 mapper are - * NINA hacks, so this is actually 34 mapper - * - */ - -#include "mapinc.h" -#include "latch.h" - -#define M034_NINA001 1 -#define M034_BNROM 2 -#define M034_NESTICLE 3 - -static uint8 reg[3]; - -static uint8 type; -static void (*WSync)(void); - -static SFORMAT StateRegs[] = { - { reg, 3, "REGS" }, - { 0 } -}; - -/* submapper 1 - AVE NINA-001 */ - -static void Sync_NINA001(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, reg[0]); - setchr4(0x0000, reg[1]); - setchr4(0x1000, reg[2]); -} - -static DECLFW(M034Write_NINA001) { - CartBW(A, V); - if (A >= 0x7FFD) { - reg[A - 0x7FFD] = V; - WSync(); - } -} - -static void M034Power_NINA001(void) { - reg[0] = reg[1] = 0; - reg[2] = 1; - WSync(); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, M034Write_NINA001); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -/* submapper 2 - BNROM */ - -static void Sync_BNROM(void) { - setprg32(0x8000, latch.data); - setchr8(0); -} - -/* nesticle */ - -static void Sync_Nesticle(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, reg[0]); - setchr4(0x0000, reg[1]); - setchr4(0x1000, reg[2]); -} - -static DECLFW(M034Write_Nesticle) { - if (A >= 0x8000) { - reg[0] = V; - WSync(); - } else { - CartBW(A, V); - if (A >= 0x7FFD) { - reg[A - 0x7FFD] = V; - WSync(); - } - } -} - -static void M034Power_Nesticle(void) { - reg[0] = reg[1] = 0; - reg[2] = 1; - WSync(); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0xFFFF, M034Write_Nesticle); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M034Close(void) { -} - -static void StateRestore(int version) { - WSync(); -} - -void Mapper034_Init(CartInfo *info) { - if (info->HasTrainer) { - type = M034_NESTICLE; - WSync = Sync_Nesticle; - info->Power = M034Power_Nesticle; - } else if ((info->submapper == 1) || ((info->submapper != 2) && CHR_ROM_SIZE)) { - type = M034_NINA001; - WSync = Sync_NINA001; - info->Power = M034Power_NINA001; - } else if ((info->submapper == 2) || ((info->submapper != 1) && !CHR_ROM_SIZE)) { - type = M034_BNROM; - Latch_Init(info, Sync_BNROM, NULL, FALSE, TRUE); - info->Reset = Latch_RegReset; - } - - switch (type) { - case M034_NESTICLE: - case M034_NINA001: - info->Close = M034Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - break; - } -} diff --git a/src/mappers/mapper036.c b/src/mappers/mapper036.c deleted file mode 100644 index fdc2d8016..000000000 --- a/src/mappers/mapper036.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "txc.h" - -static uint8 chr = 0; - -static void M036Sync(void) { - setprg32(0x8000, txc.output & 0x03); - setchr8(chr & 0x0F); -} - -static DECLFW(M036Write) { - if ((A & 0xF200) == 0x4200) { - chr = V; - } - TXC_Write(A, (V >> 4) & 0x03); -} - -static DECLFR(M036Read) { - return (CPU_OPENBUS & ~0x30) | ((TXC_Read(A) << 4) & 0x30); -} - -static void M036Power(void) { - chr = 0; - TXC_Power(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x5FFF, M036Read); - SetWriteHandler(0x4100, 0xFFFF, M036Write); -} - -void Mapper036_Init(CartInfo *info) { - TXC_Init(info, M036Sync); - info->Power = M036Power; - AddExState(&chr, 1, 0, "CREG"); -} diff --git a/src/mappers/mapper037.c b/src/mappers/mapper037.c deleted file mode 100644 index 5fcb457b8..000000000 --- a/src/mappers/mapper037.c +++ /dev/null @@ -1,66 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M037PW(uint16 A, uint16 V) { - uint16 mask = (reg << 1) | 0x07; - uint16 base = ((reg << 2) & 0x10) | (((reg & 0x03) == 0x03) ? 0x08 : 0); - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M037CW(uint16 A, uint16 V) { - uint16 mask = 0x7F; - uint16 base = (reg << 5) & 0x80; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M037Write) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M037Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M037Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M037Write); -} - -void Mapper037_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - MMC3_pwrap = M037PW; - MMC3_cwrap = M037CW; - info->Power = M037Power; - info->Reset = M037Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper038.c b/src/mappers/mapper038.c deleted file mode 100644 index d036d050c..000000000 --- a/src/mappers/mapper038.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REG" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg & 0x03); - setchr8((reg >> 2) & 0x03); -} - -static DECLFW(M038Write) { - reg = V; - Sync(); -} - -static void M038Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x7000, 0x7FFF, M038Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper038_Init(CartInfo *info) { - info->Power = M038Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper040.c b/src/mappers/mapper040.c deleted file mode 100644 index 9218ce246..000000000 --- a/src/mappers/mapper040.c +++ /dev/null @@ -1,113 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - * - */ - -#include "mapinc.h" - -static uint8 reg[2]; -static uint32 IRQCount, IRQa; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &IRQCount, 4, "IRQC" }, - { &IRQa, 4, "IRQA" }, - { 0 } -}; - -static void Sync(void) { - if (reg[1] & 0x08) { - if (reg[1] & 0x10) - setprg32(0x8000, 2 | (reg[1] >> 6)); - else { - setprg16(0x8000, 4 | (reg[1] >> 5)); - setprg16(0xC000, 4 | (reg[1] >> 5)); - } - } else { - setprg8(0x6000, 6); - setprg8(0x8000, 4); - setprg8(0xA000, 5); - setprg8(0xC000, reg[0] & 0x07); - setprg8(0xE000, 7); - } - setchr8((reg[1] >> 1) & 0x03); - setmirror((reg[1] & 0x01) ^ 0x01); -} - -static DECLFW(M040Write) { - switch (A & 0xE000) { - case 0x8000: - IRQa = FALSE; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xA000: - IRQa = TRUE; - break; - case 0xC000: - if (iNESCart.submapper == 1) { - reg[1] = A & 0xFF; - Sync(); - } - break; - case 0xE000: - reg[0] = V; - Sync(); - break; - } -} - -static void M040Power(void) { - reg[0] = reg[1] = 0; - IRQCount = IRQa = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M040Write); -} - -static void M040Reset(void) { - reg[0] = 0; - reg[1] = 0; - IRQCount = IRQa = 0; - Sync(); -} - -static void M040IRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount & 0x1000) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper040_Init(CartInfo *info) { - info->Reset = M040Reset; - info->Power = M040Power; - MapIRQHook = M040IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper041.c b/src/mappers/mapper041.c deleted file mode 100644 index 12b440ce1..000000000 --- a/src/mappers/mapper041.c +++ /dev/null @@ -1,72 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg[0] & 0x07); - setchr8(((reg[0] >> 1) & 0x0C) | (reg[1] & 0x03)); - setmirror(((reg[0] >> 5) & 0x01) ^ 0x01); -} - -static DECLFW(M041Write0) { - reg[0] = A; - Sync(); -} - -static DECLFW(M041Write1) { - if (reg[0] & 0x04) { - /* bus conflict */ - reg[1] = (V & CartBR(A)); - Sync(); - } -} - -static void M041Reset(void) { - reg[0] = reg[1] = 0; - Sync(); -} - -static void M041Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x67FF, M041Write0); - SetWriteHandler(0x8000, 0xFFFF, M041Write1); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper041_Init(CartInfo *info) { - info->Power = M041Power; - info->Reset = M041Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper042.c b/src/mappers/mapper042.c deleted file mode 100644 index b4ba6bc90..000000000 --- a/src/mappers/mapper042.c +++ /dev/null @@ -1,201 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - * - Submapper 1 - Ai Senshi Nicol (256K PRG, 128K CHR, fixed Mirroring) - * - Submapper 3 - Bio Miracle Bokutte Upa (J) (128K PRG, 0K CHR, IRQ) - * - * - Submapper 2 - * - KS-018/AC-08/LH09 - * - UNIF UNL-AC08 - * - [UNIF] Green Beret (FDS Conversion, LH09) (Unl) [U][!][t1] (160K PRG) - * - Green Beret (FDS Conversion) (Unl) (256K PRG) - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg[2]; -static uint8 IRQa; -static uint16 IRQCount; - -static void (*WSync)(void); - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 2, "IRQC" }, - { 0 } -}; - -/* Submapper 1 - Ai Senshi Nicol */ - -static void M042_Sub1_Sync(void) { - setprg8(0x6000, reg[1] & 0x0F); - setprg32(0x8000, ~0); - setchr8(reg[0] & 0x0F); -} - -static DECLFW(M042_Sub1_Write) { - switch (A & 0xE000) { - case 0x8000: - reg[0] = V; - WSync(); - break; - case 0xE000: - reg[1] = V; - WSync(); - break; - } -} - -static void M042_Sub1_Power(void) { - reg[1] = 0; - reg[0] = 0; - FDSSound_Power(); - WSync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M042_Sub1_Write); -} - -/* Submapper 2 - Green Beret */ - -static void M042_Sub2_Sync(void) { - setprg8(0x6000, (reg[0] >> 1) & 0x0F); - setprg32(0x8000, (PRG_BANK_COUNT(16) & 0x07) ? 4 : 7); - setchr8(0); - setmirror(((reg[1] >> 3) & 1) ^ 1); -} - -static DECLFW(M042_Sub2_Write) { - switch (A & 0xF001) { - case 0x4001: - case 0x4000: - if ((A & 0xFF) != 0x25) { - break; - } - reg[1] = V; - WSync(); - break; - case 0x8001: - reg[0] = V; - WSync(); - break; - } -} - -static void M042_Sub2_Power(void) { - reg[0] = 0; - reg[1] = 0; - WSync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x4020, 0xFFFF, M042_Sub2_Write); -} - -/* Submapper 3 - Mario Baby */ - -static void M042_Sub3_Sync(void) { - setprg8(0x6000, reg[0] & 0x0F); - setprg32(0x8000, ~0); - setchr8(0); - setmirror(((reg[1] >> 3) & 1) ^ 1); -} - -static DECLFW(M042_Sub3_Write) { - switch (A & 0xE003) { - case 0xE000: - reg[0] = V; - WSync(); - break; - case 0xE001: - reg[1] = V; - WSync(); - break; - case 0xE002: - IRQa = (V & 0x02) != 0; - if (!IRQa) { - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - } - break; - } -} - -static void M042_Sub3_Power(void) { - reg[0] = 0; - reg[1] = 0; - IRQa = IRQCount = 0; - WSync(); - FDSSound_Power(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0xE000, 0xFFFF, M042_Sub3_Write); -} - -static void M042_Sub3_IRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount >= 24576) { - X6502_IRQBegin(FCEU_IQEXT); - } else { - X6502_IRQEnd(FCEU_IQEXT); - } - } -} - -/* Mapper 42 Loader */ -static void StateRestore(int version) { - WSync(); -} - -void Mapper042_Init(CartInfo *info) { - if (info->submapper == 0 || info-> submapper > 3) { - if (CHR_ROM_SIZE) { - /* Ai Senshi Nicol, only cart with CHR-ROM, all others use CHR-RAM */ - info->submapper = 1; - } else { - if (PRG_ROM_SIZE > (128 * 1024)) { - /* Green Beret LH09 FDS Conversion can be 160K or 256K */ - info->submapper = 2; - } else { - /* Mario Baby has only 128K PRG */ - info->submapper = 3; - } - } - } - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - switch (info->submapper) { - case 1: - info->Power = M042_Sub1_Power; - WSync = M042_Sub1_Sync; - break; - case 2: - info->Power = M042_Sub2_Power; - WSync = M042_Sub2_Sync; - break; - default: - info->Power = M042_Sub3_Power; - WSync = M042_Sub3_Sync; - MapIRQHook = M042_Sub3_IRQHook; - break; - } -} diff --git a/src/mappers/mapper043.c b/src/mappers/mapper043.c deleted file mode 100644 index 7840198de..000000000 --- a/src/mappers/mapper043.c +++ /dev/null @@ -1,97 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - * - */ - -#include "mapinc.h" - -static uint8 reg, swap; -static uint32 IRQCount, IRQa; - -static SFORMAT StateRegs[] = { - { &IRQCount, 4, "IRQC" }, - { &IRQa, 4, "IRQA" }, - { ®, 1, "REGS" }, - { &swap, 1, "SWAP" }, - { 0 } -}; - -static void Sync(void) { - int transo[8] = { 4, 3, 4, 4, 4, 7, 5, 6 }; - - setprg4(0x5000, 8 << 1); /* Only YS-612 advanced version */ - setprg8(0x6000, swap ? 0 : 2); - setprg8(0x8000, 1); - setprg8(0xA000, 0); - setprg8(0xC000, transo[reg & 0x07]); - setprg8(0xE000, swap ? 8 : 9); /* hard dump for mr.Mary is 128K, - * bank 9 is the last 2K ok bank 8 repeated 4 times, then till the end of 128K - * instead used bank A, containing some CHR data, ines rom have unused banks removed, - * and bank A moved to the bank 9 place for compatibility with other crappy dumps - */ - setchr8(0); -} - -static DECLFW(M043Write) { - switch (A & 0xF1FF) { - case 0x4022: - reg = V; - Sync(); - break; - case 0x4120: - swap = V & 0x01; - Sync(); - break; - case 0x8122: /* hacked version */ - case 0x4122: /* original version */ - IRQa = V & 0x01; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -static void M043Power(void) { - reg = swap = 0; - Sync(); - SetReadHandler(0x5000, 0xFFFF, CartBR); - SetWriteHandler(0x4020, 0x8FFF, M043Write); -} - -static void M043IRQHook(int a) { - IRQCount += a; - if (IRQa && (IRQCount >= 4096)) { - IRQa = 0; - X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper043_Init(CartInfo *info) { - info->Power = M043Power; - MapIRQHook = M043IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper044.c b/src/mappers/mapper044.c deleted file mode 100644 index e0f170f1f..000000000 --- a/src/mappers/mapper044.c +++ /dev/null @@ -1,63 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M044PW(uint16 A, uint16 V) { - uint8 base = (mmc3.wram << 4) & 0x70; - uint8 mask = ((mmc3.wram & 0x06) == 0x06) ? 0x1F : 0x0F; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M044CW(uint16 A, uint16 V) { - uint16 base = (mmc3.wram << 7) & 0x380; - uint16 mask = ((mmc3.wram & 0x06) == 0x06) ? 0xFF : 0x7F; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static DECLFW (M044WriteA000) { - MMC3_CMDWrite(A, V); - switch (A & 0xE001) { - case 0xA001: - MMC3_FixPRG(); - MMC3_FixCHR(); - break; - } -} - -static void M044Reset(void) { - MMC3_Reset(); -} - -static void M044Power(void) { - MMC3_Power(); - SetWriteHandler(0xA000, 0xBFFF, M044WriteA000); -} - -void Mapper044_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - MMC3_cwrap = M044CW; - MMC3_pwrap = M044PW; - info->Power = M044Power; - info->Reset = M044Reset; -} diff --git a/src/mappers/mapper045.c b/src/mappers/mapper045.c deleted file mode 100644 index 0343082ef..000000000 --- a/src/mappers/mapper045.c +++ /dev/null @@ -1,108 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; -static uint8 cmd; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &cmd, 1, "CMD0" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M045CW(uint16 A, uint16 V) { - if (CHR_ROM_SIZE || (iNESCart.CHRRamSize > 8192)) { - uint32 mask = 0xFF >> (~reg[2] & 0x0F); - uint32 base = ((reg[2] << 4) & 0xF00) | reg[0]; - - setchr1(A, (base & ~mask) | (V & mask)); - } else { - /* assume chr-ram, 4-in-1 Yhc-Sxx-xx variants */ - setchr8(0); - } -} - -static void M045PW(uint16 A, uint16 V) { - uint32 mask = ~reg[3] & 0x3F; - uint32 base = ((reg[2] << 2) & 0x300) | reg[1]; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static DECLFR(M045ReadCart) { - /* Some multicarts select between five different menus by connecting one of the higher address lines to PRG /CE. - The menu code selects between menus by checking which of the higher address lines disables PRG-ROM when set. */ - if (((PRGsize[0] < 0x200000) && (dipsw == 1) && (reg[1] & 0x80)) || - ((PRGsize[0] < 0x200000) && (dipsw == 2) && (reg[2] & 0x40)) || - ((PRGsize[0] < 0x100000) && (dipsw == 3) && (reg[1] & 0x40)) || - ((PRGsize[0] < 0x100000) && (dipsw == 4) && (reg[2] & 0x20))) { - return CPU_OPENBUS; - } - return CartBR(A); -} - -static DECLFW(M045WriteReg) { - CartBW(A, V); - if (!(reg[3] & 0x40)) { - reg[cmd] = V; - cmd = (cmd + 1) & 0x03; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static DECLFR(M045ReadDIP) { - uint32 addr = 1 << (dipsw + 4); - if (A & (addr | (addr - 1))) { - return 0x01; - } - return 0x00; -} - -static void M045Reset(void) { - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - dipsw++; - dipsw &= 7; - MMC3_Reset(); -} - -static void M045Power(void) { - reg[0] = reg[1] = reg[3] = cmd = dipsw = 0; - reg[2] = 0x0F; - MMC3_Power(); - SetReadHandler(0x8000, 0xFFFF, M045ReadCart); - SetWriteHandler(0x6000, 0x7FFF, M045WriteReg); - SetReadHandler(0x5000, 0x5FFF, M045ReadDIP); -} - -void Mapper045_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - MMC3_cwrap = M045CW; - MMC3_pwrap = M045PW; - info->Reset = M045Reset; - info->Power = M045Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper046.c b/src/mappers/mapper046.c deleted file mode 100644 index 04d15ef6e..000000000 --- a/src/mappers/mapper046.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, ((reg & 0x0F) << 1) | (latch.data & 0x01)); - setchr8(((reg & 0xF0) >> 1) | ((latch.data >> 4) & 0x07)); -} - -static DECLFW(M046WriteReg) { - reg = V; - Sync(); -} - -static void M046Power(void) { - reg = 0; - Latch_Power(); - SetWriteHandler(0x6000, 0x7FFF, M046WriteReg); -} - -static void M046Reset(void) { - reg = 0; - Sync(); -} - -void Mapper046_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Power = M046Power; - info->Reset = M046Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper047.c b/src/mappers/mapper047.c deleted file mode 100644 index 5f35075ab..000000000 --- a/src/mappers/mapper047.c +++ /dev/null @@ -1,65 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M047PW(uint16 A, uint16 V) { - setprg8(A, (reg << 4) | (V & 0x0F)); -} - -static void M047CW(uint16 A, uint16 V) { - setchr1(A, (reg << 7) | (V & 0x7F)); -} - -static DECLFW(M047Write) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M047Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M047Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M047Write); -} - -void Mapper047_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M047PW; - MMC3_cwrap = M047CW; - info->Power = M047Power; - info->Reset = M047Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper048.c b/src/mappers/mapper048.c deleted file mode 100644 index 3467c5121..000000000 --- a/src/mappers/mapper048.c +++ /dev/null @@ -1,120 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 48 - Taito TC0690/TC190+PAL16R4 */ - -#include "mapinc.h" - -static uint8 prg[2], chr[6], mirr; -static uint8 IRQa; -static int16 IRQCount, IRQLatch; - -static SFORMAT StateRegs[] = { - { prg, 2, "PREG" }, - { chr, 6, "CREG" }, - { &mirr, 1, "MIRR" }, - { &IRQCount, 2, "IRQC" }, - { &IRQLatch, 2, "IRQL" }, - { &IRQa, 1, "IRQA" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg16(0xC000, ~0); - - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr1(0x1000, chr[2]); - setchr1(0x1400, chr[3]); - setchr1(0x1800, chr[4]); - setchr1(0x1C00, chr[5]); - - setmirror(((mirr >> 6) & 0x01) ^ 0x01); -} - -static DECLFW(M048Write) { - switch (A & 0xE003) { - case 0x8000: - case 0x8001: - prg[A & 0x01] = V; - Sync(); - break; - case 0x8002: - case 0x8003: - chr[A & 0x01] = V; - Sync(); - break; - case 0xA000: - case 0xA001: - case 0xA002: - case 0xA003: - chr[2 + (A & 0x03)] = V; - Sync(); - break; - case 0xC000: - IRQLatch = V; - break; - case 0xC001: - IRQCount = IRQLatch; - break; - case 0xC002: - IRQa = TRUE; - break; - case 0xC003: - IRQa = FALSE; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xE000: - mirr = V; - Sync(); - break; - } -} - -static void M048Power(void) { - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M048Write); -} - -static void IRQHook(void) { - if (IRQa) { - IRQCount++; - if (IRQCount == 0x100) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper048_Init(CartInfo *info) { - info->Power = M048Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - GameHBIRQHook = IRQHook; -} - diff --git a/src/mappers/mapper049.c b/src/mappers/mapper049.c deleted file mode 100644 index d77f60ec2..000000000 --- a/src/mappers/mapper049.c +++ /dev/null @@ -1,72 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 49 */ -/* BMC-STREETFIGTER-GAME4IN1 - Sic. $6000 set to $41 rather than $00 on power-up. */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M049PW(uint16 A, uint16 V) { - if (reg & 0x01) { - setprg8(A, ((reg >> 2) & ~0x0F) | (V & 0x0F)); - } else { - setprg32(0x8000, (reg >> 4) & 0x03); - } -} - -static void M049CW(uint16 A, uint16 V) { - setchr1(A, ((reg << 1) & 0x180) | (V & 0x7F)); -} - -static DECLFW(M049Write) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M049Reset(void) { - reg = ((iNESCart.submapper == 1) || (iNESCart.PRGCRC32 == 0x408EA235)) ? 0x41 : 0x00; /* Street Fighter II Game 4-in-1 */ - MMC3_Reset(); -} - -static void M049Power(void) { - reg = ((iNESCart.submapper == 1) || (iNESCart.PRGCRC32 == 0x408EA235)) ? 0x41 : 0x00; /* Street Fighter II Game 4-in-1 */ - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M049Write); -} - -void Mapper049_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M049CW; - MMC3_pwrap = M049PW; - info->Reset = M049Reset; - info->Power = M049Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper050.c b/src/mappers/mapper050.c deleted file mode 100644 index 68cbb6aa1..000000000 --- a/src/mappers/mapper050.c +++ /dev/null @@ -1,90 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - * - */ - -#include "mapinc.h" - -static uint8 reg; -static uint32 IRQCount, IRQa; - -static SFORMAT StateRegs[] = { - { &IRQCount, 4, "IRQC" }, - { &IRQa, 4, "IRQA" }, - { ®, 1, "REG" }, - { 0 } -}; - -static void Sync(void) { - uint8 prg = ((reg & 0x01) << 2) | ((reg & 0x02) >> 1) | ((reg & 0x04) >> 1) | (reg & 0x08); - - setprg8(0x6000, 15); - setprg8(0x8000, 8); - setprg8(0xA000, 9); - setprg8(0xC000, prg); - setprg8(0xE000, 11); - setchr8(0); -} - -static DECLFW(M050Write) { - switch (A & 0xD160) { - case 0x4120: - IRQa = V & 0x01; - if (!IRQa) { - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - } - break; - case 0x4020: - reg = V; - Sync(); - break; - } -} - -static void M050Power(void) { - reg = 0; - IRQa = IRQCount = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x4020, 0x4FFF, M050Write); -} - -static void M050IRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount & 0x1000) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper050_Init(CartInfo *info) { - info->Power = M050Power; - MapIRQHook = M050IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper051.c b/src/mappers/mapper051.c deleted file mode 100644 index 536007f4b..000000000 --- a/src/mappers/mapper051.c +++ /dev/null @@ -1,95 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg, mode; - -static SFORMAT StateRegs[] = { - { &prg, 1, "PREG" }, - { &mode, 1, "MODE" }, - { 0 } -}; - -static void Sync(void) { - if (iNESCart.submapper == 1) { - setprg8(0x6000, (prg << 1) | 0x23); - if (mode & 0x022) - setprg32(0x8000, prg >> 1); - else { - setprg16(0x8000, ((prg >> 2) & 0x10) | ((prg >> 1) & 0x08) | (prg & 0x07)); - setprg16(0xC000, ((prg >> 2) & 0x10) | ((prg >> 1) & 0x08) | 0x07); - } - } else { - if (mode & 0x02) { - setprg8(0x6000, ((prg << 2) & 0x1C) | 0x23); - setprg32(0x8000, prg); - } else { - setprg8(0x6000, ((prg << 2) & 0x10) | 0x2F); - setprg16(0x8000, (prg << 1) | (prg >> 4)); - setprg16(0xC000, (prg << 1) | 0x07); - } - } - setchr8(0); - setmirror(((mode >> 4) & 1) ^ 1); -} - -static DECLFW(M051WriteMode) { - mode = V; - Sync(); -} - -static DECLFW(M051WriteBank) { - prg = V; - Sync(); -} - -static void M051Power(void) { - prg = 0; - mode = 2; - Sync(); - SetWriteHandler(0x6000, 0x7FFF, M051WriteMode); - SetWriteHandler(0x8000, 0xFFFF, M051WriteBank); - SetReadHandler(0x6000, 0xFFFF, CartBR); -} - -static void M051Reset(void) { - prg = 0; - mode = 2; - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper051_Init(CartInfo *info) { - info->Power = M051Power; - info->Reset = M051Reset; - AddExState(StateRegs, ~0, 0, NULL); - GameStateRestore = StateRestore; - - if ((CHR_ROM_SIZE == 8192) && (info->CHRRamSize == 8192)) { - /* at least 1 variant has 8K CHR-ROM which should be treated as CHR-RAM */ - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 1); - AddExState(CHRptr[0], CHRsize[0], 0, "CHRR"); - } -} diff --git a/src/mappers/mapper052.c b/src/mappers/mapper052.c deleted file mode 100644 index af25c32ee..000000000 --- a/src/mappers/mapper052.c +++ /dev/null @@ -1,110 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Submapper 13/14 - CHR-ROM + CHR-RAM */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M052PW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x08) ? 0x0F : 0x1F; - uint8 base = (reg << 4) & 0x70; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M052CW(uint16 A, uint16 V) { - uint16 mask = (reg & 0x40) ? 0x7F : 0xFF; - uint16 base = (((reg << 3) & 0x180) | ((reg << 7) & 0x200)); - uint8 chrram = CHRRAM && - (((iNESCart.submapper == 13) && ((reg & 0x03) == 0x03)) || - ((iNESCart.submapper == 14) && (reg & 0x20))); - - if (iNESCart.CRC32 == 0x68FE207F) { - /* Mario 7-in-1 (YH-705) with wrong bank order */ - base = ((reg & 0x20) << 4) | ((reg & 0x04) << 6) | - (reg & 0x40 ? (reg & 0x10) << 3 : 0x00); - } else if (iNESCart.submapper == 14) { - /* Well 8-in-1 (AB128) (Unl) (p1) */ - base = ((reg << 3) & 0x080) | ((reg << 7) & 0x300); - } - - setchr1r(chrram ? 0x10 : 0, A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M052Write) { - if (MMC3_WramIsWritable()) { - if (!(reg & 0x80)) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } else { - CartBW(A, V); - } - } -} - -static void M052Close(void) { - MMC3_Close(); -} - -static void M052Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M052Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M052Write); -} - -void Mapper052_Init(CartInfo *info) { - uint8 ws = info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) / 1024 : 8; - - MMC3_Init(info, ws, info->battery); - MMC3_cwrap = M052CW; - MMC3_pwrap = M052PW; - - info->Reset = M052Reset; - info->Power = M052Power; - info->Close = M052Close; - AddExState(®, 1, 0, "EXPR"); - - - if (info->CRC32 == 0xA874E216 && info->submapper != 13) { - info->submapper = 13; /* (YH-430) 97-98 Four-in-One */ - iNESCart.CHRRamSize = 8192; - } else if (info->CRC32 == 0xCCE8CA2F && info->submapper != 14) { - /* Well 8-in-1 (AB128) (Unl) (p1), with 1024 PRG and CHR is incompatible with submapper 13. - * This is reassigned to submapper 14 instead. */ - info->submapper = 14; - iNESCart.CHRRamSize = 8192; - } - - if (CHR_ROM_SIZE && iNESCart.CHRRamSize) { - CHRRAMSIZE = info->CHRRamSize ? info->CHRRamSize : 8192; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); - } -} diff --git a/src/mappers/mapper053.c b/src/mappers/mapper053.c deleted file mode 100644 index 56b36dbb2..000000000 --- a/src/mappers/mapper053.c +++ /dev/null @@ -1,79 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 053 - BMC-Supervision16in1 */ - -#include "mapinc.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x6000, 0x04 + (((reg[0] & 0x0F) << 4) | 0x0F)); - if (reg[0] & 0x10) { - setprg16(0x8000, 0x02 + (((reg[0] & 0x0F) << 3) | (reg[1] & 0x07))); - setprg16(0xc000, 0x02 + (((reg[0] & 0x0F) << 3) | 0x07)); - } else { - setprg32(0x8000, 0); - } - setchr8(0); - setmirror(((reg[0] & 0x20) >> 5) ^ 0x01); -} - -static DECLFW(M053Write6) { - if (!(reg[0] & 0x10)) { - reg[0] = V; - Sync(); - } -} - -static DECLFW(M053Write8) { - reg[1] = V; - Sync(); -} - -static void M053Power(void) { - SetWriteHandler(0x6000, 0x7FFF, M053Write6); - SetWriteHandler(0x8000, 0xFFFF, M053Write8); - SetReadHandler(0x6000, 0xFFFF, CartBR); - reg[0] = reg[1] = 0; - Sync(); -} - -static void M053Reset(void) { - reg[0] = reg[1] = 0; - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper053_Init(CartInfo *info) { - info->Power = M053Power; - info->Reset = M053Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper055.c b/src/mappers/mapper055.c deleted file mode 100644 index 3b5c877f8..000000000 --- a/src/mappers/mapper055.c +++ /dev/null @@ -1,52 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Mapper 55 - UNL-MARIO1-M0552 - * FDS Conversion - * - */ - -#include "mapinc.h" - -static void M055Power(void) { - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x6000, 0x67FF, CartBR); - SetReadHandler(0x7000, 0x77FF, CartBR); - SetWriteHandler(0x7000, 0x77FF, CartBW); - - setprg2(0x6000, 16); - setprg2r(0x10, 0x7000, 0); - setprg32(0x8000, 0); - setchr8(0); -} - -void Mapper055_Init(CartInfo *info) { - info->Power = M055Power; - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } else if (info->battery) { - WRAMSIZE = 2048; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } -} diff --git a/src/mappers/mapper056.c b/src/mappers/mapper056.c deleted file mode 100644 index 703a9823c..000000000 --- a/src/mappers/mapper056.c +++ /dev/null @@ -1,94 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * - Mapper 56 - UNL KS202 - * FDS Conversion: Super Mario Bros. 3 (Pirate, Alt) - * similar to M142 but use WRAM instead? $D000 additional IRQ trigger - * - fix IRQ counter, noticeable in status bars of both SMB2J(KS7032) and SMB3J(KS202) - */ - - #include "mapinc.h" - #include "ks202.h" - -static uint8 prg[4]; -static uint8 chr[8]; -static uint8 mirr; - -static SFORMAT M056StateRegs[] = { - { prg, 8, "PREG" }, - { chr, 8, "CREG" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - - setprg8(0x8000, (prg[0] & 0x10) | (ks202.reg[1] & 0x0F)); - setprg8(0xA000, (prg[1] & 0x10) | (ks202.reg[2] & 0x0F)); - setprg8(0xC000, (prg[2] & 0x10) | (ks202.reg[3] & 0x0F)); - setprg8(0xE000, (prg[3] & 0x10) | ( ~0 & 0x0F)); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - setmirror(mirr & 1); -} - -static DECLFW(M056Write) { - switch (A & 0xC00) { - case 0x000: prg[A & 0x03] = V; break; - case 0x800: mirr = V; break; - case 0xC00: chr[A & 0x07] = V; break; - } - ks202.reg[ks202.cmd & 0x07] = V; - Sync(); -} - -static void M056Reset(void) { - prg[0] = prg[1] = prg[2] = prg[3] = 0x10; - chr[0] = chr[1] = chr[2] = chr[3] = 0; - chr[4] = chr[5] = chr[6] = chr[7] = 0; - mirr = 0; - Sync(); -} - -static void M056Power(void) { - prg[0] = prg[1] = prg[2] = prg[3] = 0x10; - chr[0] = chr[1] = chr[2] = chr[3] = 0; - chr[4] = chr[5] = chr[6] = chr[7] = 0; - mirr = 0; - KS202_Power(); - SetWriteHandler(0xF000, 0xFFFF, M056Write); -} - -void Mapper056_Init(CartInfo *info) { - KS202_Init(info, Sync, 1, 0); - info->Power = M056Power; - info->Reset = M056Reset; - AddExState(&M056StateRegs, ~0, 0, 0); -} diff --git a/src/mappers/mapper057.c b/src/mappers/mapper057.c deleted file mode 100644 index b4af8b52c..000000000 --- a/src/mappers/mapper057.c +++ /dev/null @@ -1,90 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" - -static uint8 reg[2]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint8 prg = (reg[1] >> 5) & 0x07; - uint8 chr = ((reg[0] >> 3) & 0x08) | (reg[1] & 0x07); - - if (reg[1] & 0x10) { - setprg32(0x8000, prg >> 1); - } else { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } - if (reg[0] & 0x80) { - setchr8(chr); - } else { - setchr8((chr & ~0x03) | (reg[0] & 0x03)); - } - setmirror(((reg[1] >> 3) & 0x01) ^ 0x01); -} - -static DECLFR(M057Read) { - return dipsw & 0x03; -} - -static DECLFW(M057Write) { - if (A & 0x2000) { - reg[(A >> 11) & 0x01] = (reg[(A >> 11) & 0x01] & ~0x40) | (V & 0x40); - } else { - reg[(A >> 11) & 0x01] = V; - } - Sync(); -} - -static void M057Power(void) { - reg[1] = reg[0] = 0; /* Always reset to menu */ - dipsw = 1; /* YH-xxx "Olympic" multicarts disable the menu after one selection */ - SetReadHandler(0x5000, 0x6FFF, M057Read); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M057Write); - Sync(); -} - -static void M057Reset(void) { - reg[1] = reg[0] = 0; /* Always reset to menu */ - dipsw++; - FCEU_printf("Select Register = %02x\n", dipsw); - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper057_Init(CartInfo *info) { - info->Power = M057Power; - info->Reset = M057Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper058.c b/src/mappers/mapper058.c deleted file mode 100644 index 5bbf20b66..000000000 --- a/src/mappers/mapper058.c +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x40) { - setprg16(0x8000, latch.addr & 0x07); - setprg16(0xC000, latch.addr & 0x07); - } else { - setprg32(0x8000, (latch.addr >> 1) & 0x03); - } - setchr8((latch.addr >> 3) & 0x07); - setmirror(((latch.addr & 0x80) >> 7) ^ 0x01); -} - -void Mapper058_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper059.c b/src/mappers/mapper059.c deleted file mode 100644 index be1140504..000000000 --- a/src/mappers/mapper059.c +++ /dev/null @@ -1,73 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* iNES Mapper 59 - BMCD1038 */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static void Sync(void) { - if (latch.addr & 0x80) { - setprg16(0x8000, (latch.addr & 0x70) >> 4); - setprg16(0xC000, (latch.addr & 0x70) >> 4); - } else { - setprg32(0x8000, (latch.addr & 0x60) >> 5); - } - setchr8(latch.addr & 0x07); - setmirror(((latch.addr & 0x08) >> 3) ^ 0x01); -} - -static DECLFR(M059Read) { - if (latch.addr & 0x100) { - return (CPU_OPENBUS & ~0x03) | (dipsw & 0x03); - } - return CartBR(A); -} - -static DECLFW(M059Write) { - /* Only recognize the latch write if the lock bit has not been set. */ - /* Needed for NT-234 "Road Fighter" */ - if (!(latch.addr & 0x200)) { - Latch_Write(A, V); - } -} - -static void M059Reset(void) { - dipsw++; - /* Always reset to menu */ - latch.addr = 0; - Sync(); -} - -static void M059Power(void) { - Latch_Power(); - /* Trap latch writes to enforce the "Lock" bit */ - SetWriteHandler(0x8000, 0xFFFF, M059Write); -} - -void Mapper059_Init(CartInfo *info) { - Latch_Init(info, Sync, M059Read, FALSE, FALSE); - info->Reset = M059Reset; - info->Power = M059Power; - AddExState(&dipsw, 1, 0, "DIPSW"); -} diff --git a/src/mappers/mapper060.c b/src/mappers/mapper060.c deleted file mode 100644 index 12ea59722..000000000 --- a/src/mappers/mapper060.c +++ /dev/null @@ -1,52 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mapinc.h" - -static uint8 game = 0; - -static void Sync(void) { - setchr8(game); - setprg16(0x8000, game); - setprg16(0xC000, game); -} - -static void M060Reset(void) { - game++; - Sync(); -} - -static void M060Power(void) { - game = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper060_Init(CartInfo *info) { - info->Power = M060Power; - info->Reset = M060Reset; - GameStateRestore = StateRestore; - AddExState(&game, 1, 0, "GAME"); -} diff --git a/src/mappers/mapper061.c b/src/mappers/mapper061.c deleted file mode 100644 index e1b2994b0..000000000 --- a/src/mappers/mapper061.c +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x10) { - setprg16(0x8000, ((latch.addr & 0x0F) << 1) | ((latch.addr & 0x20) >> 5)); - setprg16(0xC000, ((latch.addr & 0x0F) << 1) | ((latch.addr & 0x20) >> 5)); - } else { - setprg32(0x8000, latch.addr & 0x0F); - } - setchr8(latch.addr >> 8 & 0x0F); - setmirror(((latch.addr >> 7) & 0x01) ^ 0x01); -} - -void Mapper061_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper062.c b/src/mappers/mapper062.c deleted file mode 100644 index 5e7e4d305..000000000 --- a/src/mappers/mapper062.c +++ /dev/null @@ -1,41 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = (latch.addr & 0x40) | ((latch.addr >> 8) & 0x3F); - - if (latch.addr & 0x20) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { - setprg32(0x8000, prg >> 1); - } - setchr8(((latch.addr & 0x1F) << 2) | (latch.data & 0x03)); - setmirror(((latch.addr >> 7) & 1) ^ 1); -} - -void Mapper062_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper063.c b/src/mappers/mapper063.c deleted file mode 100644 index 8eb59154b..000000000 --- a/src/mappers/mapper063.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Mapper 63 NTDEC-Multicart - * http://wiki.nesdev.com/w/index.php/INES_Mapper_063 - * - Powerful 250-in-1 - * - Hello Kitty 255-in-1 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg_mask = (iNESCart.submapper == 0) ? 0xFF : 0x7F; - uint8 prg_bank = (latch.addr >> 2) & prg_mask; - uint8 chr_protect = (latch.addr & ((iNESCart.submapper == 0) ? 0x400 : 0x200)) == 0; - - /* return openbus for unpopulated rom banks */ - SetReadHandler(0x8000, 0xFFFF, prg_bank >= PRG_BANK_COUNT(16) ? 0 : CartBROB); - - if (latch.addr & 2) { - setprg32(0x8000, prg_bank >> 1); - } else { - setprg16(0x8000, prg_bank); - setprg16(0xC000, prg_bank); - } - - setchr8(0); - setmirror((latch.addr & 1) ^ 1); - - /* chr-ram protect */ - SetupCartCHRMapping(0, CHRptr[0], 0x2000, chr_protect); -} - -void Mapper063_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper064.c b/src/mappers/mapper064.c deleted file mode 100644 index fd05dc8c9..000000000 --- a/src/mappers/mapper064.c +++ /dev/null @@ -1,183 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 64 - Tengen 800032 Rambo-1 - * Mapper 158 - Tengen 800037 (Alien Syndrome Unl) -*/ - -#include "mapinc.h" - -static uint8 cmd, mirr, reg[16]; -static uint8 IRQReload, IRQmode, IRQCount, IRQa, IRQLatch; -static uint8 IRQPrescaler; - -static SFORMAT StateRegs[] = { - { reg, 16, "REGS" }, - { &cmd, 1, "CMDR" }, - { &mirr, 1, "MIRR" }, - { &IRQReload, 1, "IRQR" }, - { &IRQmode, 1, "IRQM" }, - { &IRQCount, 1, "IRQC" }, - { &IRQa, 1, "IRQA" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQPrescaler, 1, "IRQP" }, - { 0 } -}; - -static void Sync(void) { - /* - 0000: R0: Select 2 (K=0) or 1 (K=1) KiB CHR bank at PPU $0000 (or $1000) - 0001: R1: Select 2 (K=0) or 1 (K=1) KiB CHR bank at PPU $0800 (or $1800) - 0010: R2: Select 1 KiB CHR bank at PPU $1000-$13FF (or $0000-$03FF) - 0011: R3: Select 1 KiB CHR bank at PPU $1400-$17FF (or $0400-$07FF) - 0100: R4: Select 1 KiB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF) - 0101: R5: Select 1 KiB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF) - 0110: R6: Select 8 KiB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF) - 0111: R7: Select 8 KiB PRG ROM bank at $A000-$BFFF - 1000: R8: If K=1, Select 1 KiB CHR bank at PPU $0400 (or $1400) - 1001: R9: If K=1, Select 1 KiB CHR bank at PPU $0C00 (or $1C00) - 1111: RF: Select 8 KiB PRG ROM bank at $C000-$DFFF (or $8000-$9FFF) - */ - setprg8(0x8000, reg[6]); - setprg8(0xA000, reg[7]); - setprg8(0xC000, reg[15]); - setprg8(0xE000, ~0); - - if (cmd & 0x20) { - setchr1(0x0000, reg[0]); - setchr1(0x0400, reg[8]); - setchr1(0x0800, reg[1]); - setchr1(0x0C00, reg[9]); - } else { - setchr1(0x0000, (reg[0] & 0xFE)); - setchr1(0x0400, (reg[0] & 0xFE) | 1); - setchr1(0x0800, (reg[1] & 0xFE)); - setchr1(0x0C00, (reg[1] & 0xFE) | 1); - } - - setchr1(0x1000, reg[2]); - setchr1(0x1400, reg[3]); - setchr1(0x1800, reg[4]); - setchr1(0x1C00, reg[5]); - - if (iNESCart.mapper == 158) { - if (cmd & 0x20) { - setntamem(NTARAM + ((reg[0] >> 7) << 10), 1, 0); - setntamem(NTARAM + ((reg[8] >> 7) << 10), 1, 1); - setntamem(NTARAM + ((reg[1] >> 7) << 10), 1, 2); - setntamem(NTARAM + ((reg[9] >> 7) << 10), 1, 3); - } else { - setntamem(NTARAM + ((reg[0] >> 7) << 10), 1, 0); - setntamem(NTARAM + ((reg[0] >> 7) << 10), 1, 1); - setntamem(NTARAM + ((reg[1] >> 7) << 10), 1, 2); - setntamem(NTARAM + ((reg[1] >> 7) << 10), 1, 3); - } - } else { - setmirror((mirr & 1) ^ 1); - } -} - -static DECLFW(M064Write) { - switch (A & 0xF001) { - case 0xA000: - mirr = V; - Sync(); - break; - case 0x8000: - cmd = V; - break; - case 0x8001: - reg[cmd & 0x0F] = V; - Sync(); - break; - case 0xC000: - IRQLatch = V; - if (IRQReload) { - IRQCount = IRQLatch; - } - break; - case 0xC001: - IRQReload = TRUE; - IRQCount = IRQLatch; - IRQmode = V & 1; - break; - case 0xE000: - IRQa = FALSE; - X6502_IRQEnd(FCEU_IQEXT); - if (IRQReload) { - IRQCount = IRQLatch; - } - break; - case 0xE001: - IRQa = TRUE; - if (IRQReload) { - IRQCount = IRQLatch; - } - break; - } -} - -static void M064Power(void) { - cmd = mirr = 0; - reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = ~0; - reg[6] = reg[7] = reg[8] = reg[9] = reg[10] = ~0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M064Write); -} - -static void StateRestore(int version) { - Sync(); -} - -static void M064CPUHook(int a) { - static int32 smallcount; - if (IRQmode) { - smallcount += a; - while (smallcount >= 4) { - smallcount -= 4; - IRQCount--; - if (IRQCount == 0xFF) - if (IRQa) X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void M064HBHook(void) { - if ((!IRQmode) && (scanline != 240)) { - IRQReload = 0; - IRQCount--; - if (IRQCount == 0xFF) { - if (IRQa) { - IRQReload = 1; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -void Mapper064_Init(CartInfo *info) { - info->Power = M064Power; - GameHBIRQHook = M064HBHook; - MapIRQHook = M064CPUHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper065.c b/src/mappers/mapper065.c deleted file mode 100644 index 4ebf8f842..000000000 --- a/src/mappers/mapper065.c +++ /dev/null @@ -1,153 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[2], chr[8], mirr, cmd; -static uint8 IRQa; -static int16 IRQCount, IRQLatch; - -static SFORMAT StateRegs[] = { - { &cmd, 1, "CMD0" }, - { prg, 2, "PREG" }, - { chr, 8, "CREG" }, - { &mirr, 1, "MIRR" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 2, "IRQC" }, - { &IRQLatch, 2, "IRQL" }, - { 0 } -}; - -static void Sync(void) { - if (cmd & 0x80) { - setprg8(0x8000, ~1); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[0]); - setprg8(0xE000, ~0); - } else { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); - } - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - switch (mirr >> 6) { - case 0: - setmirror(MI_V); - break; - case 2: - setmirror(MI_H); - break; - default: - setmirror(MI_0); - break; - } -} - -static DECLFW(M065Write) { - switch (A & 0xF000) { - case 0x8000: - case 0xA000: - prg[(A >> 13) & 0x01] = V; - Sync(); - break; - case 0x9000: - switch (A & 0x07) { - case 0: - cmd = V; - Sync(); - break; - case 1: - mirr = V; - Sync(); - break; - case 3: - IRQa = V & 0x80; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 4: - IRQCount = IRQLatch; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 5: - IRQLatch &= 0x00FF; - IRQLatch |= V << 8; - break; - case 6: - IRQLatch &= 0xFF00; - IRQLatch |= V; - break; - } - break; - case 0xB000: - chr[A & 0x07] = V; - Sync(); - break; - } -} - -static void M065Power(void) { - prg[0] = 0; - prg[1] = 1; - - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - chr[4] = 4; - chr[5] = 5; - chr[6] = 6; - chr[7] = 7; - - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xBFFF, M065Write); -} - -static void M065IRQ(int a) { - if (IRQa) { - IRQCount -= a; - if (IRQCount <= 0) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper065_Init(CartInfo *info) { - info->Power = M065Power; - MapIRQHook = M065IRQ; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper066.c b/src/mappers/mapper066.c deleted file mode 100644 index c40f30fed..000000000 --- a/src/mappers/mapper066.c +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, (latch.data >> 4) & 0x07); - setchr8(latch.data & 0x0F); -} - -void Mapper066_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper067.c b/src/mappers/mapper067.c deleted file mode 100644 index b852dcfcf..000000000 --- a/src/mappers/mapper067.c +++ /dev/null @@ -1,126 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg, chr[4], mirr; -static uint8 IRQa, toggle = 0; -static int16 IRQCount, IRQLatch; - -static SFORMAT StateRegs[] = { - { &prg, 1, "PREG" }, - { &toggle, 1, "TOGL" }, - { chr, 4, "CREG" }, - { &mirr, 1, "MIRR" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 2, "IRQC" }, - { &IRQLatch, 2, "IRQL" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, prg); - setprg16(0xC000, ~0); - - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr2(0x1000, chr[2]); - setchr2(0x1800, chr[3]); - - switch (mirr & 0x03) { - case 0: - setmirror(MI_V); - break; - case 1: - setmirror(MI_H); - break; - case 2: - setmirror(MI_0); - break; - case 3: - setmirror(MI_1); - break; - } -} - -static DECLFW(M067Write) { - switch (A & 0xF800) { - case 0x8800: - case 0x9800: - case 0xA800: - case 0xB800: - chr[(A >> 12) & 0x03] = V; - Sync(); - break; - case 0xC000: - case 0xC800: - IRQCount &= 0xFF << (toggle << 3); - IRQCount |= V << ((toggle ^ 1) << 3); - toggle ^= 1; - break; - case 0xD800: - toggle = 0; - IRQa = V & 0x10; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xE800: - mirr = V; - Sync(); - break; - case 0xF800: - prg = V; - Sync(); - break; - } -} - -static void M067Power(void) { - prg = 0; - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - IRQa = IRQCount = IRQLatch = toggle = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M067Write); -} - -static void M067IRQ(int a) { - if (IRQa) { - IRQCount -= a; - if (IRQCount < 0) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper067_Init(CartInfo *info) { - info->Power = M067Power; - MapIRQHook = M067IRQ; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper068.c b/src/mappers/mapper068.c deleted file mode 100644 index a43bac57f..000000000 --- a/src/mappers/mapper068.c +++ /dev/null @@ -1,150 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -/* FIXME: needs updating, submapper 1 support etc */ - -static uint8 chr[4]; -static uint8 nt[2]; -static uint8 kogame, prg, mirr; -static uint32 count; - -static SFORMAT StateRegs[] = { - { &mirr, 1, "MIRR" }, - { &prg, 1, "PRG" }, - { &kogame, 1, "KGME" }, - { &count, 4, "CNT" }, - { chr, 4, "CHR" }, - { nt, 2, "NTAR" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg16r((PRGptr[1]) ? kogame : 0, 0x8000, prg); - setprg16(0xC000, 0x07); - - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr2(0x1000, chr[2]); - setchr2(0x1800, chr[3]); - - switch (mirr & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } - - if (mirr & 0x10) { - int i; - PPUNTARAM = 0; - for (i = 0; i < 4; i++) { - switch (mirr & 0x03) { - case 0: vnapage[i] = CHRptr[0] + (((nt[i & 0x01] | 0x80) & CHRmask1[0]) << 10); break; - case 1: vnapage[i] = CHRptr[0] + (((nt[(i >> 0x01) & 0x01] | 0x80) & CHRmask1[0]) << 10); break; - case 2: vnapage[i] = CHRptr[0] + (((nt[0] | 0x80) & CHRmask1[0]) << 10); break; - case 3: vnapage[i] = CHRptr[0] + (((nt[1] | 0x80) & CHRmask1[0]) << 10); break; - } - } - } -} - -static DECLFR(M68Read) { - if (!(kogame & 0x08)) { - count++; - if (count == 1784) { - setprg16r(0, 0x8000, prg); - } - } - return CartBR(A); -} - -static DECLFW(M68WriteLo) { - if (!V) { - count = 0; - setprg16r((PRGptr[1]) ? kogame : 0, 0x8000, prg); - } - CartBW(A, V); -} - -static DECLFW(M068Write) { - switch (A & 0xF000) { - case 0x8000: - case 0x9000: - case 0xA000: - case 0xB000: - chr[(A >> 12) & 0x03] = V; - Sync(); - break; - case 0xC000: - case 0xD000: - nt[(A >> 12) & 0x01] = V; - Sync(); - break; - case 0xE000: - mirr = V; - Sync(); - break; - case 0xF000: - prg = V & 0x07; - kogame = ((V >> 3) & 0x01) ^ 0x01; - Sync(); - break; - } -} - -static void M68Power(void) { - prg = 0; - kogame = 0; - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetReadHandler(0x8000, 0xBFFF, M68Read); - SetReadHandler(0xC000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M068Write); - SetWriteHandler(0x6000, 0x6000, M68WriteLo); - SetWriteHandler(0x6001, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M68Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper068_Init(CartInfo *info) { - info->Power = M68Power; - info->Close = M68Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } -} diff --git a/src/mappers/mapper069.c b/src/mappers/mapper069.c deleted file mode 100644 index 07b86688d..000000000 --- a/src/mappers/mapper069.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "s5bsound.h" -#include "fme7.h" - -static void M069PW(uint16 A, uint16 V) { - setprg8(A, V & 0x3F); -} - -static void M069CW(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -void Mapper069_Init(CartInfo *info) { - FME7_Init(info, TRUE, info->battery); - FME7_pwrap = M069PW; - FME7_cwrap = M069CW; -} diff --git a/src/mappers/mapper070.c b/src/mappers/mapper070.c deleted file mode 100644 index d42a50ac4..000000000 --- a/src/mappers/mapper070.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.data >> 4); - setprg16(0xc000, ~0); - setchr8(latch.data & 0x0F); -} - -void Mapper070_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper071.c b/src/mappers/mapper071.c deleted file mode 100644 index 1527dd444..000000000 --- a/src/mappers/mapper071.c +++ /dev/null @@ -1,74 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg, mirr; - -static SFORMAT StateRegs[] = { - { &prg, 1, "PREG" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, prg); - setprg16(0xC000, ~0); - setchr8(0); - /* Fire Hawk or submapper 1, otherwise hard-mirroring */ - if (mirr) { - setmirror(mirr); - } -} - -static DECLFW(M071Write) { - switch (A & 0xF000) { - case 0x9000: - mirr = MI_0 + ((V >> 4) & 0x01); - Sync(); - break; - case 0xC000: - case 0xD000: - case 0xE000: - case 0xF000: - prg = V; - Sync(); - break; - } -} - -static void M071Power(void) { - prg = 0; - mirr = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x9000, 0xFFFF, M071Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper071_Init(CartInfo *info) { - info->Power = M071Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper072.c b/src/mappers/mapper072.c deleted file mode 100644 index 2ba80e790..000000000 --- a/src/mappers/mapper072.c +++ /dev/null @@ -1,80 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Mapper 72: - * Moero!! Pro Tennis have ADPCM codec on-board, PROM isn't dumped, emulation isn't - * possible just now. - * - * Mapper 092 - * Another two-in-one mapper, two Jaleco carts uses similar - * hardware, but with different wiring. - * Original code provided by LULU - * Additionally, PCB contains DSP extra sound chip, used for voice samples (unemulated) - * This mapper is identical to mapper 072 except for the different PRG Setup. - */ - -#include "mapinc.h" - -static uint8 prg, chr, reg; - -static SFORMAT StateRegs[] = { - { &prg, 1, "PREG" }, - { &chr, 1, "CREG" }, - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - if (iNESCart.mapper == 92) { - setprg16(0x8000, 0); - setprg16(0xC000, prg); - setchr8(chr); - } else { - setprg16(0x8000, prg); - setprg16(0xC000, ~0); - setchr8(chr); - } -} - -static DECLFW(M072Write) { - V &= CartBR(A); /* bus conflict */ - - reg = (reg ^ V) & V; - if (reg & 0x80) prg = V; - if (reg & 0x40) chr = V; - - Sync(); -} - -static void M072Power(void) { - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M072Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper072_Init(CartInfo *info) { - info->Power = M072Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper073.c b/src/mappers/mapper073.c deleted file mode 100644 index 7649d9f32..000000000 --- a/src/mappers/mapper073.c +++ /dev/null @@ -1,131 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Konami VRC-3 - * - */ - -#include "mapinc.h" - -static uint8 prg; -static uint8 IRQx; /* autoenable */ -static uint8 IRQm; /* mode */ -static uint8 IRQa; -static uint16 IRQLatch, IRQCount; - -static SFORMAT StateRegs[] = { - { &prg, 1, "PREG" }, - { &IRQa, 1, "IRQA" }, - { &IRQx, 1, "IRQX" }, - { &IRQm, 1, "IRQM" }, - { &IRQLatch, 2, "IRQL" }, - { &IRQCount, 2, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, prg); - setprg16(0xC000, ~0); - setchr8(0); -} - -static DECLFW(M073Write) { - switch (A & 0xF000) { - case 0x8000: - IRQLatch &= 0xFFF0; - IRQLatch |= (V & 0x0F) << 0; - break; - case 0x9000: - IRQLatch &= 0xFF0F; - IRQLatch |= (V & 0x0F) << 4; - break; - case 0xA000: - IRQLatch &= 0xF0FF; - IRQLatch |= (V & 0x0F) << 8; - break; - case 0xB000: - IRQLatch &= 0x0FFF; - IRQLatch |= (V & 0x0F) << 12; - break; - case 0xC000: - IRQm = V & 0x04; - IRQx = V & 0x01; - IRQa = V & 0x02; - if (IRQa) { - IRQCount = IRQLatch; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xD000: - X6502_IRQEnd(FCEU_IQEXT); - IRQa = IRQx; - break; - case 0xF000: - prg = V; - Sync(); - break; - } -} - -static void M073IRQHook(int a) { - int32 i; - - if (IRQa) { - for (i = 0; i < a; i++) { - uint32 IRQCountMask = IRQm ? 0xFF : 0xFFFF; - if ((IRQCount & IRQCountMask) == IRQCountMask) { - IRQCount = IRQLatch; - X6502_IRQBegin(FCEU_IQEXT); - } else { - IRQCount++; - } - } - } -} - -static void M073Power(void) { - IRQLatch = IRQm = IRQx = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, M073Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M073Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper073_Init(CartInfo *info) { - info->Power = M073Power; - info->Close = M073Close; - MapIRQHook = M073IRQHook; - AddExState(StateRegs, ~0, 0, NULL); - GameStateRestore = StateRestore; - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper074.c b/src/mappers/mapper074.c deleted file mode 100644 index afd48f469..000000000 --- a/src/mappers/mapper074.c +++ /dev/null @@ -1,45 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M074CW(uint16 A, uint16 V) { - if ((V & ~0x01) == 0x08) { /* Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes, Ji Jia Zhan Shi (As).nes */ - setchr1r(0x10, A, V & 0x01); - } else { - setchr1(A, V); - } -} - -static void M074Close(void) { - MMC3_Close(); -} - -void Mapper074_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - info->Close = M074Close; - MMC3_cwrap = M074CW; - - CHRRAMSIZE = 2048; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper075.c b/src/mappers/mapper075.c deleted file mode 100644 index 64488e01b..000000000 --- a/src/mappers/mapper075.c +++ /dev/null @@ -1,91 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Konami VRC-1 - * - */ - -#include "mapinc.h" - -static uint8 prg[3], chr[2], mode; - -static SFORMAT StateRegs[] = { - { &mode, 1, "MODE" }, - { chr, 2, "CREG" }, - { prg, 3, "PREG" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, ~0); - - setchr4(0x0000, (chr[0] & 0x0F) | ((mode & 2) << 3)); - setchr4(0x1000, (chr[1] & 0x0F) | ((mode & 4) << 2)); - - if (iNESCart.mirror != 2) { /* VS rom conversion uses 4-screen mirroring */ - setmirror((mode & 1) ^ 1); - } -} - -static DECLFW(M75Write) { - switch (A & 0xF000) { - case 0x8000: - case 0xA000: - case 0xC000: - prg[(A >> 13) & 0x03] = V; - Sync(); - break; - case 0x9000: - mode = V; - Sync(); - break; - case 0xE000: - case 0xF000: - chr[(A >> 12) & 0x01] = V; - Sync(); - break; - } -} - -static void M75Power(void) { - Sync(); - SetWriteHandler(0x8000, 0xFFFF, M75Write); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper075_Init(CartInfo *info) { - info->Power = M75Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} - -void Mapper151_Init(CartInfo *info) { - Mapper075_Init(info); - /*info->mirror = 2; - setmirror(MI_4);*/ -} - diff --git a/src/mappers/mapper076.c b/src/mappers/mapper076.c deleted file mode 100644 index 9426f57fb..000000000 --- a/src/mappers/mapper076.c +++ /dev/null @@ -1,48 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 076 - * iNES Mapper 076 represents NAMCOT-3446, a board used onlyfor the game - * Megami Tensei: Digital Devil Story. - * It rewires the Namcot 108 mapper IC to be able to address 128 KiB of CHR, - * in exchange for coarser CHR banking. - * The PCB also has a 7432 which allows the use of a 28-pin CHR-ROM. - * https://www.nesdev.org/wiki/INES_Mapper_076 - */ - -#include "mapinc.h" -#include "n118.h" - -static void M076PW(uint16 A, uint16 V) { - setprg8(A, V & 0x1F); /* support for PRG bank for fan translations */ -} - -static void M076FixCHR(void) { - setchr2(0x0000, n118.reg[2] & 0x3F); - setchr2(0x0800, n118.reg[3] & 0x3F); - setchr2(0x1000, n118.reg[4] & 0x3F); - setchr2(0x1800, n118.reg[5] & 0x3F); -} - -void Mapper076_Init(CartInfo *info) { - N118_Init(info, 0, 0); - N118_pwrap = M076PW; - N118_FixCHR = M076FixCHR; -} diff --git a/src/mappers/mapper077.c b/src/mappers/mapper077.c deleted file mode 100644 index 1c2f4db73..000000000 --- a/src/mappers/mapper077.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.data & 0x0F); - setchr2(0x0000, latch.data >> 4); - setchr2r(0x10, 0x0800, 2); - setchr4r(0x10, 0x1000, 0); -} - -static void M077Close(void) { - Latch_Close(); -} - -void Mapper077_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Close = M077Close; - - CHRRAMSIZE = 6 * 1024; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); -} diff --git a/src/mappers/mapper078.c b/src/mappers/mapper078.c deleted file mode 100644 index 55c63393c..000000000 --- a/src/mappers/mapper078.c +++ /dev/null @@ -1,43 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Map 78 */ -/* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */ -/* Submapper 1 - Uchuusen - Cosmo Carrier ( one-screen mirroring ) */ -/* Submapper 3 - Holy Diver ( horizontal/vertical mirroring ) */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.data & 0x07); - setprg16(0xc000, ~0); - setchr8(latch.data >> 4); - if (iNESCart.submapper == 3) { - setmirror((latch.data >> 3) & 0x01); - } else { - setmirror(MI_0 + ((latch.data >> 3) & 0x01)); - } -} - -void Mapper078_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper079.c b/src/mappers/mapper079.c deleted file mode 100644 index 7d1f12595..000000000 --- a/src/mappers/mapper079.c +++ /dev/null @@ -1,59 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, (reg >> 3) & 0x01); - setchr8(reg & 0x07); -} - -static DECLFW(M79Write) { - if (A & 0x100) { - reg = V; - Sync(); - } -} - -static void M079Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, M79Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper079_Init(CartInfo *info) { - info->Power = M079Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper080.c b/src/mappers/mapper080.c deleted file mode 100644 index 8928dd6f9..000000000 --- a/src/mappers/mapper080.c +++ /dev/null @@ -1,125 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[3], chr[6], mirr; -static uint8 wram[256]; - -static SFORMAT StateRegs[] = { - { prg, 3, "PREG" }, - { chr, 6, "CREG" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, ~0); - - setchr2(0x0000, chr[0] >> 1); - setchr2(0x0800, chr[1] >> 1); - setchr1(0x1000, chr[2]); - setchr1(0x1400, chr[3]); - setchr1(0x1800, chr[4]); - setchr1(0x1C00, chr[5]); - - if (iNESCart.mapper == 207) { - setmirrorw(chr[0] >>7, chr[0] >>7, chr[1] >>7, chr[1] >>7); - } else { - setmirror(mirr & 0x01); - } -} - -static DECLFW(M080RamWrite) { - wram[A & 0xFF] = V; -} - -static DECLFR(M080RamRead) { - return wram[A & 0xFF]; -} - -static DECLFW(M080Write) { - switch (A) { - case 0x7EF0: - case 0x7EF1: - case 0x7EF2: - case 0x7EF3: - case 0x7EF4: - case 0x7EF5: - chr[A & 0x07] = V; - Sync(); - break; - case 0x7EF6: - mirr = V; - Sync(); - break; - case 0x7EF8: - break; - case 0x7EFA: - case 0x7EFB: - case 0x7EFC: - case 0x7EFD: - case 0x7EFE: - case 0x7EFF: - prg[(A - 0x7EFA) >> 1] = V; - Sync(); - break; - } -} - -static void M080Power(void) { - Sync(); - SetReadHandler(0x7F00, 0x7FFF, M080RamRead); - SetWriteHandler(0x7F00, 0x7FFF, M080RamWrite); - SetWriteHandler(0x7EF0, 0x7EFF, M080Write); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void M207Power(void) { - Sync(); - SetWriteHandler(0x7EF0, 0x7EFF, M080Write); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper080_Init(CartInfo *info) { - info->Power = M080Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - if (info->battery) { - info->SaveGame[0] = wram; - info->SaveGameLen[0] = 256; - AddExState(wram, sizeof(wram), 0, "WRAM"); - } -} - -void Mapper207_Init(CartInfo *info) { - info->Power = M207Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper081.c b/src/mappers/mapper081.c deleted file mode 100644 index 405bd1e46..000000000 --- a/src/mappers/mapper081.c +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, (latch.addr >> 2) & 3); - setprg16(0xC000, ~0); - setchr8(latch.data & 3); -} - -void Mapper081_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper082.c b/src/mappers/mapper082.c deleted file mode 100644 index 7536083b4..000000000 --- a/src/mappers/mapper082.c +++ /dev/null @@ -1,145 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Taito X1-017 board, battery backed - * NES 2.0 Mapper 552 represents the actual way the mask ROM is connected and is thus - * the correct bank order, while iNES Mapper 082 represents the bank order as it was - * understood before January 2020 when the mapper was reverse-engineered. - */ - -#include "mapinc.h" - -static uint8 chr[6], prg[3], protect[3], ctrl; - -static SFORMAT StateRegs[] = { - { prg, 3, "PREGS" }, - { chr, 6, "CREGS" }, - { protect, 3, "PROT" }, - { &ctrl, 1, "CTRL" }, - - { 0 } -}; - -static uint32 GetPRGBank(uint8 V) { - if (iNESCart.mapper == 552) { - return (((V << 5) & 0x20) | - ((V << 3) & 0x10) | - ((V << 1) & 0x08) | - ((V >> 1) & 0x04) | - ((V >> 3) & 0x02) | - ((V >> 5) & 0x01)); - } - return V >> 2; -} - -static void Sync(void) { - uint32 swap = ((ctrl & 2) << 11); - - setprg8r(0x10, 0x6000, 0); - - setprg8(0x8000, GetPRGBank(prg[0])); - setprg8(0xA000, GetPRGBank(prg[1])); - setprg8(0xC000, GetPRGBank(prg[2])); - setprg8(0xE000, ~0); - - setchr2(0x0000 ^ swap, chr[0] >> 1); - setchr2(0x0800 ^ swap, chr[1] >> 1); - setchr1(0x1000 ^ swap, chr[2]); - setchr1(0x1400 ^ swap, chr[3]); - setchr1(0x1800 ^ swap, chr[4]); - setchr1(0x1C00 ^ swap, chr[5]); - - setmirror(ctrl & 0x01); -} - -static DECLFR(ReadWRAM) { - if (((A >= 0x6000) && (A <= 0x67FF) && (protect[0] == 0xCA)) || - ((A >= 0x6800) && (A <= 0x6FFF) && (protect[1] == 0x69)) || - ((A >= 0x7000) && (A <= 0x73FF) && (protect[2] == 0x84))) { - return CartBR(A); - } - return CPU_OPENBUS; -} - -static DECLFW(WriteWRAM) { - if (((A >= 0x6000) && (A <= 0x67FF) && (protect[0] == 0xCA)) || - ((A >= 0x6800) && (A <= 0x6FFF) && (protect[1] == 0x69)) || - ((A >= 0x7000) && (A <= 0x73FF) && (protect[2] == 0x84))) { - CartBW(A, V); - } -} - -static DECLFW(M082Write) { - switch (A & 0x0F) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: chr[A & 7] = V; break; - case 0x06: ctrl = V & 3; break; - case 0x07: protect[0] = V; break; - case 0x08: protect[1] = V; break; - case 0x09: protect[2] = V; break; - case 0x0A: prg[0] = V; break; - case 0x0B: prg[1] = V; break; - case 0x0C: prg[2] = V; break; - default: - /* IRQ emulation ignored since no commercial games uses it */ - return; - } - Sync(); -} - -static void M082Power(void) { - Sync(); - SetReadHandler(0x6000, 0xffff, CartBR); - SetReadHandler(0x6000, 0x73ff, ReadWRAM); - SetWriteHandler(0x6000, 0x73ff, WriteWRAM); - SetWriteHandler(0x7ef0, 0x7eff, M082Write); /* external WRAM might end at $73FF */ - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M082Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper082_Init(CartInfo *info) { - info->Power = M082Power; - info->Close = M082Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } -} - -void Mapper552_Init(CartInfo *info) { - Mapper082_Init(info); -} diff --git a/src/mappers/mapper083.c b/src/mappers/mapper083.c deleted file mode 100644 index e0da6b960..000000000 --- a/src/mappers/mapper083.c +++ /dev/null @@ -1,268 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * YOKO mapper, almost the same as 83, TODO: figure out difference - * Mapper 83 - 30-in-1 mapper, two modes for single game carts, one mode for - * multigame Dragon Ball Z Party - * - * Mortal Kombat 2 YOKO - * N-CXX(M), XX - PRG+CHR, 12 - 128+256, 22 - 256+256, 14 - 128+512 - * - */ - -/* - * iNES Mapper 083 also knows as Yoko - * 256 KiB CHR-ROM => Submapper 0 (1 KiB CHR-ROM banking, no WRAM) - * - Street Fighter II Pro/Street Blaster II Pro - * - Street Fighter IV Pro 10/Street Blaster IV Pro 10 - * - Street Blaster V Turbo 20 - * - Street Fighter X Turbo 40 - * - Fatal Fury 2/餓狼伝説 2 - * - Fatal Fury 2'/餓狼伝説 2' - * 512 KiB CHR-ROM => Submapper 1 (2 KiB CHR-ROM banking, no WRAM) - * - Super Blaster VII Turbo 28 - * - World Heroes 2/快打英雄榜 2 - * - World Heroes 2 Pro//快打英雄榜 2 Pro - * 1024 KiB CHR-ROM => Submapper 2 (1 KiB CHR-ROM banking with outer bank, 32 KiB banked WRAM) - * - Dragon Ball Party - * - * NES 2.0 264 - UNL-Yoko - * - Mortal Kombat II/V Pro - * - Master Fighter VI' -*/ - -#include "mapinc.h" - -static uint8 prg[4], chr[8], low[4]; -static uint8 mode, bank, dip; -static uint8 IRQa; -static int32 IRQCount; - -static uint8 prgMask; -static uint8 chrMode; -static uint16 dipMask; - -static SFORMAT StateRegs[] = -{ - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { &mode, 1, "MODE" }, - { &bank, 1, "BANK" }, - { &IRQCount, 4, "IRQC" }, - { &IRQa, 1, "IRQA" }, - { low, 4, "LOWR" }, - { 0 } -}; - -static void M083Sync(void) { - uint8 prgMode = (mode >> 3) & 0x03; - uint8 mirr = mode & 0x03; - - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, (bank >> 6)); - } else if (mode & 0x20) { - setprg8(0x6000, prg[3]); - } - switch (prgMode) { - case 0: - setprg16(0x8000, bank); - setprg16(0xC000, bank | (prgMask >> 1)); - break; - case 1: - setprg32(0x8000, bank >> 1); - break; - case 2: - case 3: - setprg8(0x8000, ((bank << 1) & ~prgMask) | (prg[0] & prgMask)); - setprg8(0xA000, ((bank << 1) & ~prgMask) | (prg[1] & prgMask)); - setprg8(0xC000, ((bank << 1) & ~prgMask) | (prg[2] & prgMask)); - setprg8(0xE000, ((bank << 1) & ~prgMask) | (~0 & prgMask)); - break; - } - switch (chrMode) { - case 0: - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - break; - case 1: - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr2(0x1000, chr[6]); - setchr2(0x1800, chr[7]); - break; - case 2: - setchr1(0x0000, ((bank << 4) & 0x300) | chr[0]); - setchr1(0x0400, ((bank << 4) & 0x300) | chr[1]); - setchr1(0x0800, ((bank << 4) & 0x300) | chr[2]); - setchr1(0x0C00, ((bank << 4) & 0x300) | chr[3]); - setchr1(0x1000, ((bank << 4) & 0x300) | chr[4]); - setchr1(0x1400, ((bank << 4) & 0x300) | chr[5]); - setchr1(0x1800, ((bank << 4) & 0x300) | chr[6]); - setchr1(0x1C00, ((bank << 4) & 0x300) | chr[7]); - break; - } - switch (mirr) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -static DECLFW(M083Write) { - if (iNESCart.mapper == 264) { - A = ((A >> 2) & 0x3C0) | (A & 0x3F); - } - switch (A & 0x300) { - case 0x000: - bank = V; - break; - case 0x100: - mode = V; - break; - case 0x200: - if (A & 0x01) { - IRQa = mode & 0x80; - IRQCount &= 0xFF; - IRQCount |= V << 8; - } else { - IRQCount &= 0xFF00; - IRQCount |= V; - X6502_IRQEnd(FCEU_IQEXT); - } - break; - case 0x300: - A &= 0x1F; - if (A < 0x10) { - prg[A & 0x03] = V; - } else if (A < 0x18) { - chr[A & 0x07] = V; - } - break; - } - M083Sync(); -} - -static DECLFR(M083ReadLow) { - if (A & dipMask) { - return low[A & 3]; - } - return dip; -} - -static DECLFW(M083WriteLow) { - low[A & 3] = V; -} - -static void M083Power(void) { - mode = 0x10; - bank = 0; - dip = (iNESCart.mapper == 264) ? 0x01 : 0x00; - M083Sync(); - SetReadHandler(0x5000, 0x5FFF, M083ReadLow); - SetWriteHandler(0x5000, 0x5FFF, M083WriteLow); - SetReadHandler(0x6000, 0x7fff, CartBR); - SetReadHandler(0x8000, 0xffff, CartBR); - SetWriteHandler(0x8000, 0xffff, M083Write); - if (WRAMSIZE) { - SetWriteHandler(0x6000, 0x7fff, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - - } -} - -static void M083Reset(void) { - dip++; - if (iNESCart.mapper == 264) { - dip &= 3; - } else { - dip &= 1; - } - mode = bank = 0; - M083Sync(); -} - -static void M083Close(void) { -} - -static void M083IRQHook(int a) { - if (IRQa && (IRQCount > 0)) { - if (mode & 0x40) { - IRQCount -= a; - } else { - IRQCount += a; - } - if (IRQCount <= 0) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - } - } -} - -static void M083StateRestore(int version) { - M083Sync(); -} - -void Mapper083_Init(CartInfo *info) { - info->Power = M083Power; - info->Reset = M083Reset; - info->Close = M083Close; - MapIRQHook = M083IRQHook; - GameStateRestore = M083StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - if (!info->iNES2) { - if (CHR_ROM_SIZE >= (1024 * 1024)) { - info->submapper = 2; - } else if (CHR_ROM_SIZE >= (512 * 1024)) { - info->submapper = 1; - } - } - - chrMode = info->submapper; - prgMask = 0x1F; - dipMask = 0x100; - - WRAMSIZE = (info->submapper == 2) ? 32768 : 0; - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } -} - -void Mapper264_Init(CartInfo *info) { - info->Power = M083Power; - info->Reset = M083Reset; - info->Close = M083Close; - MapIRQHook = M083IRQHook; - GameStateRestore = M083StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - chrMode = 1; - prgMask = 0x0F; - dipMask = 0x400; -} diff --git a/src/mappers/mapper085.c b/src/mappers/mapper085.c deleted file mode 100644 index 37b2888fb..000000000 --- a/src/mappers/mapper085.c +++ /dev/null @@ -1,42 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - */ - -#include "mapinc.h" -#include "vrc7.h" - -static void M085PW(uint16 A, uint16 V) { - setprg8(A, V & 0x3F); -} - -static void M085CW(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -void Mapper085_Init(CartInfo *info) { - switch (info->submapper) { - case 0x01: VRC7_Init(info, 0x08, 0x20); break; - case 0x02: VRC7_Init(info, 0x10, 0x20); break; - default: VRC7_Init(info, 0x18, 0x20); break; - } - VRC7_pwrap = M085PW; - VRC7_cwrap = M085CW; -} diff --git a/src/mappers/mapper086.c b/src/mappers/mapper086.c deleted file mode 100644 index ca40f199c..000000000 --- a/src/mappers/mapper086.c +++ /dev/null @@ -1,57 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* TODO: ADPCM not emulated */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, (reg >> 4) & 0x03); - setchr8(((reg >> 4) & 0x04) | (reg & 0x03)); -} - -static DECLFW(M086Write) { - reg = V; - Sync(); -} - -static void M086Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x6FFF, M086Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper086_Init(CartInfo *info) { - info->Power = M086Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper087.c b/src/mappers/mapper087.c deleted file mode 100644 index 8344b2a3f..000000000 --- a/src/mappers/mapper087.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, 0); - setchr8(((reg << 1) & 0x02) | ((reg >> 1) & 0x01)); -} - -static DECLFW(M087Write) { - reg = V; - Sync(); -} - -static void M087Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, M087Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper087_Init(CartInfo *info) { - info->Power = M087Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper088.c b/src/mappers/mapper088.c deleted file mode 100644 index bf7778bcc..000000000 --- a/src/mappers/mapper088.c +++ /dev/null @@ -1,36 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "n118.h" - -static void M088FixCHR(void) { - setchr2(0x0000, (n118.reg[0] & 0x3F) >> 1); - setchr2(0x0800, (n118.reg[1] & 0x3F) >> 1); - setchr1(0x1000, 0x40 | (n118.reg[2] & 0x3F)); - setchr1(0x1400, 0x40 | (n118.reg[3] & 0x3F)); - setchr1(0x1800, 0x40 | (n118.reg[4] & 0x3F)); - setchr1(0x1C00, 0x40 | (n118.reg[5] & 0x3F)); -} - -void Mapper088_Init(CartInfo *info) { - N118_Init(info, 0, 0); - N118_FixCHR = M088FixCHR; -} diff --git a/src/mappers/mapper089.c b/src/mappers/mapper089.c deleted file mode 100644 index 8013a021f..000000000 --- a/src/mappers/mapper089.c +++ /dev/null @@ -1,34 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, (latch.data >> 4) & 0x07); - setprg16(0xC000, ~0); - setchr8((latch.data & 0x07) | ((latch.data >> 4) & 0x08)); - setmirror(MI_0 + ((latch.data >> 3) & 0x01)); -} - -void Mapper089_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper091.c b/src/mappers/mapper091.c deleted file mode 100644 index 228057b90..000000000 --- a/src/mappers/mapper091.c +++ /dev/null @@ -1,162 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2020 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* added 2020-2-15 - * Street Fighter 3, Mortal Kombat II, Dragon Ball Z 2, Mario & Sonic 2 (JY-016) - * 1995 Super HIK 4-in-1 (JY-016), 1995 Super HiK 4-in-1 (JY-017) - * submapper 1 - Super Fighter III - * NOTE: nesdev's notes for IRQ is different that whats implemented here - */ - -#include "mapinc.h" - -static uint8 chr[4], prg[2]; -static uint8 outerbank; -static uint8 mirr; - -static uint8 IRQa; -static uint8 IRQPrescaler; -static uint8 IRQCount; -static int16 IRQCount16; - -static SFORMAT StateRegs[] = { - { chr, 4, "CREG" }, - { prg, 2, "PREG" }, - { &IRQa, 1, "IRQA" }, - { &IRQPrescaler, 1, "IRQP" }, - { &IRQCount, 1, "IRQC" }, - { &IRQCount16, 4, "IRQ2" }, - { &outerbank, 1, "OUTB" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - /* FCEU_printf("P0:%02x P1:%02x outerbank:%02x\n", prg[0], prg[1], outerbank);*/ - setprg8(0x8000, ((outerbank << 3) & ~0x0F) | prg[0]); - setprg8(0xa000, ((outerbank << 3) & ~0x0F) | prg[1]); - setprg8(0xc000, ((outerbank << 3) & ~0x0F) | 0x0E); - setprg8(0xe000, ((outerbank << 3) & ~0x0F) | 0x0F); - - setchr2(0x0000, ((outerbank << 8) & 0x100) | chr[0]); - setchr2(0x0800, ((outerbank << 8) & 0x100) | chr[1]); - setchr2(0x1000, ((outerbank << 8) & 0x100) | chr[2]); - setchr2(0x1800, ((outerbank << 8) & 0x100) | chr[3]); - - if (iNESCart.submapper != 0) { - setmirror((mirr & 0x01) ^ 0x01); - } -} - -static DECLFW(M091CHRWrite) { - if (iNESCart.submapper == 1) { - switch (A & 0x07) { - case 0: - case 1: - case 2: - case 3: - chr[A & 0x03] = V; - Sync(); - break; - case 4: - case 5: - mirr = V; - Sync(); - break; - case 6: - IRQCount16 = (IRQCount16 & 0xFF00) | V; - break; - case 7: - IRQCount16 = (IRQCount16 & 0x00FF) | (V << 8); - break; - } - } else { - chr[A & 0x03] = V; - Sync(); - } -} - -static DECLFW(M091IRQWrite) { - switch (A & 0x03) { - case 0: - case 1: - prg[A & 0x01] = V; - Sync(); - break; - case 2: - IRQa = IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: - IRQa = 1; - IRQPrescaler = 3; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -static DECLFW(M091OuterBankWrite) { - outerbank = A & 0xFF; - Sync(); -} - -static void M091Power(void) { - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x6FFF, M091CHRWrite); - SetWriteHandler(0x7000, 0x7FFF, M091IRQWrite); - SetWriteHandler(0x8000, 0x9FFF, M091OuterBankWrite); -} - -static void M091HBHook(void) { - if ((IRQCount < 8) && IRQa) { - IRQCount++; - if (IRQCount >= 8) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void M091IRQHook(int a) { - IRQPrescaler += a; - if (IRQPrescaler >= 4) { - IRQPrescaler -= 4; - IRQCount16 -= 5; - if ((IRQCount16 <= 0) && IRQa) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper091_Init(CartInfo *info) { - info->Power = M091Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - if (info->submapper == 1) { - MapIRQHook = M091IRQHook; - } else { - GameHBIRQHook = M091HBHook; - } -} diff --git a/src/mappers/mapper093.c b/src/mappers/mapper093.c deleted file mode 100644 index e241352f8..000000000 --- a/src/mappers/mapper093.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.data >> 4); - setprg16(0xc000, ~0); - setchr8(0); -} - -void Mapper093_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper094.c b/src/mappers/mapper094.c deleted file mode 100644 index 132ce5602..000000000 --- a/src/mappers/mapper094.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.data >> 2); - setprg16(0xc000, ~0); - setchr8(0); -} - -void Mapper094_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper095.c b/src/mappers/mapper095.c deleted file mode 100644 index cbbd87a4f..000000000 --- a/src/mappers/mapper095.c +++ /dev/null @@ -1,121 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* -Mapper 95 represents NAMCOT-3425, a board used only for the game Dragon Buster (J). - -It is to the ordinary Namco 108 family boards (mapper 206) as TKSROM and TLSROM -(mapper 118) is to ordinary MMC3 boards. Instead of having hardwired mirroring -like mapper 206, it has CHR A15 directly controlling CIRAM A10, just as CHR A17 -controls CIRAM A10 on TxSROM. Only horizontal mirroring and 1-screen mirroring -are possible because the Namco 108 lacks the C bit of MMC3. -*/ - -#include "mapinc.h" -#include "n118.h" - -static uint8 mcache[8]; -static uint32 lastppu; - -static SFORMAT StateRegs[] = { - { mcache, 8, "MCCH" }, - { &lastppu, 4, "LPPU" }, - { 0 } -}; - -static void M095FixCHR(void) { - setchr2(0x0000, n118.reg[0] >> 1); - setchr2(0x0800, n118.reg[1] >> 1); - setchr1(0x1000, n118.reg[2]); - setchr1(0x1400, n118.reg[3]); - setchr1(0x1800, n118.reg[4]); - setchr1(0x1C00, n118.reg[5]); - setmirror(MI_0 + mcache[lastppu]); -} - -static DECLFW(M095Write) { - switch (A & 0xE001) { - case 0x8001: - n118.reg[n118.cmd & 0x07] = V & 0x1F; - switch (n118.cmd & 0x07) { - case 0: - mcache[0] = mcache[1] = (V >> 5) & 0x01; - N118_FixCHR(); - break; - case 1: - mcache[2] = mcache[3] = (V >> 5) & 0x01; - N118_FixCHR(); - break; - case 2: - mcache[4] = (V >> 5) & 0x01; - N118_FixCHR(); - break; - case 3: - mcache[5] = (V >> 5) & 0x01; - N118_FixCHR(); - break; - case 4: - mcache[6] = (V >> 5) & 0x01; - N118_FixCHR(); - break; - case 5: - mcache[7] = (V >> 5) & 0x01; - N118_FixCHR(); - break; - case 6: - case 7: - N118_FixPRG(); - break; - } - break; - default: - N118_Write(A, V); - break; - } -} - -static void MExMirrPPU(uint32 A) { - static int8 lastmirr = -1, curmirr; - if (A < 0x2000) { - lastppu = A >> 10; - curmirr = mcache[lastppu]; - if (curmirr != lastmirr) { - setmirror(MI_0 + curmirr); - lastmirr = curmirr; - } - } -} - -static void M095Power(void) { - lastppu = 0; - memset(mcache, 0, sizeof(mcache)); - - N118_Power(); - SetWriteHandler(0x8000, 0x9FFF, M095Write); -} - -void Mapper095_Init(CartInfo *info) { - N118_Init(info, 0, 0); - info->Power = M095Power; - N118_FixCHR = M095FixCHR; - PPU_hook = MExMirrPPU; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper096.c b/src/mappers/mapper096.c deleted file mode 100644 index 059eccec7..000000000 --- a/src/mappers/mapper096.c +++ /dev/null @@ -1,71 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 1998 BERO - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Oeka-kids board - * - * I might want to add some code to the mapper 96 PPU hook function - * to not change CHR banks if the attribute table is being accessed, - * if I make emulation a little more accurate in the future. - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 ppulatch; -static uint16 lastAddr; - -static SFORMAT StateRegs[] = -{ - { &ppulatch, 1, "PPUL" }, - { &lastAddr, 2, "LADR" }, - { 0 } -}; - -static void Sync(void) { - setmirror(MI_0); - setprg32(0x8000, latch.data & 3); - setchr4(0x0000, (latch.data & 4) | ppulatch); - setchr4(0x1000, (latch.data & 4) | 3); -} - -static void M096PPUHook(uint32 A) { - uint16 addr = A & 0x3000; - if ((lastAddr != 0x2000) && ((A & 0x3000) == 0x2000)) { - ppulatch = (A >> 8) & 3; - Sync(); - } - lastAddr = addr; -} - -static void M096Power(void) { - ppulatch = 0; - lastAddr = 0; - Latch_Power(); -} - -void Mapper096_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Power = M096Power; - PPU_hook = M096PPUHook; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper097.c b/src/mappers/mapper097.c deleted file mode 100644 index 52369e163..000000000 --- a/src/mappers/mapper097.c +++ /dev/null @@ -1,34 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, ~0); - setprg16(0xC000, latch.data); - setchr8(0); - setmirror((latch.data >> 7) & 0x01); -} - -void Mapper097_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper099.c b/src/mappers/mapper099.c deleted file mode 100644 index 20630c2bb..000000000 --- a/src/mappers/mapper099.c +++ /dev/null @@ -1,73 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 latch; -static writefunc old4016; - -static SFORMAT StateRegs[] = { - { &latch, 1, "LATC" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, 0); - setprg8(0x8000, latch & 4); /* Special for VS Gumshoe */ - setchr8((latch >> 2) & 1); -} - -static DECLFW(M099Write) { - latch = V; - Sync(); - old4016(A, V); -} - -static void M099Power(void) { - latch = 0; - Sync(); - old4016 = GetWriteHandler(0x4016); - SetWriteHandler(0x4016, 0x4016, M099Write); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M099Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper099_Init(CartInfo *info) { - info->Power = M099Power; - info->Close = M099Close; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper100.c b/src/mappers/mapper100.c deleted file mode 100644 index b330e873d..000000000 --- a/src/mappers/mapper100.c +++ /dev/null @@ -1,167 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 cmd; -static uint8 prg[4]; -static uint8 chr[8]; - -static SFORMAT StateRegs[] = { - { &cmd, 1, "CMD0" }, - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { 0 } -}; - -static void M100PRG(void) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, prg[3]); -} - -static void M100CHR(void) { - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); -} - -static DECLFW(M100WriteCMD) { - switch (A & 0xE001) { - case 0x8000: - cmd = V; - break; - case 0x8001: - switch (cmd) { - case 0x00: - chr[0] = V & 0xFE; - chr[1] = V | 0x01; - break; - case 0x01: - chr[2] = V & 0xFE; - chr[3] = V | 0x01; - break; - case 0x02: - chr[4] = V; - break; - case 0x03: - chr[5] = V; - break; - case 0x04: - chr[6] = V; - break; - case 0x05: - chr[7] = V; - break; - case 0x06: - prg[0] = V; - break; - case 0x07: - prg[1] = V; - break; - case 0x46: - prg[2] = V; - break; - case 0x47: - prg[1] = V; - break; - case 0x80: - chr[4] = V & 0xFE; - chr[5] = V | 0x01; - break; - case 0x81: - chr[6] = V & 0xFE; - chr[7] = V | 0x01; - break; - case 0x82: - chr[0] = V; - break; - case 0x83: - chr[1] = V; - break; - case 0x84: - chr[2] = V; - break; - case 0x85: - chr[3] = V; - break; - } - MMC3_FixPRG(); - MMC3_FixCHR(); - break; - } -} - -static void M100Reset(void) { - cmd = 0; - prg[0] = 0; - prg[1] = 1; - prg[2] = ~1; - prg[3] = ~0; - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - chr[4] = 4; - chr[5] = 5; - chr[6] = 6; - chr[7] = 7; - MMC3_Reset(); -} - -static void M100Power(void) { - cmd = 0; - prg[0] = 0; - prg[1] = 1; - prg[2] = ~1; - prg[3] = ~0; - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - chr[4] = 4; - chr[5] = 5; - chr[6] = 6; - chr[7] = 7; - MMC3_Power(); - SetWriteHandler(0x8000, 0x9FFF, M100WriteCMD); - - if (iNESCart.HasTrainer && MISC_ROM_SIZE) { - if (MISC_ROM_PTR[0] == 0x4C) { - X6502_SetNewPC(0x7000); - } - } -} - -void Mapper100_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_FixPRG = M100PRG; - MMC3_FixCHR = M100CHR; - info->Power = M100Power; - info->Reset = M100Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper101.c b/src/mappers/mapper101.c deleted file mode 100644 index 706499dfe..000000000 --- a/src/mappers/mapper101.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REG" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, 0); - setchr8(reg); -} - -static DECLFW(M101Write) { - reg = V; - Sync(); -} - -static void M101Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, M101Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper101_Init(CartInfo *info) { - info->Power = M101Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper103.c b/src/mappers/mapper103.c deleted file mode 100644 index b7053ae89..000000000 --- a/src/mappers/mapper103.c +++ /dev/null @@ -1,110 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - Doki Doki Panic - * - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg[3]; - -static SFORMAT StateRegs[] = { - { reg, 3, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, 0x0C); - setprg8(0xE000, 0x0F); - if (reg[2] & 0x10) { - setprg8(0x6000, reg[0] & 0x0F); - setprg8(0xA000, 0x0D); - setprg8(0xC000, 0x0E); - } else { - setprg8r(0x10, 0x6000, 0); - setprg4(0xA000, (0x0D << 1)); - setprg2(0xB000, (0x0D << 2) + 2); - setprg2r(0x10, 0xB800, 4); - setprg2r(0x10, 0xC000, 5); - setprg2r(0x10, 0xC800, 6); - setprg2r(0x10, 0xD000, 7); - setprg2(0xD800, (0x0E << 2) + 3); - } - setchr8(0); - setmirror(((reg[1] >> 3) & 0x01) ^ 0x01); -} - -static DECLFW(M103RamWrite0) { - WRAM[A & 0x1FFF] = V; -} - -static DECLFW(M103RamWrite1) { - WRAM[0x2000 + ((A - 0xB800) & 0x1FFF)] = V; -} - -static DECLFW(M103WritePRG) { - reg[0] = V; - Sync(); -} - -static DECLFW(M103WriteMirror) { - reg[1] = V; - Sync(); -} - -static DECLFW(M103WriteRAMEnable) { - reg[2] = V; - Sync(); -} - -static void M103Power(void) { - FDSSound_Power(); - reg[0] = reg[1] = 0; - reg[2] = 0; - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, M103RamWrite0); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0xB800, 0xD7FF, M103RamWrite1); - SetWriteHandler(0x8000, 0x8FFF, M103WritePRG); - SetWriteHandler(0xE000, 0xEFFF, M103WriteMirror); - SetWriteHandler(0xF000, 0xFFFF, M103WriteRAMEnable); -} - -static void M103Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper103_Init(CartInfo *info) { - info->Power = M103Power; - info->Close = M103Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 16384; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper104.c b/src/mappers/mapper104.c deleted file mode 100644 index a7b0fe1af..000000000 --- a/src/mappers/mapper104.c +++ /dev/null @@ -1,81 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Pegasus 5-in-1 (Golden Five) (Unl) - */ - -#include "mapinc.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, (reg[1] << 4) | (reg[0] & 0x0F)); - setprg16(0xC000, (reg[1] << 4) | 0x0F); - setchr8(0); -} - -static DECLFW(M104Write) { - switch (A & 0xF000) { - case 0x8000: - case 0x9000: - case 0xA000: - case 0xB000: - if (!(reg[1] & 0x08)) { - reg[1] = V; - Sync(); - } - break; - case 0xC000: - case 0xD000: - case 0xE000: - case 0xF000: - reg[0] = V; - Sync(); - break; - } -} - -static void M104Close(void) { -} - -static void M104Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M104Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper104_Init(CartInfo *info) { - info->Power = M104Power; - info->Close = M104Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper105.c b/src/mappers/mapper105.c deleted file mode 100644 index 094cd8b8d..000000000 --- a/src/mappers/mapper105.c +++ /dev/null @@ -1,74 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc1.h" - -static uint32 count; -static uint32 count_target = 0x28000000; - -static void M105IRQHook(int a) { - while (a--) { - if (mmc1.reg[1] & 0x10) { - count = 0; - X6502_IRQEnd(FCEU_IQEXT); - } else { - if (++count == count_target) { - X6502_IRQBegin(FCEU_IQEXT); - } - if ((count % 1789773) == 0) { - uint32 seconds = (count_target - count) / 1789773; - FCEU_DispMessage(RETRO_LOG_INFO, 1000, "Time left: %02i:%02i\n", seconds / 60, seconds % 60); - } - } - } -} - -static void M105CW(uint16 A, uint16 V) { - setchr8r(0, 0); -} - -static void M105PW(uint16 A, uint16 V) { - if (mmc1.reg[1] & 0x08) { - setprg16(A, 8 | (V & 0x7)); - } else { - setprg32(0x8000, (mmc1.reg[1] >> 1) & 0x03); - } -} - -static void M105Power(void) { - count_target = 0x20000000 | ((uint32)GameInfo->cspecial << 25); - MMC1_Power(); -} - -static void M105Reset(void) { - count_target = 0x20000000 | ((uint32)GameInfo->cspecial << 25); - MMC1_Reset(); -} - -void Mapper105_Init(CartInfo *info) { - MMC1_Init(info, 8, 0); - MMC1_cwrap = M105CW; - MMC1_pwrap = M105PW; - MapIRQHook = M105IRQHook; - info->Power = M105Power; - info->Reset = M105Reset; - AddExState(&count, 4, 0, "IRQC"); -} diff --git a/src/mappers/mapper106.c b/src/mappers/mapper106.c deleted file mode 100644 index 5fe755c2e..000000000 --- a/src/mappers/mapper106.c +++ /dev/null @@ -1,124 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[4], chr[8]; -static uint8 mirr, IRQa; -static uint32 IRQCount; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREGS" }, - { chr, 8, "CREGS" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 4, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg8(0x8000, (prg[0] & 0x0F) | 0x10); - setprg8(0xA000, (prg[1] & 0x1F)); - setprg8(0xC000, (prg[2] & 0x1F)); - setprg8(0xE000, (prg[3] & 0x0F) | 0x10); - - setchr1(0x0000, chr[0] & ~1); - setchr1(0x0400, chr[1] | 1); - setchr1(0x0800, chr[2] & ~1); - setchr1(0x0c00, chr[3] | 1); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - setmirror((mirr & 0x01) ^ 0x01); -} - -static DECLFW(M106Write) { - switch (A & 0x0F) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - chr[A & 0x07] = V; - Sync(); - break; - case 0x08: case 0x09: case 0x0A: case 0x0B: - prg[A & 0x03] = V; - Sync(); - break; - case 0x0C: - mirr = V; - Sync(); - break; - case 0x0D: - IRQa = 0; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x0E: - IRQCount = (IRQCount & 0xFF00) | V; - break; - case 0x0F: - IRQCount = (IRQCount & 0x00FF) | (V << 8); - IRQa = 1; - break; - } -} - -static void M106Power(void) { - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, M106Write); -} - -static void M106Reset(void) { } - -static void M106Close(void) { -} - -static void M106CpuHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount > 0x10000) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper106_Init(CartInfo *info) { - info->Reset = M106Reset; - info->Power = M106Power; - info->Close = M106Close; - MapIRQHook = M106CpuHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper107.c b/src/mappers/mapper107.c deleted file mode 100644 index abfaacc15..000000000 --- a/src/mappers/mapper107.c +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.data >> 1); - setchr8(latch.data); -} - -void Mapper107_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper108.c b/src/mappers/mapper108.c deleted file mode 100644 index c19852909..000000000 --- a/src/mappers/mapper108.c +++ /dev/null @@ -1,98 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - * - * Bubble Bobble (LH31) - * - submapper 1: CHR-RAM 8K - * - submapper 2: CHR-ROM 32K - UNIF UNL-BB - * Submapper 3: - * - Falsion (LH54) - * - Meikyuu Jiin Dababa (LH28) - * Submapper 4: UNIF UNL-BB - * - Pro Wrestling (LE05) - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - if (iNESCart.submapper == 4) { - setprg8(0x6000, ~0); - } else { - setprg8(0x6000, reg); - } - setprg32(0x8000, ~0); - if (CHR_ROM_SIZE) { - setchr8(reg); - } else { - setchr8(0); - } -} - -static DECLFW(M108Write) { - reg = V; - Sync(); -} - -static void M108Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - switch (iNESCart.submapper) { - case 1: SetWriteHandler(0xF000, 0xFFFF, M108Write); break; - case 2: SetWriteHandler(0xE000, 0xFFFF, M108Write); break; - default: SetWriteHandler(0x8000, 0xFFFF, M108Write); break; - } - FDSSound_Power(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper108_Init(CartInfo *info) { - info->Power = M108Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - if (!info->iNES2 || !info->submapper) { - if (!CHR_ROM_SIZE) { - if (info->mirror == MI_H) { - info->submapper = 1; - } else { - info->submapper = 3; - } - } else { - if (CHR_ROM_SIZE <= (32 * 1024)) { - info->submapper = 4; - } else { - info->submapper = 2; - } - } - } -} diff --git a/src/mappers/mapper111.c b/src/mappers/mapper111.c deleted file mode 100644 index b555733f3..000000000 --- a/src/mappers/mapper111.c +++ /dev/null @@ -1,178 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* mapper 111 - Cheapocabra board by Memblers - * http://forums.nesdev.com/viewtopic.php?p=146039 - * - * 512k PRG-ROM in 32k pages (flashable if battery backed is specified) - * 32k CHR-RAM used as: - * 2 x 8k pattern pages - * 2 x 8k nametable pages - * - * Notes: - * - CHR-RAM for nametables maps to $3000-3FFF as well, but FCEUX internally mirrors to 4k? - */ - -#include "mapinc.h" -#include "flashrom.h" -#include "mmc1.h" - -static uint8 reg; - -static int m111_mmc1 = FALSE; - -static uint8 *FLASHROM = NULL; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M111MMC1PW(uint16 A, uint16 V) { - setprg16(A, V & 0x0F); -} - -static void M111MMC1CW(uint16 A, uint16 V) { - setchr4(A, V & 0x3F); -} - -static DECLFW(M111Write_mmc1) { - mmc1.reg[(A >> 13) & 0x03] = V; - MMC1_FixPRG(); - MMC1_FixCHR(); - MMC1_FixMIR(); -} - -static void M111Power_mmc1(void) { - MMC1_Power(); - SetWriteHandler(0x8000, 0xFFFF, M111Write_mmc1); -} - -#define VRAM_OFFSET(x) (0x4000 + (0x400 * (x))) - -static void Sync(void) { - /* 7 bit 0 - * ---- ---- - * GRNC PPPP - * |||| |||| - * |||| ++++- Select 32 KB PRG ROM bank for CPU $8000-$FFFF - * |||+------ Select 8 KB CHR RAM bank for PPU $0000-$1FFF - * ||+------- Select 8 KB nametable for PPU $2000-$3EFF - * |+-------- Red LED - 0=On; 1=Off - * +--------- Green LED - 0=On; 1=Off */ - int nt = (reg & 0x20) >> 5; - - setprg32r(FLASHROM ? 0x10 : 0, 0x8000, reg & 0x0F); - setchr8((reg & 0x10) >> 4); - setntamem(CHRptr[0] + VRAM_OFFSET(0) + (nt << 13), 1, 0); - setntamem(CHRptr[0] + VRAM_OFFSET(1) + (nt << 13), 1, 1); - setntamem(CHRptr[0] + VRAM_OFFSET(2) + (nt << 13), 1, 2); - setntamem(CHRptr[0] + VRAM_OFFSET(3) + (nt << 13), 1, 3); -} - -static DECLFR(M111ReadOB) { - reg = CPU_OPENBUS; - Sync(); - return reg; -} - -static DECLFW(M111WriteReg) { - reg = V; - Sync(); -} - -static DECLFR(M111ReadFlash) { - return FlashROM_Read(A); -} - -static DECLFW(M111WriteFlash) { - FlashROM_Write(A, V); -} - -static void M111CPUCycle(int a) { - FlashROM_CPUCyle(a); -} - -static void M111Power(void) { - reg = 0xFF; - Sync(); - - SetReadHandler(0x5000, 0x5FFF, M111ReadOB); - SetReadHandler(0x7000, 0x7FFF, M111ReadOB); - - SetWriteHandler(0x5000, 0x5FFF, M111WriteReg); - SetWriteHandler(0x7000, 0x7FFF, M111WriteReg); - - SetReadHandler(0x8000, 0xFFFF, M111ReadFlash); - SetWriteHandler(0x8000, 0xFFFF, M111WriteFlash); -} - -static void M111Close(void) { - if (FLASHROM) { - FCEU_gfree(FLASHROM); - } - FLASHROM = NULL; -} - -static void StateRestore(int version) { - if (m111_mmc1) { - MMC1_FixPRG(); - MMC1_FixCHR(); - MMC1_FixMIR(); - return; - } - - Sync(); -} - -void Mapper111_Init(CartInfo *info) { - m111_mmc1 = FALSE; - if (CHR_ROM_SIZE) { - /* Prior to the introduction of GTROM, Mapper 111 was assigned to a Chinese Fan Translation - * of Ninja Ryukenden (Japanese Ninja Gaiden). This translation uses a non-serialized - * version of MMC1 and supports 256KiB of CHR-ROM, whereas the official MMC1 is limited to - * 128KiB */ - m111_mmc1 = TRUE; - info->Power = M111Power_mmc1; - MMC1_pwrap = M111MMC1PW; - MMC1_cwrap = M111MMC1CW; - return; - } - - info->Power = M111Power; - info->Close = M111Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - if (info->battery) { - int fsize = PRGsize[0]; - - FLASHROM = (uint8 *)FCEU_gmalloc(fsize); - info->SaveGame[0] = FLASHROM; - info->SaveGameLen[0] = fsize; - AddExState(FLASHROM, fsize, 0, "FROM"); - memcpy(FLASHROM, PRGptr[0], fsize); - SetupCartPRGMapping(0x10, FLASHROM, fsize, 0); - - FlashROM_Init(FLASHROM, fsize, 0xBF, 0xB7, 4096, 0x5555, 0x2AAA); - MapIRQHook = M111CPUCycle; - } -} diff --git a/src/mappers/mapper112.c b/src/mappers/mapper112.c deleted file mode 100644 index 0cc0e97e2..000000000 --- a/src/mappers/mapper112.c +++ /dev/null @@ -1,111 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NTDEC, ASDER games - * - */ - -#include "mapinc.h" - -static uint8 reg[8]; -static uint8 mirror, cmd, chrBase; - -static SFORMAT StateRegs[] = { - { &cmd, 1, "CMD" }, - { &mirror, 1, "MIRR" }, - { &chrBase, 1, "CHRB" }, - { reg, 8, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - - setprg8(0x8000, reg[0]); - setprg8(0xA000, reg[1]); - setprg16(0xC000, ~0); - - setchr2(0x0000, (reg[2] >> 1)); - setchr2(0x0800, (reg[3] >> 1)); - setchr1(0x1000, ((chrBase << 4) & 0x100) | reg[4]); - setchr1(0x1400, ((chrBase << 3) & 0x100) | reg[5]); - setchr1(0x1800, ((chrBase << 2) & 0x100) | reg[6]); - setchr1(0x1C00, ((chrBase << 1) & 0x100) | reg[7]); - - setmirror((mirror & 0x01) ^ 0x01); -} - -static DECLFW(M112Write) { - switch (A & 0xE000) { - case 0x8000: - cmd = V; - break; - case 0xA000: - reg[cmd & 0x07] = V; - Sync(); - break; - case 0xC000: - chrBase = V; - Sync(); - break; - case 0xE000: - mirror = V; - Sync(); - break; - } -} - -static void M112Close(void) { -} - -static void M112Power(void) { - reg[0] = 0; - reg[1] = 1; - reg[2] = 0; - reg[3] = 2; - reg[4] = 4; - reg[5] = 5; - reg[6] = 6; - reg[7] = 7; - chrBase = 0; - Sync(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M112Write); - - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(8, 0x6000, WRAM); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper112_Init(CartInfo *info) { - info->Power = M112Power; - info->Close = M112Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAM = (uint8 *)FCEU_gmalloc(8192); - SetupCartPRGMapping(0x10, WRAM, 8192, 1); - AddExState(WRAM, 8192, 0, "WRAM"); -} diff --git a/src/mappers/mapper113.c b/src/mappers/mapper113.c deleted file mode 100644 index 1ef59d4fa..000000000 --- a/src/mappers/mapper113.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, (reg >> 3) & 0x07); - setchr8(((reg >> 3) & 0x08) | (reg & 0x07)); - setmirror(reg >> 0x07); -} - -static DECLFW(M113Write) { - if (A & 0x100) { - reg = V; - Sync(); - } -} - -static void M113Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, M113Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper113_Init(CartInfo *info) { - info->Power = M113Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper114.c b/src/mappers/mapper114.c deleted file mode 100644 index 3775db6ee..000000000 --- a/src/mappers/mapper114.c +++ /dev/null @@ -1,117 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static uint32 M114_addr[2][8] = { - { 0xA001, 0xA000, 0x8000, 0xC000, 0x8001, 0xC001, 0xE000, 0xE001 }, /* 0: Aladdin, The Lion King */ - { 0xA001, 0x8001, 0x8000, 0xC001, 0xA000, 0xC000, 0xE000, 0xE001 } /* 1: Boogerman */ -}; - -static uint8 M114_index[2][8] = { - { 0, 3, 1, 5, 6, 7, 2, 4 }, /* 0: Aladdin, The Lion King */ - { 0, 2, 5, 3, 6, 1, 7, 4 }, /* 1: Boogerman */ -}; - -static void M114PW(uint16 A, uint16 V) { - if (reg[0] & 0x80) { - uint8 bank = reg[0] & 0x0F; - - if (reg[0] & 0x20) { - setprg32(0x8000, bank >> 1); - } else { - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } else { - setprg8(A, V & 0x3F); - } -} - -static void M114CW(uint16 A, uint16 V) { - setchr1(A, ((reg[1] << 8) & 0x100) | (V & 0x0FF)); -} - -static DECLFW(M114WriteReg) { - reg[A & 0x01] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static DECLFW(M114Write) { - A = M114_addr[iNESCart.submapper & 0x01][((A >> 12) & 0x06) | (A & 0x01)]; - switch (A & 0xE001) { - case 0x8000: - V = (V & 0xF8) | M114_index[iNESCart.submapper & 0x01][V & 0x07]; - MMC3_CMDWrite(A, V); - break; - default: - MMC3_Write(A, V); - break; - } -} - -static DECLFR(M114ReadDip) { - if ((A & 0x03) == 0x02) { - return (CPU_OPENBUS & ~0x07) | (dipsw & 0x07); - } - return CPU_OPENBUS; -} - -static void M114Power(void) { - reg[0] = reg[1] = 0; - MMC3_Power(); - SetReadHandler(0x6000, 0x7FFF, M114ReadDip); - SetWriteHandler(0x6000, 0x7FFF, M114WriteReg); - SetWriteHandler(0x8000, 0xFFFF, M114Write); -} - -static void M114Reset(void) { - reg[0] = reg[1] = 0; - dipsw++; - MMC3_Reset(); -} - -void Mapper114_Init(CartInfo *info) { - isRevB = 0; - /* Use NES 2.0 submapper to identify scrambling pattern, otherwise CRC32 for Boogerman and test rom */ - if (!info->iNES2) { - if ((info->CRC32 == 0x80eb1839) || (info->CRC32 == 0x071e4ee8)) { - info->submapper = 1; - } - } - - MMC3_Init(info, 0, 0); - MMC3_pwrap = M114PW; - MMC3_cwrap = M114CW; - info->Power = M114Power; - info->Reset = M114Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper115.c b/src/mappers/mapper115.c deleted file mode 100644 index ab08b318b..000000000 --- a/src/mappers/mapper115.c +++ /dev/null @@ -1,67 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void M115PW(uint16 A, uint16 V) { - if (reg[0] & 0x80) { - uint8 bank = reg[0] & 0x0F; - - if (reg[0] & 0x20) { - setprg32(0x8000, bank >> 1); - } else { - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } else { - setprg8(A, V & 0x3F); - } -} - -static void M115CW(uint16 A, uint16 V) { - setchr1(A, ((reg[1] << 8) & 0x100) | (V & 0xFF)); -} - -static DECLFW(M115WriteReg) { - reg[A & 0x01] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M115Power(void) { - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M115WriteReg); -} - -void Mapper115_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M115CW; - MMC3_pwrap = M115PW; - info->Power = M115Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper116.c b/src/mappers/mapper116.c deleted file mode 100644 index c6990b27d..000000000 --- a/src/mappers/mapper116.c +++ /dev/null @@ -1,208 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1) - * the same as 603-5052 board (TODO: add reading registers, merge) - * SL1632 2-in-1 protected board, similar to SL12 (TODO: find difference) - * - * Known PCB: - * - * Garou Densetsu Special (G0904.PCB, Huang-1, GAL dip: W conf.) - * Kart Fighter (008, Huang-1, GAL dip: W conf.) - * Somari (008, C5052-13, GAL dip: P conf., GK2-P/GK2-V maskroms) - * Somari (008, Huang-1, GAL dip: W conf., GK1-P/GK1-V maskroms) - * AV Mei Shao Nv Zhan Shi (aka AV Pretty Girl Fighting) (SL-12 PCB, Hunag-1, GAL dip: unk conf. SL-11A/SL-11B maskroms) - * Samurai Spirits (Full version) (Huang-1, GAL dip: unk conf. GS-2A/GS-4A maskroms) - * Contra Fighter (603-5052 PCB, C5052-3, GAL dip: unk conf. SC603-A/SCB603-B maskroms) - * - */ - -#include "mapinc.h" -#include "vrc24.h" -#include "mmc3.h" -#include "mmc1.h" - -#define MODE_MMC1 mode & 0x02 -#define MODE_MMC3 mode & 0x01 - -static uint8 mode = 0; -static uint8 game = 0; - -static SFORMAT StateRegs[] = { - { &mode, 1, "MODE"}, - { &game, 1, "GAME"}, - { 0 } -}; - -static uint32 GetPRGMask(void) { - if (iNESCart.submapper != 3) { - return 0x3F; - } - return (game ? 0x0F : 0x1F); -} - -static uint32 GetPRGBase(void) { - if (game) { - return (game + 1) * 0x10; - } - return 0; -} - -static uint32 GetCHRMask(void) { - return (game ? 0x7F : 0xFF); -} - -static uint32 GetCHRBase(void) { - return (game ? (game + 1) * 0x80 : 0); -} - -static void M116VRC24PW(uint16 A, uint16 V) { - setprg8(A, GetPRGBase() | (V & GetPRGMask())); -} - -static void M116VRC24CW(uint16 A, uint16 V) { - setchr1(A, ((mode << 6) & 0x100) | GetCHRBase() | (V & GetCHRMask())); -} - -static void M116MMC3PW(uint16 A, uint16 V) { - setprg8(A, GetPRGBase() | (V & GetPRGMask())); -} - -static void M116MMC3CW(uint16 A, uint16 V) { - setchr1(A, ((mode << 6) & 0x100) | GetCHRBase() | (V & GetCHRMask())); -} - -static void M116MMC1PW(uint16 A, uint16 V) { - if (iNESCart.submapper == 2) { - setprg16(A, V >> 1); - } else { - setprg16(A, (GetPRGBase() >> 1) | (V & (GetPRGMask() >> 1))); - } -} - -static void M116MMC1CW(uint16 A, uint16 V) { - setchr4(A, (GetCHRBase() >> 2) | (V & (GetCHRMask() >> 2))); -} - -static void Sync(void) { - if (MODE_MMC1) { - MMC1_FixPRG(); - MMC1_FixCHR(); - MMC1_FixMIR(); - } else if (MODE_MMC3) { - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } else { - VRC24_FixPRG(); - VRC24_FixCHR(); - VRC24_FixMIR(); - } -} - -static void applyMode(void) { - if (MODE_MMC1) { - SetWriteHandler(0x8000, 0xFFFF, MMC1_Write); - if (iNESCart.submapper != 1) { - MMC1_Write(0x8000, 0x80); - } - } else if (MODE_MMC3) { - SetWriteHandler(0x8000, 0xFFFF, MMC3_Write); - } else { - SetWriteHandler(0x8000, 0xFFFF, VRC24_Write); - } -} - -static DECLFW(M116ModeWrite) { - if (A & 0x100) { - mode = V; - applyMode(); - Sync(); - } -} - -static void M116HBIRQ(void) { - if ((mode & 0x03) == 0x01) { - MMC3_IRQHBHook(); - } -} - -static void StateRestore(int version) { - Sync(); -} - -static void M116Reset(void) { - if (iNESCart.submapper == 3) { - game = game + 1; - if (game > 4) { - game = 0; - } - } - applyMode(); - Sync(); -} - -static void M116Power(void) { - game = (iNESCart.submapper == 3) ? 4 : 0; - mode = 1; - - MMC3_Power(); - MMC1_Reset(); - VRC24_Power(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, M116ModeWrite); - - vrc24.chr[0] = ~0; - vrc24.chr[1] = ~0; - vrc24.chr[2] = ~0; - vrc24.chr[3] = ~0; - - applyMode(); - Sync(); -} - -void Mapper116_Init(CartInfo *info) { - VRC24_Init(info, VRC2, 0x01, 0x02, FALSE, TRUE); - VRC24_pwrap = M116VRC24PW; - VRC24_cwrap = M116VRC24CW; - - MMC3_Init(info, FALSE, FALSE); - MMC3_pwrap = M116MMC3PW; - MMC3_cwrap = M116MMC3CW; - - MMC1_Init(info, FALSE, FALSE); - MMC1_pwrap = M116MMC1PW; - MMC1_cwrap = M116MMC1CW; - mmc1_type = MMC1A; - - info->Power = M116Power; - info->Reset = M116Reset; - - GameHBIRQHook = M116HBIRQ; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - /* PRG 128K and CHR 128K is Huang-2 (iNESCart.submapper 2) */ - if ((info->submapper != 2) && (PRG_ROM_SIZE == (128 * 1024)) && (CHR_ROM_SIZE == (128 * 1024))) { - info->submapper = 2; - } -} diff --git a/src/mappers/mapper117.c b/src/mappers/mapper117.c deleted file mode 100644 index 15ded86d5..000000000 --- a/src/mappers/mapper117.c +++ /dev/null @@ -1,123 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[4], chr[8], mirr; -static uint8 IRQa, IRQCount, IRQLatch; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { &mirr, 1, "MREG" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 1, "IRQC" }, - { &IRQLatch, 1, "IRQL" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, ~0); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - setmirror(mirr ^ 1); -} - -static DECLFW(M117Write) { - switch (A & 0xF000) { - case 0x8000: - prg[A & 0x03] = V; - Sync(); - break; - case 0xA000: - switch (A & 0x0F) { - case 0: case 1: case 2: case 3: - case 4: case 5: case 6: case 7: - chr[A & 0x07] = V; - Sync(); - break; - } - break; - case 0xC000: - switch (A & 0x03) { - case 1: - IRQLatch = V; - break; - case 3: - IRQCount = IRQLatch; - IRQa |= 2; - break; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xD000: - mirr = V & 1; - Sync(); - break; - case 0xE000: - IRQa &= ~1; - IRQa |= V & 1; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -static void M117Power(void) { - prg[0] = ~3; - prg[1] = ~2; - prg[2] = ~1; - prg[3] = ~0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M117Write); -} - -static void M117IRQHook(void) { - if (IRQa == 3 && IRQCount) { - IRQCount--; - if (!IRQCount) { - IRQa &= 1; - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper117_Init(CartInfo *info) { - info->Power = M117Power; - GameHBIRQHook = M117IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper118.c b/src/mappers/mapper118.c deleted file mode 100644 index a6be1fa8f..000000000 --- a/src/mappers/mapper118.c +++ /dev/null @@ -1,75 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M118MIR(void) { - if (mmc3.cmd & 0x80) { - setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); - } else { - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); - } -} - -static DECLFW(M118Write) { - switch (A & 0xE001) { - case 0x8001: - switch (mmc3.cmd & 0x07) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - mmc3.reg[mmc3.cmd & 0x07] = V; - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - default: - MMC3_CMDWrite(A, V); - break; - } - case 0xA000: - /* MMC3 mirroring not used in favor of nametable mirroring */ - break; - default: - MMC3_CMDWrite(A, V); - break; - } -} - -static void M118Power(void) { - MMC3_Power(); - SetWriteHandler(0x8000, 0xBFFF, M118Write); -} - -void Mapper118_Init(CartInfo *info) { - uint8 ws = info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) / 1024 : 8; - MMC3_Init(info, ws, info->battery); - info->Power = M118Power; - MMC3_FixMIR = M118MIR; -} diff --git a/src/mappers/mapper119.c b/src/mappers/mapper119.c deleted file mode 100644 index f2f16276b..000000000 --- a/src/mappers/mapper119.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M119CW(uint16 A, uint16 V) { - if (V & 0x40) { - setchr1r(0x10, A, V & 0x07); - } else { - setchr1(A, V); - } -} - -static void M119Close(void) { - MMC3_Close(); -} - -void Mapper119_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - info->Close = M119Close; - MMC3_cwrap = M119CW; - CHRRAMSIZE = 8192; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper120.c b/src/mappers/mapper120.c deleted file mode 100644 index f99abd7d4..000000000 --- a/src/mappers/mapper120.c +++ /dev/null @@ -1,62 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - * - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REG" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x6000, reg); - setprg32(0x8000, 2); - setchr8(0); -} - -static DECLFW(M120Write) { - if ((A & 0xE100) == 0x4100) { - reg = V & 0x07; - Sync(); - } -} - -static void M120Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, M120Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper120_Init(CartInfo *info) { - info->Power = M120Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper121.c b/src/mappers/mapper121.c deleted file mode 100644 index 61a647f7d..000000000 --- a/src/mappers/mapper121.c +++ /dev/null @@ -1,129 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007-2008 Mad Dumper, CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Panda prince pirate. - * MK4, MK6, A9711/A9713 board - * 6035052 seems to be the same too, but with prot array in reverse - * A9746 seems to be the same too, check - * 187 seems to be the same too, check (A98402 board) - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 prg[3]; -static uint8 reg; -static uint8 readIndex; -static uint8 protIndex; -static uint8 protLatch; - -static SFORMAT StateRegs[] = { - { prg, 3, "PREG" }, - { ®, 2, "REGS" }, - { &readIndex, 1, "PRRD" }, - { &protIndex, 1, "PRID" }, - { &protLatch, 1, "PRLT" }, - { 0 } -}; - -static void M121CW(uint16 A, uint16 V) { - if (PRG_ROM_SIZE > (256 * 1024)) { - setchr1(A, ((reg & 0x80) << 1) | V); - } else { - if ((A & 0x1000) == (uint32)((mmc3.cmd & 0x80) << 5)){ - setchr1(A, 0x100 | V); - } else { - setchr1(A, V); - } - } -} - -static void M121PW(uint16 A, uint16 V) { - uint8 mask = 0x1F; - uint8 base = ((reg & 0x80) >> 2); - - if ((protIndex & 0x20) && (A > 0x8000)) { - mask = 0xFF; - V = prg[((A >> 13) & 0x03) - 1]; - } - - setprg8(A, base | (V & mask)); -} - -static const uint8 prot_array[] = { 0x83, 0x83, 0x42, 0x00, 0x00, 0x02, 0x02, 0x03 }; -static DECLFR(M121ReadLUT) { - return prot_array[readIndex]; -} - -static DECLFW(M121WriteLUT) { - readIndex = ((A >> 6) & 0x04) | (V & 0x03); - if (A & 0x0100) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static DECLFW(M121Write) { - switch (A & 0xE001) { - case 0x8001: - switch (A & 0x03) { - case 0x01: - protLatch = ((V & 0x01) << 5) | ((V & 0x02) << 3) | - ((V & 0x04) << 1) | ((V & 0x08) >> 1) | - ((V & 0x10) >> 3) | ((V & 0x20) >> 5); - if ((protIndex == 0x26) || (protIndex == 0x28) || (protIndex == 0x2A)) { - prg[0x15 - (protIndex >> 1)] = protLatch; - } - break; - case 0x03: - protIndex = V & 0x3F; - if ((protIndex & 0x20) && protLatch) { - prg[2] = protLatch; - } - break; - } - mmc3.reg[mmc3.cmd & 0x07] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - break; - default: - MMC3_CMDWrite(A, V); - break; - } -} - -static void M121Power(void) { - memset(prg, 0, sizeof(prg)); - reg = readIndex = protIndex = protLatch = 0; - MMC3_Power(); - SetReadHandler(0x5000, 0x5FFF, M121ReadLUT); - SetWriteHandler(0x5000, 0x5FFF, M121WriteLUT); - SetWriteHandler(0x8000, 0x9FFF, M121Write); -} - -void Mapper121_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M121PW; - MMC3_cwrap = M121CW; - info->Power = M121Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper123.c b/src/mappers/mapper123.c deleted file mode 100644 index b80257b2f..000000000 --- a/src/mappers/mapper123.c +++ /dev/null @@ -1,73 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 123 - UNL-H2288 */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M123PW(uint16 A, uint16 V) { - if (reg & 0x40) { - uint8 bank = ((reg & 0x28) >> 2) | (reg & 0x05); - - if (reg & 2) { - setprg32(0x8000, bank >> 1); - } else { - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } else { - setprg8(A, V & 0x3F); - } -} - -static DECLFW(M123WriteHi) { - static const uint8 m114_perm[8] = { 0, 3, 1, 5, 6, 7, 2, 4 }; - - if (!(A & 0x01)) { - V = (V & 0xC0) | m114_perm[V & 0x07]; - } - - MMC3_CMDWrite(A, V); -} - -static DECLFW(M123WriteLo) { - if (A & 0x800) { - reg = V; - MMC3_FixPRG(); - } -} - -static void M123Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x5000, 0x5FFF, M123WriteLo); - SetWriteHandler(0x8000, 0x9FFF, M123WriteHi); -} - -void Mapper123_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M123PW; - info->Power = M123Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper124.c b/src/mappers/mapper124.c deleted file mode 100644 index cfe11442c..000000000 --- a/src/mappers/mapper124.c +++ /dev/null @@ -1,234 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* iNES mapper 124 is assigned to the Super Game Mega Type III pirate arcade board. */ - -#include "mapinc.h" -#include "mmc1.h" -#include "mmc3.h" -#include "latch.h" - -#define MAPPER_UNROM 0 -#define MAPPER_AMROM 1 -#define MAPPER_MMC1 2 -#define MAPPER_MMC3 3 - -static uint8 reg[2]; -static uint8 mapper; -static uint8 dipsw; - -static uint8 audioEnable; -static uint8 *ExRAM; - -static SFORMAT StateRegs[] = { - { reg, 2, "MODE" }, - { &mapper, 1, "MAPR" }, - { 0 } -}; - -static uint32 GetPRGBase(void) { - return ((reg[1] << 4) & 0x1F0); -} - -static uint32 GetCHRBase(void) { - return ((reg[0] << 7) & 0x780); -} - -static void M124MMC1PW(uint16 A, uint16 V) { - setprg16(A, (GetPRGBase() >> 1) | (V & 0x07)); -} - -static void M124MMC1CW(uint16 A, uint16 V) { - setchr4(A, (GetCHRBase() >> 2) | (V & 0x1F)); -} - -static void M124MMC3PW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x20) ? 0x0F : 0x1F; - setprg8(A, GetPRGBase() | (V & mask)); -} - -static void M124MMC3CW(uint16 A, uint16 V) { - uint16 mask = (reg[0] & 0x40) ? 0x7F : 0xFF; - setchr1(A, GetCHRBase() | (V & mask)); -} - -static void Sync(void) { - switch (mapper) { - case MAPPER_UNROM: - setprg16(0x8000, (GetPRGBase() >> 1) | (latch.data & 0x07)); - setprg16(0xC000, (GetPRGBase() >> 1) | 0x07); - setchr8(0); - setmirror(MI_V); - break; - case MAPPER_AMROM: - setprg32(0x8000, (GetPRGBase() >> 2) | (latch.data & 0x07)); - setchr8(0); - setmirror(MI_0 + ((latch.data >> 4) & 1)); - break; - case MAPPER_MMC1: - setprg16r(0x10, 0x6000, 0); - MMC1_FixPRG(); - MMC1_FixCHR(); - MMC1_FixMIR(); - break; - case MAPPER_MMC3: - setprg16r(0x10, 0x6000, 0); - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - } - setprg4(0x5000, 0x380 + 0x05); - if (reg[1] & 0x20) { - setprg8(0x6000, (0x380 + 0x06) >> 1); - } - if (!(reg[1] & 0x80)) { - setprg32(0x8000, (0x380 + 0x08) >> 3); - } - if (!(reg[1] & 0x40)) { - setchr8r(0x10, 0); - } -} - -static void applyMode(void) { - mapper = (reg[0] >> 4) & 0x03; -} - -static DECLFR(ReadRAM) { - return ExRAM[A]; -} - -static DECLFW(WriteRAM) { - ExRAM[A] = V; -} - -extern uint8 coinon; -static DECLFR(M124ReadCoinDIP) { - if ((A & 0x0F) == 0x0F) { - /* TODO: Hack to use VS' coin insert map to use as mappers coin insert trigger */ - return ((coinon ? 0x80 : 0x00) | (dipsw & 0x7F)); - } - return CPU_OPENBUS; -} - -static DECLFW(M124WriteReg) { - if (A & 0x10) { - audioEnable = V; - } else { - reg[A & 0x01] = V; - applyMode(); - Sync(); - } -} - -static DECLFW(M124Write) { - switch (mapper) { - case MAPPER_UNROM: - case MAPPER_AMROM: - Latch_Write(A, V); - break; - case MAPPER_MMC3: - MMC3_Write(A, V); - break; - case MAPPER_MMC1: - MMC1_Write(A, V); - break; - } -} - -static void M124Close(void) { - if (ExRAM) { - FCEU_gfree(ExRAM); - ExRAM = NULL; - } -} - -static void M124Reset(void) { - dipsw++; - Sync(); -} - -static void M124Power(void) { - memset(reg, 0, sizeof(reg)); - mapper = 0; - dipsw = 0; - - MMC1_Reset(); - MMC3_Reset(); - Latch_RegReset(); - - SetReadHandler(0x0800, 0x0FFF, ReadRAM); - SetWriteHandler(0x800, 0x0FFF, WriteRAM); - - SetReadHandler(0x4F00, 0x4FFF, M124ReadCoinDIP); - - SetReadHandler(0x5000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, M124WriteReg); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, M124Write); - - applyMode(); - Sync(); -} - -static void M124HBIRQHook(void) { - if (mapper == MAPPER_MMC3) { - MMC3_IRQHBHook(); - } -} - -static void StateRestore(int version) { - applyMode(); - Sync(); -} - -void Mapper124_Init(CartInfo *info) { - MMC1_Init(info, FALSE, FALSE); - MMC1_pwrap = M124MMC1PW; - MMC1_cwrap = M124MMC1CW; - mmc1_type = MMC1A; - - MMC3_Init(info, FALSE, FALSE); - MMC3_pwrap = M124MMC3PW; - MMC3_cwrap = M124MMC3CW; - - Latch_Init(info, Sync, NULL, FALSE, TRUE); - - info->Power = M124Power; - info->Reset = M124Reset; - info->Close = M124Close; - GameHBIRQHook = M124HBIRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - ExRAM = (uint8 *)FCEU_gmalloc(4096); - AddExState(ExRAM, 4096, 0, "ExRAM"); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, TRUE); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper125.c b/src/mappers/mapper125.c deleted file mode 100644 index e8c0f29d9..000000000 --- a/src/mappers/mapper125.c +++ /dev/null @@ -1,76 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 125 - UNL-M125 - * FDS Conversion - Monty no Doki Doki Daisassō, Monty on the Run, cartridge code M125 - * - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 prg; - -static SFORMAT StateRegs[] = { - { &prg, 1, "PREG" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x6000, prg); - setprg8(0x8000, ~3); - setprg8(0xa000, ~2); - setprg8r(0x10, 0xC000, 0); - setprg8(0xE000, ~0); - setchr8(0); -} - -static DECLFW(M125WritePRG) { - prg = V; - Sync(); -} - -static void M125Power(void) { - prg = 0; - Sync(); - FDSSound_Power(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x6000, M125WritePRG); - SetWriteHandler(0xC000, 0xDFFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M125Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper125_Init(CartInfo *info) { - info->Power = M125Power; - info->Close = M125Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper126.c b/src/mappers/mapper126.c deleted file mode 100644 index 11c5b38eb..000000000 --- a/src/mappers/mapper126.c +++ /dev/null @@ -1,201 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 422: "Normal" version of the mapper. Represents UNIF boards BS-400R and BS-4040R. - * Mapper 126: Power Joy version of the mapper, connecting CHR A18 and A19 in reverse order. - * Mapper 534: Waixing version of the mapper, inverting the reload V of the MMC3 scanline counter. - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; -static uint8 dipsw; -static uint8 oldump = FALSE; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M126PW(uint16 A, uint16 V) { - uint8 reg0 = reg[0] ^ (oldump ? 0 : 0x20); - uint16 mask = (reg0 & 0x40) ? 0x0F : 0x1F; - uint16 base = (((reg0 << 4) & 0x70) | ((reg0 << 3) & 0x180)) & ~mask; - - switch (iNESCart.submapper) { - case 1: base |= ((base & 0x100) >> 1); break; - case 2: base |= ((reg[1] & 0x02) << 5); break; - } - - if (reg[3] & 0x08) { - uint8 b = (A >> 13) & 0x03; - V = MMC3_GetPRGBank(b & (((reg[3] & 0x0D) == 0x0D) ? 0x02 : ((reg[3] & 0x01) ? 0 : 0x03))); - switch (reg[3] & 0x03) { - case 0: V = ((V << 1) & ~0x03) | (V & 0x03); break; - case 1: V = ((V << 1) & ~0x01) | (b & 0x03); break; - case 2: V = ((V << 2) & ~0x03) | (V & 0x03); break; - case 3: V = ((V << 2) & ~0x03) | (b & 0x03); break; - } - } else { - switch (reg[3] & 0x03) { - case 1: - case 2: - base = base | (mmc3.reg[6] & mask); - V = (A >> 13) & 0x01; - mask = 0x01; - break; - case 3: - base = base | (mmc3.reg[6] & mask); - V = (A >> 13) & 0x03; - mask = 0x03; - break; - } - } - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M126CW(uint16 A, uint16 V) { - uint8 reg0 = reg[0] ^ (oldump ? 0 : 0x20); - uint16 mask = (reg0 & 0x80) ? 0x7F : 0xFF; - uint16 base = (reg0 << 4) & 0x380; - - if (iNESCart.mapper == 126) { - base = ((reg0 << 4) & 0x080) | ((reg0 << 3) & 0x100) | ((reg0 << 5) & 0x200); - } - if (reg[3] & 0x10) { - base = (((base & ~mask) >> 3) | (reg[2] & (mask >> 3))) << 3; - V = (A >> 10) & 0x07; - mask = 0x07; - } - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M126MIR(void) { - if (reg[3] & 0x20) { - setmirror(MI_0 + ((mmc3.reg[6] & 0x10) >> 4)); - } else if (reg[1] & 0x02) { - switch (mmc3.mirr & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } - } else { - setmirror((mmc3.mirr & 0x01) ^ 0x01); - } -} - -static DECLFR(M126ReadDIP) { - if (reg[1] & 0x01) { - return CartBR((A & ~0x01) | (dipsw & 0x01)); - } - return CartBR(A); -} - -static DECLFW(M126WriteWRAM) { - CartBW(A, V); - if (!(reg[3] & 0x80)) { - reg[A & 0x03] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } else if ((A & 0x03) == 0x02) { - const uint8 mask = 0xFF & ~(reg[2] & 0x80 ? 0xF0 : 0x00) & ~((reg[2]) >> 3 & 0x0E); - reg[2] = (reg[2] & ~mask) | (V & mask); - MMC3_FixCHR(); - } -} - -static DECLFW(M534IRQWrite) { - V ^= 0xFF; - MMC3_IRQWrite(A, V); -} - -static DECLFW(M126MMC3Write) { - if ((reg[3] & 0x09) == 0x09) { - MMC3_Write(0x8000 | (((reg[3] & 0x08) ? 0x01 : A) & 0x01), V); - } else { - MMC3_Write(A, V); - } -} - -static void M126Reset(void) { - dipsw++; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Reset(); -} - -static void M126Power(void) { - dipsw = 0; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M126WriteWRAM); - SetWriteHandler(0x8000, 0xFFFF, M126MMC3Write); - SetReadHandler(0x8000, 0xFFFF, M126ReadDIP); - if (iNESCart.mapper == 534) { - SetWriteHandler(0xC000, 0xDFFF, M534IRQWrite); - } -} - -static void InitCommon(CartInfo *info) { - uint8 ws = 8; - if (info->iNES2) { - ws = (info->PRGRamSize + info->PRGRamSaveSize) / 1024; - } - MMC3_Init(info, ws, info->battery); - MMC3_FixMIR = M126MIR; - MMC3_cwrap = M126CW; - MMC3_pwrap = M126PW; - info->Power = M126Power; - info->Reset = M126Reset; - AddExState(StateRegs, ~0, 0, NULL); - - switch (iNESCart.CRC32) { - case 0xEAD80031: /* Gamezone 118-in-1 (AT-207) */ - case 0x6FCBC309: /* Power Joy Classic TV Game 84-in-1 (PJ-008) */ - case 0x6D61FE21: /* 1998 4000000-in-1 (BS-400 PCB) */ - case 0x3FF46175: - case 0xA3FF9D9B: - case 0x2BDD0FC2: - case 0x5789017D: /* (GD-106) 18-in-1 */ - case 0x46A01871: /* 3000000-in-1 (BS-300 PCB) */ - case 0x2466B80A: /* 700000-in-1 (BS-400 PCB) */ - case 0x871CFD16: - case 0xB2724618: - case 0x42A9219D: - oldump = TRUE; - break; - } -} - -void Mapper126_Init(CartInfo *info) { - InitCommon(info); -} - -void Mapper422_Init(CartInfo *info) { - InitCommon(info); -} - -void Mapper534_Init(CartInfo *info) { - InitCommon(info); -} diff --git a/src/mappers/mapper127.c b/src/mappers/mapper127.c deleted file mode 100644 index a1c15ea7b..000000000 --- a/src/mappers/mapper127.c +++ /dev/null @@ -1,116 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[4], chr[8], nt[4]; -static uint8 IRQCount, IRQa; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { nt, 4, "NTAM" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 1, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - prg[3] |= 0x0C; - setprg8(0x8000, prg[0] & 0x0F); - setprg8(0xA000, prg[1] & 0x0F); - setprg8(0xC000, prg[2] & 0x0F); - setprg8(0xE000, prg[3] & 0x0F); - - setchr1(0x0000, chr[0] & 0x7F); - setchr1(0x0400, chr[1] & 0x7F); - setchr1(0x0800, chr[2] & 0x7F); - setchr1(0x0C00, chr[3] & 0x7F); - setchr1(0x1000, chr[4] & 0x7F); - setchr1(0x1400, chr[5] & 0x7F); - setchr1(0x1800, chr[6] & 0x7F); - setchr1(0x1C00, chr[7] & 0x7F); - - setmirrorw(nt[0] & 0x01, nt[1] & 0x01, nt[2] & 0x01, nt[3] & 0x01); -} - -static DECLFW(M127Write) { - switch (A & 0x73) { - case 0x00: case 0x01: case 0x02: case 0x03: - prg[A & 3] = V; - Sync(); - break; - - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x20: case 0x21: case 0x22: case 0x23: - chr[((A >> 3) & 4) | (A & 3)] = V; - Sync(); - break; - - case 0x30: case 0x31: case 0x32: case 0x33: - IRQa = 1; - break; - - case 0x40: case 0x41: case 0x42: case 0x43: - IRQa = 0; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - - case 0x50: case 0x51: case 0x52: case 0x53: - nt[A & 3] = V; - Sync(); - break; - } -} - -static void M127Power(void) { - prg[0] = prg[1] = prg[2] = prg[3] = ~0; - chr[0] = chr[1] = chr[2] = chr[3] = 0; - chr[4] = chr[5] = chr[6] = chr[7] = 0; - nt[0] = nt[1] = nt[2] = nt[3] = 0; - IRQa = IRQCount = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M127Write); -} - -static void M127IRQHook(int a) { - int count = a; - while (count--) { - if (IRQa) { - IRQCount--; - if (!IRQCount) { - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper127_Init(CartInfo *info) { - info->Power = M127Power; - MapIRQHook = M127IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper128.c b/src/mappers/mapper128.c deleted file mode 100644 index 9669c5673..000000000 --- a/src/mappers/mapper128.c +++ /dev/null @@ -1,61 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static uint16 reg = 0; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, (reg >> 2) | (latch.data & 0x07)); - setprg16(0xC000, (reg >> 2) | 0x07); - setchr8(0); - setmirror(((reg >> 1) & 0x01) ^ 0x01); -} - -static DECLFW(M128Write) { - if (reg < 0xF000) { - reg = A & 0xFFFF; - } - Latch_Write(A, V); -} - -static void M128Reset(void) { - reg = 0; - Latch_RegReset(); -} - -static void M128Power(void) { - reg = 0; - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M128Write); -} - -void Mapper128_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M128Power; - info->Reset = M128Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper132.c b/src/mappers/mapper132.c deleted file mode 100644 index 3f01e5958..000000000 --- a/src/mappers/mapper132.c +++ /dev/null @@ -1,98 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "txc.h" - -/**** LEGACY MAPPER IMPLEMENTATION ****/ - -static uint8 reg[4]; - -static SFORMAT UNL22211StateRegs[] = { - { reg, 4, "REGS" }, - { 0 } -}; - -static void UNL22211Sync(void) { - setprg32(0x8000, (reg[2] >> 2) & 1); - setchr8(reg[2] & 3); -} - -static DECLFW(UNL22211WriteLo) { - if (A & 0x100) { - reg[A & 3] = V; - UNL22211Sync(); - } -} - -static DECLFR(UNL22211ReadLo) { - return ((reg[1] ^ reg[2]) | 0x40); -} - -static void UNL22211Power(void) { - UNL22211Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x4100, UNL22211ReadLo); - SetWriteHandler(0x4100, 0x4FFF, UNL22211WriteLo); -} - -static void UNL22211StateRestore(int version) { - UNL22211Sync(); -} - -static void UNL22211_Init(CartInfo *info) { - info->Power = UNL22211Power; - GameStateRestore = UNL22211StateRestore; - AddExState(&UNL22211StateRegs, ~0, 0, 0); -} - -/* Mapper 132 */ - -static void M132Sync(void) { - setprg32(0x8000, (txc.output >> 2) & 0x01); - setchr8(txc.output & 0x03); -} - -static DECLFW(M132Write) { - TXC_Write(A, V & 0x0F); -} - -static DECLFR(M132Read) { - return ((CPU_OPENBUS & 0xF0) | (TXC_Read(A) & 0x0F)); -} - -static void M132Power(void) { - TXC_Power(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x5FFF, M132Read); - SetWriteHandler(0x4100, 0xFFFF, M132Write); -} - -void Mapper132_Init(CartInfo *info) { - if ((info->CRC32) == 0x2A5F4C5A) { - /* Jin Gwok Sei Chuen Saang (Ch) [U][!] */ - FCEU_printf(" WARNING: Using alternate mapper implementation.\n"); - UNL22211_Init(info); - return; - } - TXC_Init(info, M132Sync); - info->Power = M132Power; -} diff --git a/src/mappers/mapper133.c b/src/mappers/mapper133.c deleted file mode 100644 index a0217d7f3..000000000 --- a/src/mappers/mapper133.c +++ /dev/null @@ -1,59 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 133 - Sachen 3009 */ - -#include "mapinc.h" - -static uint8 reg = 0; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, (reg >> 2) & 0x01); - setchr8(reg & 0x03); -} - -static DECLFW(M133Write) { - if (A & 0x100) { - reg = V; - Sync(); - } -} - -static void M133Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, M133Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper133_Init(CartInfo *info) { - info->Power = M133Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper134.c b/src/mappers/mapper134.c deleted file mode 100644 index 09ca3975a..000000000 --- a/src/mappers/mapper134.c +++ /dev/null @@ -1,112 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Chipset used on various PCBs named WX-KB4K, T4A54A, BS-5652... */ -/* "Rockman 3" on YH-322 and "King of Fighters 97" on "Super 6-in-1" enable interrupts without initializing the frame IRQ register and therefore freeze on real hardware. - They can run if another game is selected that does initialize the frame IRQ register, then soft-resetting to the menu and selecting the previously-freezing games. */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M134PW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x04) ? 0x0F : 0x1F; - uint16 base = ((reg[1] << 4) & 0x30) | ((reg[0] << 2) & 0x40); - - if (reg[1] & 0x80) { /* NROM mode */ - if (reg[1] & 0x08) { /* NROM-128 mode */ - setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~1) | 0); - setprg8(0xA000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~1) | 1); - setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~1) | 0); - setprg8(0xE000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~1) | 1); - } else { /* NROM-256 mode */ - setprg8(0x8000, (base & ~mask) | (((mmc3.reg[6] & ~0x02) & mask) & ~1) | 0); - setprg8(0xA000, (base & ~mask) | (((mmc3.reg[6] & ~0x02) & mask) & ~1) | 1); - setprg8(0xC000, (base & ~mask) | (((mmc3.reg[6] | 0x02) & mask) & ~1) | 0); - setprg8(0xE000, (base & ~mask) | (((mmc3.reg[6] | 0x02) & mask) & ~1) | 1); - } - } else { /* MMC3 */ - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static void M134CW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x40) ? 0x7F : 0xFF; - uint16 base = ((reg[1] << 3) & 0x180) | ((reg[0] << 4) & 0x200); - - if (reg[0] & 0x08) { /* In CNROM mode, outer bank register 2 replaces the MMC3's CHR registers, and CHR A10-A12 are PPU A10-A12. */ - setchr8(((base & ~mask) >> 3) | (reg[2] & (mask >> 3))); - } else { - setchr1(A, (base & ~mask) | (V & mask)); - } -} - -static DECLFR(M134Read) { - if (reg[0] & 0x40) { - return dipsw; - } - return CartBR(A); -} - -static DECLFW(M134Write) { - if (MMC3_WramIsWritable()) { - CartBW(A, V); - if (!(reg[0] & 0x80)) { - reg[A & 0x03] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } else if ((A & 0x03) == 2) { - reg[2] = (reg[2] & ~0x03) | (V & 0x03); - MMC3_FixCHR(); - } - } -} - -static void M134Reset(void) { - dipsw++; - dipsw &= 15; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Reset(); -} - -static void M134Power(void) { - dipsw = 0; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M134Write); - SetReadHandler(0x8000, 0xFFFF, M134Read); -} - -void Mapper134_Init(CartInfo *info) { - MMC3_Init(info, info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) / 1024 : 8, info->battery); - MMC3_cwrap = M134CW; - MMC3_pwrap = M134PW; - info->Power = M134Power; - info->Reset = M134Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper136.c b/src/mappers/mapper136.c deleted file mode 100644 index a7db207e1..000000000 --- a/src/mappers/mapper136.c +++ /dev/null @@ -1,48 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "jv001.h" - -static void M136Sync(void) { - setprg32(0x8000, (jv001.output >> 4) & 0x01); - setchr8(jv001.output & 0x07); -} - -static DECLFW(M136Write) { - JV001_Write(A, V & 0x3F); -} - -static DECLFR(M136Read) { - return ((CPU_OPENBUS & 0xC0) | (JV001_Read(A) & 0x3F)); -} - -static void M136Power(void) { - JV001_Power(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x5FFF, M136Read); - SetWriteHandler(0x4100, 0xFFFF, M136Write); -} - -void Mapper136_Init(CartInfo *info) { - JV001_Init(info, M136Sync); - info->Power = M136Power; -} diff --git a/src/mappers/mapper137.c b/src/mappers/mapper137.c deleted file mode 100644 index a1def8670..000000000 --- a/src/mappers/mapper137.c +++ /dev/null @@ -1,77 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 137 - Sachen 8259D */ - -#include "mapinc.h" - -static uint8 cmd; -static uint8 reg[8]; - -static SFORMAT StateRegs[] = { - { reg, 8, "REGS" }, - { &cmd, 1, "CMD0" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg[5]); - setchr1(0x0000, (reg[0] & 0x07)); - setchr1(0x0400, ((reg[4] << 4) & 0x10) | (reg[(reg[7] & 0x01) ? 0 : 1] & 0x07)); - setchr1(0x0800, ((reg[4] << 3) & 0x10) | (reg[(reg[7] & 0x01) ? 0 : 2] & 0x07)); - setchr1(0x0C00, ((reg[4] << 2) & 0x10) | ((reg[6] << 3) & 0x08) | (reg[(reg[7] & 0x01) ? 0 : 3] & 0x07)); - setchr4(0x1000, ~0); - switch (reg[7] & 0x07) { - default: setmirror(MI_H); break; - case 2: setmirror(MI_V); break; - case 4: setmirrorw(0, 0, 0, 1); break; - case 6: setmirror(MI_0); break; - } -} - -static DECLFW(M137Write) { - if ((A & 0x4000) && (A & 0x100)) { - if (A & 0x01) { - reg[cmd & 0x07] = V; - Sync(); - } else { - cmd = V; - } - } -} - -static void M137Reset(void) { - cmd = 0; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - reg[4] = reg[5] = reg[6] = reg[7] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0xFFFF, M137Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper137_Init(CartInfo *info) { - info->Power = M137Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper138.c b/src/mappers/mapper138.c deleted file mode 100644 index bf8c45ee5..000000000 --- a/src/mappers/mapper138.c +++ /dev/null @@ -1,76 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 138 - Sachen 8259B */ - -#include "mapinc.h" - -static uint8 cmd; -static uint8 reg[8]; - -static SFORMAT StateRegs[] = { - { reg, 8, "REGS" }, - { &cmd, 1, "CMD0" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg[5]); - setchr2(0x0000, ((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 0] & 0x07))); - setchr2(0x0800, ((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 1] & 0x07))); - setchr2(0x1000, ((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 2] & 0x07))); - setchr2(0x1800, ((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 3] & 0x07))); - switch (reg[7] & 0x07) { - case 0: setmirrorw(0, 0, 0, 1); break; - case 2: setmirror(MI_H); break; - default: setmirror(MI_V); break; - case 6: setmirror(MI_0); break; - } -} - -static DECLFW(M138Write) { - if ((A & 0x4000) && (A & 0x100)) { - if (A & 0x01) { - reg[cmd & 0x07] = V; - Sync(); - } else { - cmd = V; - } - } -} - -static void M138Reset(void) { - cmd = 0; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - reg[4] = reg[5] = reg[6] = reg[7] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0xFFFF, M138Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper138_Init(CartInfo *info) { - info->Power = M138Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper139.c b/src/mappers/mapper139.c deleted file mode 100644 index 490fc999b..000000000 --- a/src/mappers/mapper139.c +++ /dev/null @@ -1,76 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 139 - Sachen 8259C */ - -#include "mapinc.h" - -static uint8 cmd; -static uint8 reg[8]; - -static SFORMAT StateRegs[] = { - { reg, 8, "REGS" }, - { &cmd, 1, "CMD0" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg[5]); - setchr2(0x0000, ((((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 0] & 0x07)) << 2) | 0)); - setchr2(0x0800, ((((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 1] & 0x07)) << 2) | 1)); - setchr2(0x1000, ((((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 2] & 0x07)) << 2) | 2)); - setchr2(0x1800, ((((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 3] & 0x07)) << 2) | 3)); - switch (reg[7] & 0x07) { - case 0: setmirrorw(0, 0, 0, 1); break; - case 2: setmirror(MI_H); break; - default: setmirror(MI_V); break; - case 6: setmirror(MI_0); break; - } -} - -static DECLFW(M139Write) { - if ((A & 0x4000) && (A & 0x100)) { - if (A & 0x01) { - reg[cmd & 0x07] = V; - Sync(); - } else { - cmd = V; - } - } -} - -static void M139Reset(void) { - cmd = 0; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - reg[4] = reg[5] = reg[6] = reg[7] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0xFFFF, M139Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper139_Init(CartInfo *info) { - info->Power = M139Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper140.c b/src/mappers/mapper140.c deleted file mode 100644 index 18c54929e..000000000 --- a/src/mappers/mapper140.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REG" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg >> 4); - setchr8(reg & 0x0F); -} - -static DECLFW(M140Write) { - reg = V; - Sync(); -} - -static void M140Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, M140Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper140_Init(CartInfo *info) { - info->Power = M140Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper141.c b/src/mappers/mapper141.c deleted file mode 100644 index 270ad32f1..000000000 --- a/src/mappers/mapper141.c +++ /dev/null @@ -1,80 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 141 - Sachen 8259A */ - -#include "mapinc.h" - -static uint8 cmd; -static uint8 reg[8]; - -static SFORMAT StateRegs[] = { - { reg, 8, "REGS" }, - { &cmd, 1, "CMD0" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg[5]); - if (!CHR_ROM_SIZE) { - setchr8(0); - } else { - setchr2(0x0000, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 0] & 0x07)) << 1) | 0); - setchr2(0x0800, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 1] & 0x07)) << 1) | 1); - setchr2(0x1000, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 2] & 0x07)) << 1) | 0); - setchr2(0x1800, (((reg[4] << 3) | (reg[(reg[7] & 0x01) ? 0 : 3] & 0x07)) << 1) | 1); - } - switch (reg[7] & 0x07) { - case 0: setmirrorw(0, 0, 0, 1); break; - case 2: setmirror(MI_H); break; - default: setmirror(MI_V); break; - case 6: setmirror(MI_0); break; - } -} - -static DECLFW(M141Write) { - if ((A & 0x4000) && (A & 0x100)) { - if (A & 0x01) { - reg[cmd & 0x07] = V; - Sync(); - } else { - cmd = V; - } - } -} - -static void M141Reset(void) { - cmd = 0; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - reg[4] = reg[5] = reg[6] = reg[7] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0xFFFF, M141Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper141_Init(CartInfo *info) { - info->Power = M141Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper142.c b/src/mappers/mapper142.c deleted file mode 100644 index 55b519d9d..000000000 --- a/src/mappers/mapper142.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 142 - UNL KS7032 */ - - #include "mapinc.h" - #include "ks202.h" - - static void Sync(void) { - setprg8(0x6000, ks202.reg[4] & 0x0F); - setprg8(0x8000, ks202.reg[1] & 0x0F); - setprg8(0xA000, ks202.reg[2] & 0x0F); - setprg8(0xC000, ks202.reg[3] & 0x0F); - setprg8(0xE000, ~0 & 0x0F); - setchr8(0); -} - -void Mapper142_Init(CartInfo *info) { - KS202_Init(info, Sync, 0, 0); -} diff --git a/src/mappers/mapper143.c b/src/mappers/mapper143.c deleted file mode 100644 index 2f724de3c..000000000 --- a/src/mappers/mapper143.c +++ /dev/null @@ -1,41 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 143 - TC-A01 */ - -#include "mapinc.h" - -static DECLFR(M143Read) { - if ((A & 0x100) == 0x100) { - return (CPU_OPENBUS & 0xC0) | ((~A) & 0x3F); - } - return CPU_OPENBUS; -} - -static void M143Power(void) { - setprg32(0x8000, 0); - setchr8(0); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x5FFF, M143Read); -} - -void Mapper143_Init(CartInfo *info) { - info->Power = M143Power; -} diff --git a/src/mappers/mapper144.c b/src/mappers/mapper144.c deleted file mode 100644 index 982c0bee6..000000000 --- a/src/mappers/mapper144.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.data); - setchr8(latch.data >> 4); -} - -static DECLFW(M144Write) { - uint8 reg = CartBR(A); - latch.data = reg & ((V & reg) | 0x01); - Sync(); -} - -static void M144Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M144Write); -} - -void Mapper144_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Power = M144Power; -} diff --git a/src/mappers/mapper145.c b/src/mappers/mapper145.c deleted file mode 100644 index ecad0f046..000000000 --- a/src/mappers/mapper145.c +++ /dev/null @@ -1,54 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 145 - Sachen SA-72007 */ - -#include "mapinc.h" - -static uint8 reg = 0; - -static void Sync(void) { - setprg32(0x8000, 0); - setchr8(reg >> 7); -} - -static DECLFW(M145Write) { - if (A & 0x100) { - reg = V; - Sync(); - } -} - -static void M145Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, M145Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper145_Init(CartInfo *info) { - info->Power = M145Power; - GameStateRestore = StateRestore; - AddExState(®, 1, 0, "REG0"); -} diff --git a/src/mappers/mapper147.c b/src/mappers/mapper147.c deleted file mode 100644 index 94900d3b1..000000000 --- a/src/mappers/mapper147.c +++ /dev/null @@ -1,49 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "jv001.h" - -static void M147Sync(void) { - setprg32(0x8000, ((jv001.output >> 4) & 0x02) | (jv001.output & 0x01)); - setchr8((jv001.output >> 1) & 0x0F); -} - -static DECLFW(M147Write) { - JV001_Write(A, ((V >> 2) & 0x3F) | ((V << 6) & 0xC0)); -} - -static DECLFR(M147Read) { - uint8 ret = JV001_Read(A); - return ((ret << 2) | ((ret >> 6) & 0x03)); -} - -static void M147Power(void) { - JV001_Power(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x5FFF, M147Read); - SetWriteHandler(0x4100, 0xFFFF, M147Write); -} - -void Mapper147_Init(CartInfo *info) { - JV001_Init(info, M147Sync); - info->Power = M147Power; -} diff --git a/src/mappers/mapper148.c b/src/mappers/mapper148.c deleted file mode 100644 index 31bd13291..000000000 --- a/src/mappers/mapper148.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 148 - Sachen SA-008-A and Tengen 800008 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, (latch.data >> 3) & 0x01); - setchr8(latch.data & 0x07); -} - -void Mapper148_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper149.c b/src/mappers/mapper149.c deleted file mode 100644 index 59db1366f..000000000 --- a/src/mappers/mapper149.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 149 - Sachen SA-0036 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, 0); - setchr8(latch.data >> 7); -} - -void Mapper149_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper150.c b/src/mappers/mapper150.c deleted file mode 100644 index 14fac6e67..000000000 --- a/src/mappers/mapper150.c +++ /dev/null @@ -1,102 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 150 - SA-015 / SA-630 / Unif UNL-Sachen-74LS374N */ -/* Mapper 243 - SA-020A */ - -#include "mapinc.h" - -static uint8 dipsw; -static uint8 cmd; -static uint8 reg[8]; - -static SFORMAT StateRegs[] = { - { reg, 8, "REGS" }, - { &dipsw, 1, "DPSW" }, - { &cmd, 1, "CMD0" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, (reg[2] & 0x01) | reg[5]); - if (iNESCart.mapper == 243) { - setchr8((reg[2] & 0x01) | ((reg[4] << 1) & 0x02) | (reg[6] << 2)); - } else { - setchr8((reg[6] & 0x03) | ((reg[4] << 2) & 0x04) | (reg[2] << 3)); - } - switch ((reg[7] >> 1) & 0x03) { - case 0: setmirrorw(0, 1, 1, 1); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_V); break; - case 3: setmirror(MI_0); break; - } -} - -static DECLFR(M150Read) { - if ((A & 0x101) == 0x101) { - if (dipsw & 1) - return (reg[cmd] & 0x03) | (CPU_OPENBUS & 0xFC); - else - return (reg[cmd] & 0x07) | (CPU_OPENBUS & 0xF8); - } - return CPU_OPENBUS; -} - -static DECLFW(M150Write) { - if (dipsw & 0x01) - V |= 0x04; - switch (A & 0x101) { - case 0x100: - cmd = V & 0x07; - break; - case 0x101: - reg[cmd] = V & 0x07; - Sync(); - break; - } -} - -static void M150Restore(int version) { - Sync(); -} - -static void M150Reset(void) { - dipsw ^= 0x01; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - reg[4] = reg[5] = reg[6] = reg[7] = 0; - Sync(); -} - -static void M150Power(void) { - dipsw = 0; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - reg[4] = reg[5] = reg[6] = reg[7] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x5FFF, M150Read); - SetWriteHandler(0x4100, 0x5FFF, M150Write); -} - -void Mapper150_Init(CartInfo *info) { - info->Power = M150Power; - info->Reset = M150Reset; - GameStateRestore = M150Restore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper152.c b/src/mappers/mapper152.c deleted file mode 100644 index 4f251843a..000000000 --- a/src/mappers/mapper152.c +++ /dev/null @@ -1,34 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.data >> 4); - setprg16(0xc000, ~0); - setchr8(latch.data & 0x0F); - setmirror(MI_0 + ((latch.data >> 7) & 0x01)); /* Saint Seiya...hmm. */ -} - -void Mapper152_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper153.c b/src/mappers/mapper153.c deleted file mode 100644 index 9eb432e90..000000000 --- a/src/mappers/mapper153.c +++ /dev/null @@ -1,91 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "eeprom_x24c0x.h" -#include "bandai.h" - -static uint8 outer; - -/* Famicom jump 2: - * 0-7: Lower bit of data selects which 256KB PRG block is in use. - * This seems to be a hack on the developers' part, so I'll make emulation - * of it a hack(I think the current PRG block would depend on whatever the - * lowest bit of the CHR bank switching register that corresponds to the - * last CHR address read). - */ - -static SFORMAT StateRegs[] = { - { &outer, 1, "OUTB" }, - { 0 } -}; - -static void M153PW(uint16 A, uint16 V) { - setprg16(A, ((outer << 4) & 0x10) | (V & 0x0F)); -} - -static void M153CW(uint16 A, uint16 V) { - setchr8(0); -} - -static DECLFW(M153Write) { - if ((A & 0x0F) <= 0x03) { - outer = V; - BANDAI_FixPRG(); - } - BANDAI_Write(A, V); -} - -static void M153Power(void) { - BANDAI_Power(); - SetWriteHandler(0x8000, 0xFFFF, M153Write); - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } -} - -static void M153Close(void) { -} - -void Mapper153_Init(CartInfo *info) { - BANDAI_Init(info, EEPROM_NONE, FALSE); - info->Power = M153Power; - info->Close = M153Close; - BANDAI_pwrap = M153PW; - BANDAI_cwrap = M153CW; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } -} diff --git a/src/mappers/mapper154.c b/src/mappers/mapper154.c deleted file mode 100644 index f3f8fc3a5..000000000 --- a/src/mappers/mapper154.c +++ /dev/null @@ -1,73 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 154 It is identical to Mapper 88, but with the addition of a single bit allowing for mapper-controlled one-screen regoring: */ - -#include "mapinc.h" -#include "n118.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M154Mirroring(void) { - setmirror(MI_0 + ((reg >> 6) & 0x01)); -} - -static void M154FixCHR(void) { - setchr2(0x0000, (n118.reg[0] & 0x3F) >> 1); - setchr2(0x0800, (n118.reg[1] & 0x3F) >> 1); - setchr1(0x1000, 0x40 | (n118.reg[2] & 0x3F)); - setchr1(0x1400, 0x40 | (n118.reg[3] & 0x3F)); - setchr1(0x1800, 0x40 | (n118.reg[4] & 0x3F)); - setchr1(0x1C00, 0x40 | (n118.reg[5] & 0x3F)); -} - -static DECLFW(M154Write) { - if (A < 0xA000) { - N118_Write(A, V); - } - reg = V; /* mirroring latch */ - M154Mirroring(); -} - -static void M154Power(void) { - reg = 0; - N118_Power(); - SetWriteHandler(0x8000, 0xFFFF, M154Write); -} - -static void StateRestore(int version) { - N118_FixPRG(); - N118_FixCHR(); - M154Mirroring(); -} - -void Mapper154_Init(CartInfo *info) { - N118_Init(info, 0, 0); - info->Power = M154Power; - N118_FixCHR = M154FixCHR; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper155.c b/src/mappers/mapper155.c deleted file mode 100644 index 16a9906bb..000000000 --- a/src/mappers/mapper155.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc1.h" - -static void M155PW(uint16 A, uint16 V) { - setprg16(A, (MMC1_GetCHRBank(0) & 0x10) | (V & 0x0F)); -} - -/* Same as mapper 1, without respect for WRAM enable bit. */ -void Mapper155_Init(CartInfo *info) { - MMC1_Init(info, 8, info->battery ? 8 : 0); - MMC1_pwrap = M155PW; - mmc1_type = MMC1A; -} diff --git a/src/mappers/mapper156.c b/src/mappers/mapper156.c deleted file mode 100644 index 423d93ff7..000000000 --- a/src/mappers/mapper156.c +++ /dev/null @@ -1,128 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * DIS23C01 DAOU ROM CONTROLLER, Korea - * Metal Force (K) - * Buzz and Waldog (K) - * General's Son (K) - * - */ - -#include "mapinc.h" - -static uint8 prg, mirr; -static uint16 chr[8]; - -static SFORMAT StateRegs[] = { - { chr, 16, "CREG" }, - { &prg, 1, "PREG" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, prg); - setprg16(0xC000, ~0); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - switch (mirr) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - default: setmirror(MI_0); break; - } -} - -static DECLFW(M156Write) { - uint8 index = A & 0x03; - - switch (A & 0xCFFC) { - case 0xC000: - chr[0 | index] = (chr[0 | index] & 0xFF00) | V; - Sync(); - break; - case 0xC004: - chr[0 | index] = (chr[0 | index] & 0x00FF) | V << 8; - Sync(); - break; - case 0xC008: - chr[4 | index] = (chr[4 | index] & 0xFF00) | V; - Sync(); - break; - case 0xC00C: - chr[4 | index] = (chr[4 | index] & 0x00FF) | V << 8; - Sync(); - break; - case 0xC010: - prg = V; - Sync(); - break; - case 0xC014: - mirr = V; - Sync(); - break; - } -} - -static void M156Reset(void) { - int i; - for (i = 0; i < 8; i++) { - chr[i] = 0; - } - prg = 0; - mirr = 2; -} - -static void M156Power(void) { - M156Reset(); - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0xC000, 0xCFFF, M156Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M156Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper156_Init(CartInfo *info) { - info->Reset = M156Reset; - info->Power = M156Power; - info->Close = M156Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper157.c b/src/mappers/mapper157.c deleted file mode 100644 index 24d63fa99..000000000 --- a/src/mappers/mapper157.c +++ /dev/null @@ -1,290 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* FIXME: Bar code input interface not attached yet */ - -#include "mapinc.h" -#include "eeprom_x24c0x.h" -#include "bandai.h" - -/* Datach Barcode Battler */ - -static uint8 BarcodeData[256]; -static int BarcodeReadPos; -static int BarcodeCycleCount; -static uint32 BarcodeOut; - -/* #define INTERL2OF5 */ - -int FCEUI_DatachSet(uint8 *rcode) { - int prefix_parity_type[10][6] = { - { 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1 }, { 0, 0, 1, 1, 0, 1 }, { 0, 0, 1, 1, 1, 0 }, - { 0, 1, 0, 0, 1, 1 }, { 0, 1, 1, 0, 0, 1 }, { 0, 1, 1, 1, 0, 0 }, { 0, 1, 0, 1, 0, 1 }, - { 0, 1, 0, 1, 1, 0 }, { 0, 1, 1, 0, 1, 0 } - }; - int data_left_odd[10][7] = { - { 0, 0, 0, 1, 1, 0, 1 }, { 0, 0, 1, 1, 0, 0, 1 }, { 0, 0, 1, 0, 0, 1, 1 }, { 0, 1, 1, 1, 1, 0, 1 }, - { 0, 1, 0, 0, 0, 1, 1 }, { 0, 1, 1, 0, 0, 0, 1 }, { 0, 1, 0, 1, 1, 1, 1 }, { 0, 1, 1, 1, 0, 1, 1 }, - { 0, 1, 1, 0, 1, 1, 1 }, { 0, 0, 0, 1, 0, 1, 1 } - }; - int data_left_even[10][7] = { - { 0, 1, 0, 0, 1, 1, 1 }, { 0, 1, 1, 0, 0, 1, 1 }, { 0, 0, 1, 1, 0, 1, 1 }, { 0, 1, 0, 0, 0, 0, 1 }, - { 0, 0, 1, 1, 1, 0, 1 }, { 0, 1, 1, 1, 0, 0, 1 }, { 0, 0, 0, 0, 1, 0, 1 }, { 0, 0, 1, 0, 0, 0, 1 }, - { 0, 0, 0, 1, 0, 0, 1 }, { 0, 0, 1, 0, 1, 1, 1 } - }; - int data_right[10][7] = { - { 1, 1, 1, 0, 0, 1, 0 }, { 1, 1, 0, 0, 1, 1, 0 }, { 1, 1, 0, 1, 1, 0, 0 }, { 1, 0, 0, 0, 0, 1, 0 }, - { 1, 0, 1, 1, 1, 0, 0 }, { 1, 0, 0, 1, 1, 1, 0 }, { 1, 0, 1, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 0, 0 }, - { 1, 0, 0, 1, 0, 0, 0 }, { 1, 1, 1, 0, 1, 0, 0 } - }; - uint8 code[13 + 1]; - uint32 tmp_p = 0; - uint32 csum = 0; - int i, j; - int len; - - for (i = len = 0; i < 13; i++) { - if (!rcode[i]) break; - if ((code[i] = rcode[i] - '0') > 9) - return(0); - len++; - } - if (len != 13 && len != 12 && len != 8 && len != 7) return(0); - - #define BS(x) BarcodeData[tmp_p] = x; tmp_p++ - - for (j = 0; j < 32; j++) { /* delay before sending a code */ - BS(0x00); - } - -#ifdef INTERL2OF5 - - BS(1); BS(1); BS(0); BS(0); /* 1 */ - BS(1); BS(1); BS(0); BS(0); /* 1 */ - BS(1); BS(1); BS(0); BS(0); /* 1 */ - BS(1); BS(1); BS(0); BS(0); /* 1 */ - BS(1); BS(1); BS(0); BS(0); /* 1 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 */ - BS(1); BS(0); BS(0); /* 0 cs */ - BS(1); BS(1); BS(0); BS(0); /* 1 */ - -#else - /* Left guard bars */ - BS(1); BS(0); BS(1); - - if (len == 13 || len == 12) { - - for (i = 0; i < 6; i++) { - if (prefix_parity_type[code[0]][i]) { - for (j = 0; j < 7; j++) { - BS(data_left_even[code[i + 1]][j]); - } - } else { - for (j = 0; j < 7; j++) { - BS(data_left_odd[code[i + 1]][j]); - } - } - } - - /* Center guard bars */ - BS(0); BS(1); BS(0); BS(1); BS(0); - - for (i = 7; i < 12; i++) { - for (j = 0; j < 7; j++) { - BS(data_right[code[i]][j]); - } - } - /* Calc and write down the control code if not assigned, instead, send code as is - Battle Rush uses modified type of codes with different control code calculation */ - if (len == 12) { - for (i = 0; i < 12; i++) { - csum += code[i] * ((i & 1) ? 3 : 1); - } - csum = (10 - (csum % 10)) % 10; - rcode[12] = csum + 0x30; /* update check code to the input string as well */ - rcode[13] = 0; - code[12] = csum; - } - for (j = 0; j < 7; j++) { - BS(data_right[code[12]][j]); - } - } else if (len == 8 || len == 7) { - for (i = 0; i < 4; i++) { - for (j = 0; j < 7; j++) { - BS(data_left_odd[code[i]][j]); - } - } - - /* Center guard bars */ - BS(0); BS(1); BS(0); BS(1); BS(0); - - for (i = 4; i < 7; i++) { - for (j = 0; j < 7; j++) { - BS(data_right[code[i]][j]); - } - } - csum = 0; - for (i = 0; i < 7; i++) { - csum += (i & 1) ? code[i] : (code[i] * 3); - } - csum = (10 - (csum % 10)) % 10; - rcode[7] = csum + 0x30; /* update check code to the input string as well */ - rcode[8] = 0; - for (j = 0; j < 7; j++) { - BS(data_right[csum][j]); - } - } - - /* Right guard bars */ - BS(1); BS(0); BS(1); -#endif - - for (j = 0; j < 32; j++) { - BS(0x00); - } - - BS(0xFF); - - #undef BS - - BarcodeReadPos = 0; - BarcodeOut = 0x8; - BarcodeCycleCount = 0; - return(1); -} - -static uint8 latch; -static uint8 hasExternalEEPROM = FALSE; -/* first 256K is internal eeprom data, 2nd 256 is for external eeprom if used. - * Combined here for simplicity and frontend save compatibility */ -static uint8 eeprom[512]; - -static void M157PW(uint16 A, uint16 V) { - setprg16(A, V & 0x0F); -} - -static void M157CW(uint16 A, uint16 V) { - setchr8(0); -} - -static DECLFW(M157Write) { - switch (A & 0x0F) { - case 0x00: - if (hasExternalEEPROM) { - latch = (latch & ~0x20) | ((V << 2) & 0x20); - x24c01_write(latch); - } - break; - case 0x0D: - if (hasExternalEEPROM) { - latch = (V & ~0x20) | (latch & 0x20); - x24c01_write(latch); - } - x24c02_write(V); - break; - default: - BANDAI_Write(A, V); - break; - } -} - -static void M157IRQHook(int a) { - BANDAI_IRQHook(a); - - BarcodeCycleCount += a; - if (BarcodeCycleCount >= 1000) { - BarcodeCycleCount -= 1000; - if (BarcodeData[BarcodeReadPos] == 0xFF) { - BarcodeOut = 0; - } else { - BarcodeOut = (BarcodeData[BarcodeReadPos] ^ 1) << 3; - BarcodeReadPos++; - } - } -} - -static DECLFR(M157Read) { - return ((CPU_OPENBUS & 0xE7) | ((x24c02_read() | x24c01_read()) << 4) | BarcodeOut); -} - -static void M157Power(void) { - BANDAI_Reset(); - - BarcodeData[0] = 0xFF; - BarcodeReadPos = 0; - BarcodeOut = 0; - BarcodeCycleCount = 0; - - SetReadHandler(0x6000, 0x7FFF, M157Read); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M157Write); -} - -void Mapper157_Init(CartInfo *info) { - BANDAI_Init(info, EEPROM_NONE, FALSE); - BANDAI_pwrap = M157PW; - BANDAI_cwrap = M157CW; - - info->Power = M157Power; - MapIRQHook = M157IRQHook; - - GameInfo->cspecial = SIS_DATACH; - - /* internal eeprom shared among all games - and always enabled regardless of battery flag */ - info->battery = 1; - x24c02_init(eeprom); - AddExState(&x24c02_StateRegs, ~0, 0, 0); - - if (info->PRGRamSaveSize && info->PRGRamSaveSize <= 128) { - /* additional 128 external eeprom */ - x24c01_init(&eeprom[256]); - AddExState(&x24c01_StateRegs, ~0, 0, 0); - AddExState(&latch, 1, 0, "LATC"); - hasExternalEEPROM = TRUE; - } - - if (hasExternalEEPROM) { - info->SaveGame[0] = eeprom; - info->SaveGameLen[0] = 512; - } else { - info->SaveGame[0] = eeprom; - info->SaveGameLen[0] = 256; - } -} diff --git a/src/mappers/mapper159.c b/src/mappers/mapper159.c deleted file mode 100644 index 91d8e0bd1..000000000 --- a/src/mappers/mapper159.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "eeprom_x24c0x.h" -#include "bandai.h" - -static void M159PW(uint16 A, uint16 V) { - setprg16(A, V & 0x1F); /* map upto 512K PRG for fan translations etc */ -} - -static void M159CW(uint16 A, uint16 V) { - setchr1(A, V); -} - -void Mapper159_Init(CartInfo *info) { - BANDAI_Init(info, EEPROM_X24C01, FALSE); - BANDAI_pwrap = M159PW; - BANDAI_cwrap = M159CW; -} diff --git a/src/mappers/mapper160.c b/src/mappers/mapper160.c deleted file mode 100644 index cbcb3f993..000000000 --- a/src/mappers/mapper160.c +++ /dev/null @@ -1,59 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -/* -iNES Mapper 160 appeared to describe variant behavior of iNES Mapper 090, but -Mapper 90 fully encompasses the behavior Mapper 160 was intended to emulate. -*/ - -#if 0 -static uint8 reg = 0; - -static void Sync(void) { - setprg32(0x8000, 0); - setchr8(reg & 1); -} - -static DECLFW(SAWrite) { - if (A & 0x100) { - reg = V; - Sync(); - } -} - -static void M160Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, SAWrite); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper160_Init(CartInfo *info) { - GameStateRestore = StateRestore; - info->Power = M160Power; - AddExState(®, 1, 0, "LATC"); -} -#endif \ No newline at end of file diff --git a/src/mappers/mapper162.c b/src/mappers/mapper162.c deleted file mode 100644 index dab0b3bd1..000000000 --- a/src/mappers/mapper162.c +++ /dev/null @@ -1,108 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2019 Libretro Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Waixing FS304 PCB */ - -#include "mapinc.h" - -static uint8 reg[4]; - -static SFORMAT StateRegs[] = -{ - { reg, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, - (reg[2] << 4) | (reg[0] & 0x0C) /* PRG A17-A20 always normal from $5000 and $5200 */ - | ((reg[3] & 0x04) ? 0x00 : 0x02) /* PRG A16 is 1 if $5300.2=0 */ - | ((reg[3] & 0x04) ? (reg[0] & 0x02) : 0x00) /* PRG A16 is $5000.1 if %5300.2=1 */ - | ((reg[3] & 0x01) ? 0x00 : reg[1] >> 1 & 0x01) /* PRG A15 is $5100.1 if $5300.0=0 */ - | ((~reg[3] & 0x04) && (reg[3] & 0x01) ? 0x01 : 0x00) /* PRG A15 is 1 if $5300.2=0 and $5300.0=1 */ - | ((reg[3] & 0x04) && (reg[3] & 0x01) ? (reg[0] & 0x01) : 0x00) /* PRG A15 is $5000.0 if $5300.2=1 and $5300.0=1 */ - ); - setprg8r(0x10, 0x6000, 0); - if (~reg[0] & 0x80) - setchr8(0); -} - -static void M162HBIRQHook(void) { - if ((reg[0] & 0x80) && - scanline < 239) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on - PA13 rises. This does not seem possible with the current PPU emulation however. */ - setchr4(0x0000, (scanline >= 127) ? 1 : 0); - setchr4(0x1000, (scanline >= 127) ? 1 : 0); - } else - setchr8(0); -} - -static DECLFR(readReg) { - return 0x00; -} - -static DECLFW(writeReg) { - reg[(A >> 8) & 3] = V; - Sync(); -} - -static void M162Power(void) { - memset(reg, 0, sizeof(reg)); - Sync(); - SetReadHandler(0x5000, 0x57FF, readReg); - SetWriteHandler(0x5000, 0x57FF, writeReg); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); -} - -static void M162Reset(void) { - memset(reg, 0, sizeof(reg)); - Sync(); -} - -static void M162Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper162_Init(CartInfo *info) { - info->Power = M162Power; - info->Reset = M162Reset; - info->Close = M162Close; - GameHBIRQHook = M162HBIRQHook; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) : 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } -} diff --git a/src/mappers/mapper163.c b/src/mappers/mapper163.c deleted file mode 100644 index 1e12f3913..000000000 --- a/src/mappers/mapper163.c +++ /dev/null @@ -1,114 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2019 Libretro Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Nanjing FC-001 PCB */ - -#include "mapinc.h" - -static uint8 reg[4]; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, (reg[2] << 4) | (reg[0] & 0x0F) | ((reg[3] & 0x04) ? 0x00 : 0x03)); - setprg8r(0x10, 0x6000, 0); - if (~reg[0] & 0x80) - setchr8(0); -} - -static void M163HBIRQHook(void) { - if ((reg[0] & 0x80) && - (scanline < 239)) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on - PA13 rises. This does not seem possible with the current PPU emulation however. */ - setchr4(0x0000, (scanline >= 127) ? 1 : 0); - setchr4(0x1000, (scanline >= 127) ? 1 : 0); - } else { - setchr8(0); - } -} - -static DECLFR(readReg) { - return ~reg[1] & 0x04; -} - -static DECLFW(writeReg) { - uint8 index = (A >> 8) & 0x03; - - /* Swap bits of registers 0-2 again if the "swap bits" bit is set. Exclude register 2 on when PRG-ROM is 1 MiB. */ - if ((reg[3] & 0x01) && (index <= (PRG_ROM_SIZE < (2024 * 1024)))) { - V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); - } - - if (A & 0x01) { - if ((reg[1] & 0x01) && (~V & 0x01)) { - reg[1] ^= 0x04; /* If A0=1, flip feedback bit on falling edges of D0 */ - } /* If A0=0, write to register */ - } else { - reg[index] = V; - Sync(); - } -} - -static void M163Power(void) { - memset(reg, 0, sizeof(reg)); - Sync(); - SetReadHandler(0x5000, 0x57FF, readReg); - SetWriteHandler(0x5000, 0x57FF, writeReg); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); -} - -static void M163Reset(void) { - memset(reg, 0, sizeof(reg)); - Sync(); -} - -static void M163Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper163_Init(CartInfo *info) { - info->Power = M163Power; - info->Reset = M163Reset; - info->Close = M163Close; - GameHBIRQHook = M163HBIRQHook; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = info->iNES2 ? (info->PRGRamSize + info->PRGRamSaveSize) : 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } -} diff --git a/src/mappers/mapper164.c b/src/mappers/mapper164.c deleted file mode 100644 index 7366c2c68..000000000 --- a/src/mappers/mapper164.c +++ /dev/null @@ -1,146 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Dongda PEC-9588 educational computer. Provides the same 1bpp all-points-addressable graphics mode. - Its chipset was later used for the Yancheng cy2000-3 PCB, used on most of the games that display "Union Bond" at the start. - Some of them also use the 1bpp mode for a few screens! -*/ - -#include "mapinc.h" -#include "eeprom_93Cx6.h" - -static uint8 reg[4]; -static uint8 eeprom_data[512]; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { eeprom_data, 512, "EEPR" }, - { 0 } -}; - -static void Sync(void) { - uint8 prgLow = (reg[0] & 0x0F) | ((reg[0] >> 1) & 0x10); - uint8 prgHigh = reg[1] << 5; - - uint8 mode = ((reg[0] >> 5) & 0x02) | ((reg[0] >> 4) & 0x01); - uint8 mirr = ((reg[0] & 0x10) && !(reg[3] & 0x80)) ? MI_H : MI_V; - - switch (mode) { - case 0: /* UNROM-512 */ - setprg16(0x8000, prgHigh | prgLow); - setprg16(0xC000, prgHigh | 0x1F); - break; - case 1: /* Open Bus on Yancheng cy2000-3 PCB, expansion cartridge on the Dongda PEC-9588 */ - break; - case 2: /* UNROM-448+64. Very strange mode, used for the LOGO program on the Dongda PEC-9588 */ - setprg16(0x8000, prgHigh | prgLow); - setprg16(0xC000, prgHigh | ((prgLow >= 0x1C) ? 0x1C : 0x1E)); - break; - case 3: /* UNROM-128 or BNROM */ - if (prgLow & 0x10) { - setprg16(0x8000, prgHigh | ((prgLow << 1) & 0x10) | (prgLow & 0x0F)); - setprg16(0xC000, prgHigh | ((prgLow << 1) & 0x10) | 0x0F); - } else { - setprg32(0x8000, (prgHigh >> 1) | prgLow); - } - break; - } - - setprg8r(0x10, 0x6000, 0); - - setchr8(0); - PEC586Hack = (reg[0] & 0x80) ? TRUE : FALSE; - - setmirror(mirr); -} - -static DECLFR(readReg) { - return eeprom_93Cx6_read() ? 0x00 : 0x04; -} - -static DECLFW(writeReg) { - switch (A & 0xFF00) { - case 0x5000: - reg[0] = V; - Sync(); - break; - case 0x5100: - reg[1] = V; - Sync(); - break; - case 0x5200: - reg[2] = V; - eeprom_93Cx6_write((reg[2] & 0x10), (reg[2] & 0x04), (reg[2] & 0x01)); - break; - case 0x5300: - reg[3] = V; - Sync(); - break; - } -} - -static void M164Power(void) { - memset(reg, 0, sizeof(reg)); - Sync(); - SetReadHandler(0x5400, 0x57FF, readReg); - SetWriteHandler(0x5000, 0x57FF, writeReg); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M164Reset(void) { - memset(reg, 0, sizeof(reg)); - Sync(); -} - -static void M164Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper164_Init(CartInfo *info) { - info->Power = M164Power; - info->Reset = M164Reset; - info->Close = M164Close; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - if (info->iNES2) { - WRAMSIZE = info->iNES2 ? (info->PRGRamSize + (info->PRGRamSaveSize & ~0x7FF)) : 8192; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - - eeprom_93Cx6_init(eeprom_data, 512, 8); - info->battery = 1; - info->SaveGame[0] = eeprom_data; - info->SaveGameLen[0] = 512; -} diff --git a/src/mappers/mapper165.c b/src/mappers/mapper165.c deleted file mode 100644 index 5962a380b..000000000 --- a/src/mappers/mapper165.c +++ /dev/null @@ -1,87 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M165CW(uint16 A, uint16 V) { - if (V == 0) { - setchr4r(0x10, A, 0); - } else { - setchr4(A, V >> 2); - } -} - -static void M165PPUFD(void) { - if (reg == 0xFD) { - M165CW(0x0000, mmc3.reg[0]); - M165CW(0x1000, mmc3.reg[2]); - } -} - -static void M165PPUFE(void) { - if (reg == 0xFE) { - M165CW(0x0000, mmc3.reg[1]); - M165CW(0x1000, mmc3.reg[4]); - } -} - -static void M165CWM(uint16 A, uint16 V) { - if (((mmc3.cmd & 0x7) == 0) || ((mmc3.cmd & 0x7) == 2)) { - M165PPUFD(); - } - if (((mmc3.cmd & 0x7) == 1) || ((mmc3.cmd & 0x7) == 4)) { - M165PPUFE(); - } -} - -static void M165PPU(uint32 A) { - if ((A & 0x1FF0) == 0x1FD0) { - reg = 0xFD; - M165PPUFD(); - } else if ((A & 0x1FF0) == 0x1FE0) { - reg = 0xFE; - M165PPUFE(); - } -} - -static void M165Close(void) { - MMC3_Close(); -} - -static void M165Power(void) { - reg = 0xFD; - MMC3_Power(); -} - -void Mapper165_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - info->Close = M165Close; - MMC3_cwrap = M165CWM; - PPU_hook = M165PPU; - info->Power = M165Power; - CHRRAMSIZE = 4096; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); - AddExState(®, 1, 0, "EXPR"); -} \ No newline at end of file diff --git a/src/mappers/mapper166.c b/src/mappers/mapper166.c deleted file mode 100644 index 3ce2b56db..000000000 --- a/src/mappers/mapper166.c +++ /dev/null @@ -1,88 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[4]; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint16 base = ((reg[0] ^ reg[1]) & 0x10) << 1; - uint16 bank = (reg[2] ^ reg[3]) & 0x1f; - - if (reg[1] & 0x08) { - bank &= 0xFE; - setprg16(0x8000, base + bank + 0); - setprg16(0xC000, base + bank + 1); - } else { - if (reg[1] & 0x04) { - setprg16(0x8000, 0x1F); - setprg16(0xC000, base + bank); - } else { - setprg16(0x8000, base + bank); - setprg16(0xC000, 0x07); - } - } - setchr8(0); -} - -static DECLFW(M166Write) { - reg[(A >> 13) & 0x03] = V; - Sync(); -} - -static void M166Power(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, M166Write); - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper166_Init(CartInfo *info) { - info->Power = M166Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8 * 1024; - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } -} diff --git a/src/mappers/mapper167.c b/src/mappers/mapper167.c deleted file mode 100644 index 1cfd7674d..000000000 --- a/src/mappers/mapper167.c +++ /dev/null @@ -1,88 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[4]; - -static SFORMAT StateRegs[] = { - { reg, 4, "DREG" }, - { 0 } -}; - -static void Sync(void) { - uint16 base = ((reg[0] ^ reg[1]) & 0x10) << 1; - uint16 bank = (reg[2] ^ reg[3]) & 0x1f; - - if (reg[1] & 0x08) { - bank &= 0xFE; - setprg16(0x8000, base + bank + 1); - setprg16(0xC000, base + bank + 0); - } else { - if (reg[1] & 0x04) { - setprg16(0x8000, 0x1F); - setprg16(0xC000, base + bank); - } else { - setprg16(0x8000, base + bank); - setprg16(0xC000, 0x20); - } - } - setchr8(0); -} - -static DECLFW(M167Write) { - reg[(A >> 13) & 0x03] = V; - Sync(); -} - -static void M167Power(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, M167Write); - if (WRAMSIZE) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper167_Init(CartInfo *info) { - info->Power = M167Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8 * 1024; - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } -} diff --git a/src/mappers/mapper168.c b/src/mappers/mapper168.c deleted file mode 100644 index aaa98c36a..000000000 --- a/src/mappers/mapper168.c +++ /dev/null @@ -1,75 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * RacerMate Challenge II - * - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = -{ - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setchr4r(0x10, 0x0000, 0); - setchr4r(0x10, 0x1000, reg & 0x0f); - setprg16(0x8000, reg >> 6); - setprg16(0xc000, ~0); -} - -static DECLFW(M168Write) { - reg = V; - Sync(); -} - -static DECLFW(M168Dummy) { } - -static void M168Power(void) { - reg = 0; - Sync(); - SetWriteHandler(0x4020, 0x7fff, M168Dummy); - SetWriteHandler(0xB000, 0xB000, M168Write); - SetWriteHandler(0xF000, 0xF000, M168Dummy); - SetWriteHandler(0xF080, 0xF080, M168Dummy); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void M168Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper168_Init(CartInfo *info) { - info->Power = M168Power; - info->Close = M168Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAMSIZE = 8192 * 8; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); -} diff --git a/src/mappers/mapper170.c b/src/mappers/mapper170.c deleted file mode 100644 index 7830e0a47..000000000 --- a/src/mappers/mapper170.c +++ /dev/null @@ -1,52 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static DECLFW(M170ProtW) { - reg = ((V << 1) & 0x80); -} - -static DECLFR(M170ProtR) { - return (reg | (CPU_OPENBUS & 0x7F)); -} - -static void M170Power(void) { - setprg32(0x8000, 0); - setchr8(0); - SetReadHandler(0x7001, 0x7001, M170ProtR); - SetReadHandler(0x7777, 0x7777, M170ProtR); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6502, 0x6502, M170ProtW); - SetWriteHandler(0x7000, 0x7000, M170ProtW); -} - -void Mapper170_Init(CartInfo *info) { - info->Power = M170Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper171.c b/src/mappers/mapper171.c deleted file mode 100644 index cef5c3698..000000000 --- a/src/mappers/mapper171.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 171 - Kaiser KS-7058 */ - -#include "mapinc.h" - -static uint8 chr[2]; - -static SFORMAT StateRegs[] = { - { chr, 2, "CREG" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, 0); - setchr4(0x0000, chr[0]); - setchr4(0x1000, chr[1]); -} - -static DECLFW(M171Write) { - chr[A & 0x01] = V; - Sync(); -} - -static void M171Power(void) { - chr[0] = chr[1] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M171Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper171_Init(CartInfo *info) { - info->Power = M171Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper172.c b/src/mappers/mapper172.c deleted file mode 100644 index 2bdb29e6c..000000000 --- a/src/mappers/mapper172.c +++ /dev/null @@ -1,54 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "jv001.h" - -static void M172Sync(void) { - setprg32(0x8000, 0); - setchr8(jv001.output); - setmirror((jv001.X & 1) ^ 1); -} - -static uint8 GetVal(uint8 V) { - return (((V << 5) & 0x20) | ((V << 3) & 0x10) | ((V << 1) & 0x08) | ((V >> 1) & 0x04) | - ((V >> 3) & 0x02) | ((V >> 5) & 0x01)); -} - -static DECLFW(M172Write) { - JV001_Write(A, GetVal(V)); -} - -static DECLFR(M172Read) { - return (CPU_OPENBUS & 0xC0) | GetVal(JV001_Read(A)); -} - -static void M172Power(void) { - JV001_Power(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x5FFF, M172Read); - SetWriteHandler(0x4100, 0xFFFF, M172Write); -} - -void Mapper172_Init(CartInfo *info) { - JV001_Init(info, M172Sync); - info->Power = M172Power; -} diff --git a/src/mappers/mapper173.c b/src/mappers/mapper173.c deleted file mode 100644 index 0aa493900..000000000 --- a/src/mappers/mapper173.c +++ /dev/null @@ -1,52 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "txc.h" - -static void M173Sync(void) { - setprg32(0x8000, 0); - if (CHR_ROM_SIZE >= (16 * 1024)) { - setchr8(((txc.output & 0x01) | (txc.Y ? 0x02 : 0x00) | ((txc.output & 2) << 0x01))); - } else { - setchr8(0); - } -} - -static DECLFW(M173Write) { - TXC_Write(A, V & 0x0F); -} - -static DECLFR(M173Read) { - return ((CPU_OPENBUS & 0xF0) | (TXC_Read(A) & 0x0F)); -} - -static void M173Power(void) { - TXC_Power(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4100, 0x5FFF, M173Read); - SetWriteHandler(0x4100, 0xFFFF, M173Write); -} - -void Mapper173_Init(CartInfo *info) { - TXC_Init(info, M173Sync); - info->Power = M173Power; -} diff --git a/src/mappers/mapper174.c b/src/mappers/mapper174.c deleted file mode 100644 index 114262eff..000000000 --- a/src/mappers/mapper174.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x80) { - setprg32(0x8000, (latch.addr >> 5) & 0x03); - } else { - setprg16(0x8000, (latch.addr >> 4) & 0x07); - setprg16(0xC000, (latch.addr >> 4) & 0x07); - } - setchr8((latch.addr >> 1) & 0x07); - setmirror((latch.addr & 0x01) ^ 0x01); -} - -void Mapper174_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper175.c b/src/mappers/mapper175.c deleted file mode 100644 index a0f896e7f..000000000 --- a/src/mappers/mapper175.c +++ /dev/null @@ -1,78 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[2], mirr; - -static SFORMAT StateRegs[] = { - { reg, 2, "REG" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, reg[0]); - setprg16(0xC000, reg[0]); - setchr8(reg[0]); - setmirror(((mirr >> 2) & 0x01) ^ 0x01); -} - -static DECLFR(M175Read) { - switch (A & 0xF000) { - case 0xF000: - if (reg[0] != reg[1]) { - reg[0] = reg[1]; - Sync(); - } - break; - } - return CartBR(A); -} - -static DECLFW(M175Write) { - switch (A & 0xF000) { - case 0x8000: - mirr = V; - Sync(); - break; - case 0xA000: - reg[1] = V; - break; - } -} - -static void M175Power(void) { - reg[0] = reg[1] = mirr = 0; - SetReadHandler(0x8000, 0xFFFF, M175Read); - SetWriteHandler(0x8000, 0xFFFF, M175Write); - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper175_Init(CartInfo *info) { - info->Power = M175Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper176.c b/src/mappers/mapper176.c deleted file mode 100644 index 883051a81..000000000 --- a/src/mappers/mapper176.c +++ /dev/null @@ -1,599 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2020 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mappers: - 176 - Standard - 523 - Jncota KT-xxx, re-release of 封神榜꞉ 伏魔三太子: 1 KiB->2 KiB, 2 KiB->4 KiB CHR, hard-wired nametable mirroring) - - Submappers: - 0 - Standard - 1 - FK-xxx - 2 - 外星 FS005/FS006 - 3 - JX9003B - 4 - GameStar Smart Genius Deluxe - 5 - HST-162 - - Verified on real hardware: - "Legend of Kage" sets CNROM latch 1 and switches between CHR bank 0 and 1 using 5FF2, causing the wrong bank (1 instead of 0) during gameplay. - - Heuristic for detecting whether the DIP switch should be changed on every soft reset: - The first write to the $5xxx range is to $501x => ROM always addresses $501x; changing the DIP switch on reset would break the emulation after reset, so don't do it. - The first write to the $5xxx range is to $5020 or higher => ROM either uses a DIP switch or writes to $5FFx for safety; changing the DIP switch on reset is possible. - Exclude the $5FF3 address as well as $5000-$500F from this heuristic. -*/ - -#include "mapinc.h" - -static uint8 fk23_regs[8] = { 0 }; /* JX9003B has eight registers, all others have four */ -static uint8 mmc3_regs[12] = { 0 }; -static uint8 mmc3_ctrl = 0; -static uint8 mmc3_mirr = 0; -static uint8 mmc3_wram = 0; -static uint8 reg4800 = 0; - -static uint8 irq_count = 0; -static uint8 irq_latch = 0; -static uint8 irq_enabled = 0; -static uint8 irq_reload = 0; -static uint8 latch = 0; -static uint8 dipswitch = 0; -static uint8 subType = 0; /* NES 2.0 Submapper, denoting PCB variants */ -static uint8 dipsw_enable = 0; /* Change the address mask on every reset? */ -static uint8 after_power = 0; /* Used for detecting whether a DIP switch is used or not (see above) */ - -static void (*FK23_cwrap)(uint16 A, uint16 V); -static void (*SyncMIRR)(void); - -static SFORMAT StateRegs[] = { - { fk23_regs, 8, "EXPR" }, - { mmc3_regs, 12, "M3RG" }, - { &latch, 1, "LATC" }, - { &dipswitch, 1, "DPSW" }, - { &mmc3_ctrl, 1, "M3CT" }, - { &mmc3_mirr, 1, "M3MR" }, - { &mmc3_wram, 1, "M3WR" }, - { ®4800, 1, "REG4" }, - { &irq_reload, 1, "IRQR" }, - { &irq_count, 1, "IRQC" }, - { &irq_latch, 1, "IRQL" }, - { &irq_enabled, 1, "IRQA" }, - { &subType, 1, "SUBT" }, - { 0 } -}; - -#define INVERT_PRG !!(mmc3_ctrl & 0x40) -#define INVERT_CHR !!(mmc3_ctrl & 0x80) -#define WRAM_ENABLED !!(mmc3_wram & 0x80) -#define WRAM_EXTENDED (!!(mmc3_wram & 0x20) && subType == 2) /* Extended A001 register. Only available on FS005 PCB. */ -#define FK23_ENABLED (!!(mmc3_wram & 0x40) || !WRAM_EXTENDED) /* Enable or disable registers in the $5xxx range. Only available on FS005 PCB. */ -#define PRG_MODE ( fk23_regs[0] & 0x07) -#define MMC3_EXTENDED !!( fk23_regs[3] & 0x02) /* Extended MMC3 mode, adding extra registers for switching the normally-fixed PRG banks C and E and for eight independent 1 KiB CHR banks. Only available on FK- and FS005 PCBs. */ -#define CHR_8K_MODE !!( fk23_regs[0] & 0x40) /* MMC3 CHR registers are ignored, apply outer bank only, and CNROM latch if it exists */ -#define CHR_CNROM_MODE (~fk23_regs[0] & 0x20 && (subType == 1 || subType == 5)) /* Only subtypes 1 and 5 have a CNROM latch, which can be disabled */ -#define CHR_OUTER_BANK_SIZE !!( fk23_regs[0] & 0x10) /* Switch between 256 and 128 KiB CHR, or 32 and 16 KiB CHR in CNROM mode */ -#define CHR_MIXED !!(WRAM_EXTENDED && mmc3_wram &0x04) /* First 8 KiB of CHR address space are RAM, then ROM */ - -static void CHRWRAP(uint16 A, uint16 V) { - uint8 bank = 0; - - /* some workaround for chr rom / ram access */ - if (!CHR_ROM_SIZE) { - /* CHR-RAM only */ - bank = 0; - } else if (CHRRAMSIZE) { - /* Mixed CHR-ROM + CHR-RAM */ - if ((fk23_regs[0] & 0x20) && ((subType == 0) || (subType == 1))) { - bank = 0x10; - } else if (CHR_MIXED && (V < 8)) { - /* first 8K of chr bank is RAM */ - bank = 0x10; - } - } - setchr1r(bank, A, V); -} - -static void SyncCHR(void) { - uint32 outer = fk23_regs[2] | - (subType == 3 ? (fk23_regs[6] << 8) : 0); /* Outer 8 KiB CHR bank. Subtype 3 has an MSB register providing more bits. */ - if (CHR_8K_MODE) { - uint32 mask = (CHR_CNROM_MODE ? (CHR_OUTER_BANK_SIZE ? 0x01 : 0x03) : 0x00); - /* In Submapper 1, address bits come either from outer bank or from latch. In Submapper 5, they are OR'd. Both - * verified on original hardware. */ - uint32 bank = ((subType == 5 ? outer : (outer & ~mask)) | (latch & mask)) << 3; - - FK23_cwrap(0x0000, bank + 0); - FK23_cwrap(0x0400, bank + 1); - FK23_cwrap(0x0800, bank + 2); - FK23_cwrap(0x0C00, bank + 3); - - FK23_cwrap(0x1000, bank + 4); - FK23_cwrap(0x1400, bank + 5); - FK23_cwrap(0x1800, bank + 6); - FK23_cwrap(0x1C00, bank + 7); - } else { - uint32 cbase = (INVERT_CHR ? 0x1000 : 0); - uint32 mask = (CHR_OUTER_BANK_SIZE ? 0x7F : 0xFF); - - outer = (outer << 3) & ~mask; /* From 8 KiB to 1 KiB banks. Address bits are never OR'd; they either come from - the outer bank or from the MMC3. */ - - if (MMC3_EXTENDED) { - FK23_cwrap(cbase ^ 0x0000, (mmc3_regs[0] & mask) | outer); - FK23_cwrap(cbase ^ 0x0400, (mmc3_regs[10] & mask) | outer); - FK23_cwrap(cbase ^ 0x0800, (mmc3_regs[1] & mask) | outer); - FK23_cwrap(cbase ^ 0x0c00, (mmc3_regs[11] & mask) | outer); - - FK23_cwrap(cbase ^ 0x1000, (mmc3_regs[2] & mask) | outer); - FK23_cwrap(cbase ^ 0x1400, (mmc3_regs[3] & mask) | outer); - FK23_cwrap(cbase ^ 0x1800, (mmc3_regs[4] & mask) | outer); - FK23_cwrap(cbase ^ 0x1c00, (mmc3_regs[5] & mask) | outer); - } else { - FK23_cwrap(cbase ^ 0x0000, ((mmc3_regs[0] & 0xFE) & mask) | outer); - FK23_cwrap(cbase ^ 0x0400, ((mmc3_regs[0] | 0x01) & mask) | outer); - FK23_cwrap(cbase ^ 0x0800, ((mmc3_regs[1] & 0xFE) & mask) | outer); - FK23_cwrap(cbase ^ 0x0C00, ((mmc3_regs[1] | 0x01) & mask) | outer); - - FK23_cwrap(cbase ^ 0x1000, (mmc3_regs[2] & mask) | outer); - FK23_cwrap(cbase ^ 0x1400, (mmc3_regs[3] & mask) | outer); - FK23_cwrap(cbase ^ 0x1800, (mmc3_regs[4] & mask) | outer); - FK23_cwrap(cbase ^ 0x1c00, (mmc3_regs[5] & mask) | outer); - } - } -} - -static void SyncPRG(void) { - const static int mask_lut[8] ={ 0x3F, 0x1F, 0x0F, 0x00, 0x00, 0x00, 0x7F, 0xFF}; - uint32 mask = mask_lut[PRG_MODE]; /* For PRG modes 0-2, the mode# decides how many bits of the inner 8 KiB bank are used. This - is greatly relevant to map the correct bank that contains the reset vectors. */ - uint32 prg_base = fk23_regs[1] & 0x7F; /* The bits for the first 2 MiB are the same between all the variants. */ - uint32 cbase = 0; - switch (subType) { - case 1: /* FK-xxx */ - if (PRG_MODE == 0 && MMC3_EXTENDED) { - mask = 0xFF; /* Mode 7 allows the MMC3 to address 2 MiB rather than the usual 512 KiB. */ - } - break; - case 2: /* FS005 */ - prg_base |= ((fk23_regs[0] << 4) & 0x080) | ((fk23_regs[0] << 1) & 0x100) | ((fk23_regs[2] << 3) & 0x600) | - ((fk23_regs[2] << 6) & 0x800); - break; - case 3: /* JX9003B */ - if (PRG_MODE == 0) { - mask = 0xFF; /* Mode 7 allows the MMC3 to address 2 MiB rather than the usual 512 KiB. */ - } - prg_base |= fk23_regs[5] << 7; - break; - case 4: /* GameStar Smart Genius Deluxe */ - prg_base |= (fk23_regs[2] & 0x80); - break; - case 5: /* HST-162 */ - prg_base = (prg_base & 0x1F) | (reg4800 << 5); - break; - } - - switch (PRG_MODE) { - default: - /* 0: MMC3 with 512 KiB addressable */ - /* 1: MMC3 with 256 KiB addressable */ - /* 2: MMC3 with 128 KiB addressable */ - /* 7: MMC3 with 2 MB addressable. Used byc at least on 2 games: - - 最终幻想 2 - 光明篇 (Final Fantasy 2 - Arc of Light) - - 梦幻仙境 - (Fantasy Wonderworld) */ - cbase = (INVERT_PRG ? 0x4000 : 0); - prg_base = (prg_base << 1) & ~mask; /* from 16 to 8 KiB. Address bits are never OR'd; they either come from - the outer bank or from the MMC3. */ - if (MMC3_EXTENDED) { - setprg8(0x8000 ^ cbase, (mmc3_regs[6] & mask) | prg_base); - setprg8(0xA000, (mmc3_regs[7] & mask) | prg_base); - setprg8(0xC000 ^ cbase, (mmc3_regs[8] & mask) | prg_base); - setprg8(0xE000, (mmc3_regs[9] & mask) | prg_base); - } else { - setprg8(0x8000 ^ cbase, (mmc3_regs[6] & mask) | prg_base); - setprg8(0xA000, (mmc3_regs[7] & mask) | prg_base); - setprg8(0xC000 ^ cbase, (0xFE & mask) | prg_base); - setprg8(0xE000, (0xFF & mask) | prg_base); - } - break; - case 3: /* NROM-128 */ - setprg16(0x8000, prg_base); - setprg16(0xC000, prg_base); - break; - case 4: /* NROM-256 */ - setprg32(0x8000, (prg_base >> 1)); - break; - case 5: /* UNROM */ - setprg16(0x8000, (latch & 0x07) | (prg_base & ~0x07)); - setprg16(0xC000, 0x07 | prg_base); - break; - } -} - -static void SyncWRAM(void) { - /* TODO: WRAM Protected mode when not in extended mode */ - if (WRAM_ENABLED || WRAM_EXTENDED) { - if (WRAM_EXTENDED) { - setprg8r(0x10, 0x4000, (mmc3_wram + 1) & 0x03); - setprg8r(0x10, 0x6000, (mmc3_wram + 0) & 0x03); - } else { - setprg8r(0x10, 0x6000, 0); - } - } -} - -static void FixMir(void) { - switch (mmc3_mirr & (subType == 2 ? 0x03 : 0x01)) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -static void Sync(void) { - SyncPRG(); - SyncCHR(); - SyncWRAM(); - SyncMIRR(); -} - -static DECLFW(Write4800) { /* Only used by submapper 5 (HST-162) */ - reg4800 = V; - SyncPRG(); -} - -static DECLFW(Write5000) { - if (after_power && A > 0x5010 && A != 0x5FF3) { /* Ignore writes from $5000-$500F, in particular to $5008, but not $5FF3 */ - after_power = 0; - dipsw_enable = A >= 0x5020; /* The DIP switch change on soft-reset is enabled if the first write after power-on - is not to $501x */ - } - if (FK23_ENABLED && (A & (0x10 << dipswitch))) { - fk23_regs[A & (subType == 3 ? 7 : 3)] = V; - SyncPRG(); - SyncCHR(); - } else { - /* FK23C Registers disabled, $5000-$5FFF maps to the second 4 KiB of the 8 KiB WRAM bank 2 */ - CartBW(A, V); - } -} - -static DECLFW(Write8000) { - uint8 old_ctrl = 0; - uint8 ctrl_mask = 0; - - latch = V; - if (CHR_8K_MODE) { - SyncCHR(); /* CNROM latch updated */ - } - if (PRG_MODE == 5) { - SyncPRG(); /* UNROM latch has been updated */ - } - - switch (A & 0xE001) { - case 0x8000: - if (A & 2) { - return; /* Confirmed on real hardware: writes to 8002 and 8003, or 9FFE and 9FFF, are ignored. Needed - for Dr. Mario on some of the "bouncing ball" multis. */ - } - old_ctrl = mmc3_ctrl; - /* Subtype 2, 8192 or more KiB PRG-ROM, no CHR-ROM: Like Subtype 0, - * but MMC3 registers $46 and $47 swapped. */ - if (subType == 2) { - if (V == 0x46) { - V = 0x47; - } else if (V == 0x47) { - V = 0x46; - } - } - mmc3_ctrl = V; - if (INVERT_PRG != (old_ctrl & 0x40)) { - SyncPRG(); - } - if (INVERT_CHR != (old_ctrl & 0x80)) { - SyncCHR(); - } - break; - case 0x8001: - if (A & 2) { - return; /* Confirmed on real hardware: writes to 8002 and 8003, or 9FFE and 9FFF, are ignored. Needed - for Dr. Mario on some of the "bouncing ball" multis. */ - } - ctrl_mask = MMC3_EXTENDED ? 0x0F : 0x07; - if ((mmc3_ctrl & ctrl_mask) < 12) { - mmc3_regs[mmc3_ctrl & ctrl_mask] = V; - - switch (mmc3_ctrl & ctrl_mask) { - case 6: - case 7: - case 8: - case 9: - SyncPRG(); - break; - default: - SyncCHR(); - break; - } - } - break; - case 0xA000: - mmc3_mirr = V; - SyncMIRR(); - break; - case 0xA001: - /* ignore bits when ram config register is disabled */ - if ((V & 0x20) == 0) { - V &= 0xC0; - } - mmc3_wram = V; - Sync(); - break; - case 0xC000: - irq_latch = V; - break; - case 0xC001: - irq_reload = 1; - break; - case 0xE000: - X6502_IRQEnd(FCEU_IQEXT); - irq_enabled = 0; - break; - case 0xE001: - irq_enabled = 1; - break; - default: - break; - } -} - -static void M176HBIRQHook(void) { - if (!irq_count || irq_reload) { - irq_count = irq_latch; - } else { - irq_count--; - } - if (!irq_count && irq_enabled) { - X6502_IRQBegin(FCEU_IQEXT); - } - irq_reload = 0; -} - -static void RegReset(void) { - fk23_regs[0] = fk23_regs[1] = fk23_regs[2] = fk23_regs[3] = 0; - fk23_regs[4] = fk23_regs[5] = fk23_regs[6] = fk23_regs[7] = 0; - mmc3_regs[0] = 0; - mmc3_regs[1] = 2; - mmc3_regs[2] = 4; - mmc3_regs[3] = 5; - mmc3_regs[4] = 6; - mmc3_regs[5] = 7; - mmc3_regs[6] = 0; - mmc3_regs[7] = 1; - mmc3_regs[8] = ~1; - mmc3_regs[9] = ~0; - mmc3_regs[10] = ~0; - mmc3_regs[11] = ~0; - mmc3_ctrl = mmc3_mirr = irq_count = irq_latch = irq_enabled = 0; - reg4800 = 0; - - if (subType == 2) { - mmc3_wram = 0xC0; - } else { - mmc3_wram = 0x80; - } - - if (subType == 1) { - fk23_regs[1] = ~0; - } - - Sync(); -} - -static void M176Reset(void) { - /* this little hack makes sure that we try all the dip switch settings eventually, if we reset enough */ - if (dipsw_enable) { - dipswitch = (dipswitch + 1) & 7; - FCEU_printf("BMCFK23C dipswitch set to $%04x\n", 0x5000 | 0x10 << dipswitch); - } - - RegReset(); -} - -static void M176Power(void) { - RegReset(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, Write5000); - SetWriteHandler(0x8000, 0xFFFF, Write8000); - - if (subType == 5) { - SetWriteHandler(0x4800, 0x4FFF, Write4800); - } - - if (WRAMSIZE) { - if (subType == 2) { - SetReadHandler(0x5000, 0x5FFF, CartBR); - } - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - } -} - -static void M176Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -static void Init(CartInfo *info) { - /* Setup default function wrappers */ - FK23_cwrap = CHRWRAP; - SyncMIRR = FixMir; - - /* Initialization for iNES and UNIF. subType and dipsw_enable must have been set. */ - info->Power = M176Power; - info->Reset = M176Reset; - info->Close = M176Close; - GameHBIRQHook = M176HBIRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - if (CHRRAMSIZE) { - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); - } - - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - if (info->battery) { - info->SaveGame[0] = WRAM; - if (info->iNES2 && info->PRGRamSaveSize) { - info->SaveGameLen[0] = info->PRGRamSaveSize; - } else { - info->SaveGameLen[0] = WRAMSIZE; - } - } - } -} - -void Mapper176_Init(CartInfo *info) { /* .NES file */ - dipsw_enable = 0; - if (info->iNES2) { - subType = info->submapper; - after_power = subType != 2; /* FS005 never has DIP switches, the others may have one, so use the heuristic. */ - if (CHR_ROM_SIZE) { - CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; - } - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } else { - /* Waixing boards have 32K battery backed wram */ - if (info->battery) { - subType = 2; - after_power = 0; - WRAMSIZE = 32 * 1024; - } else { - /* Always enable WRAM for iNES-headered files */ - WRAMSIZE = 8 * 1024; - - if ((PRG_ROM_SIZE == (1024 * 1024)) && (CHR_ROM_SIZE == (1024 * 1024))) { - subType = 1; - } else if ((PRG_ROM_SIZE == (256 * 1024)) && (CHR_ROM_SIZE == (128 * 1024))) { - subType = 1; - } else if ((PRG_ROM_SIZE == (128 * 1024)) && (CHR_ROM_SIZE == (64 * 1024))) { - subType = 1; - } else if ((PRG_ROM_SIZE >= (8192 * 1024)) && (CHR_ROM_SIZE == (0 * 1024))) { - subType = 2; - } else if ((PRG_ROM_SIZE == (4096 * 1024)) && (CHR_ROM_SIZE == (0 * 1024))) { - subType = 3; - } - - /* Detect heuristically whether the address mask should be changed on every soft reset */ - after_power = 1; - - if (CHRRAMSIZE && !CHR_ROM_SIZE) { - /* FIXME: CHR-RAM is already set in iNES mapper initializer when there is no CHR ROM present */ - /* so avoid reallocation it. */ - CHRRAMSIZE = 0; - } - } - } - Init(info); -} - -/* UNIF FK23C. Also includes mislabelled WAIXING-FS005, recognizable by their PRG-ROM size. */ -void BMCFK23C_Init(CartInfo *info) { - if (CHR_ROM_SIZE) { - /* Rockman I-VI uses mixed chr rom/ram */ - if (PRG_ROM_SIZE == (2048 * 1024) && CHR_ROM_SIZE == (512 * 1024)) { - CHRRAMSIZE = 8 * 1024; - } - } - WRAMSIZE = 8 * 1024; - - dipsw_enable = 0; - after_power = 1; - subType = (PRG_ROM_SIZE >= (4096 * 1024)) ? 2 : (PRG_ROM_SIZE == (64 * 1024) && CHR_ROM_SIZE == (128 * 1024)) ? 1 : 0; - if (subType == 2) { - CHRRAMSIZE = 256 * 1024; - } - - Init(info); -} - - /* UNIF FK23CA. Also includes mislabelled WAIXING-FS005, recognizable by their PRG-ROM size. */ -void BMCFK23CA_Init(CartInfo *info) { - WRAMSIZE = 8 * 1024; - - dipsw_enable = 0; - after_power = 1; - subType = (PRG_ROM_SIZE >= (2048 * 1024)) ? 2 : 1; - if (subType == 2) { - CHRRAMSIZE = 256 * 1024; - } - - Init(info); -} - -/* UNIF BMC-Super24in1SC03 */ -void Super24_Init(CartInfo *info) { - CHRRAMSIZE = 8 * 1024; - dipsw_enable = 0; - after_power = 0; - subType = 0; - Init(info); -} - -/* UNIF WAIXING-FS005 */ -void WAIXINGFS005_Init(CartInfo *info) { - CHRRAMSIZE = 8 * 1024; - WRAMSIZE = 32 * 1024; - dipsw_enable = 0; - after_power = 0; - subType = 2; - Init(info); -} - -static void M523CW(uint16 A, uint16 V) { - if (~A & 0x0400) { - setchr2(A, V); - } -} - -static void M523MIR(void) { - /* Jncota board has hard-wired mirroring */ -} - -/* Jncota board with unusual wiring that turns 1 KiB CHR banks into 2 KiB banks, and has hard-wired nametable mirroring. */ -void Mapper523_Init(CartInfo *info) { /* Jncota Fengshengban */ - WRAMSIZE = 8 * 1024; - dipsw_enable = 0; - after_power = 0; - subType = 1; - - Init(info); - SyncMIRR = M523MIR; - FK23_cwrap = M523CW; -} diff --git a/src/mappers/mapper177.c b/src/mappers/mapper177.c deleted file mode 100644 index 936f8ffcc..000000000 --- a/src/mappers/mapper177.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 177 - Oversized BNROM without bus conflict */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, latch.data & 0x1F); - setchr8(0); - setmirror(((latch.data & 0x20) >> 5) ^ 1); -} - -void Mapper177_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper178.c b/src/mappers/mapper178.c deleted file mode 100644 index ae2050e8d..000000000 --- a/src/mappers/mapper178.c +++ /dev/null @@ -1,107 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2013 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * DSOUNDV1/FL-TR8MA boards (32K WRAM, 8/16M), 178 mapper boards (8K WRAM, 4/8M) - * Various Education Cartridges - * - * mapper 551 - * Compared to INES Mapper 178, mirroring is hard-wired, and the chipset's internal CHR-RAM is not used in favor of CHR-ROM. - * - */ - -#include "mapinc.h" - -static uint8 reg[4]; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint16 base = (reg[1] & 0x07) | (reg[2] << 3); - - if ((reg[0] & 0x02)) { - setprg16(0x8000, base); - setprg16(0xC000, base | ((reg[0] & 0x04) ? 0x06 : 0x07)); - } else { - if (reg[0] & 0x04) { - setprg16(0x8000, base); - setprg16(0xC000, base); - } else { - setprg32(0x8000, base >> 1); - } - } - - if (iNESCart.mapper == 551) { - setprg8r(0x10, 0x6000, 0); - setchr8(reg[3]); - } else { - setchr8(0); - setprg8r(0x10, 0x6000, reg[3] & 3); - setmirror((reg[0] & 1) ^ 1); - } -} - -static DECLFW(M178Write) { - reg[A & 3] = V; -/* FCEU_printf("cmd %04x:%02x\n", A, V); */ - Sync(); -} - -static void M178Power(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - Sync(); - SetWriteHandler(0x4800, 0x4FFF, M178Write); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M178Reset(void) { - /* Always reset to menu */ - reg[0] = reg[1] = reg[2] = reg[3] = 0; - Sync(); -} - -static void M178Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper178_Init(CartInfo *info) { - info->Power = M178Power; - info->Reset = M178Reset; - info->Close = M178Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } -} diff --git a/src/mappers/mapper180.c b/src/mappers/mapper180.c deleted file mode 100644 index ea396672e..000000000 --- a/src/mappers/mapper180.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, 0); - setprg16(0xC000, latch.data); - setchr8(0); -} - -void Mapper180_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper183.c b/src/mappers/mapper183.c deleted file mode 100644 index 95eda4cab..000000000 --- a/src/mappers/mapper183.c +++ /dev/null @@ -1,87 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * iNES mapper 183 - * Gimmick Bootleg (VRC4 mapper) - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 prg[4]; - -static SFORMAT StateRegs[] = { - { prg, 4, "PRG" }, - { 0 } -}; - -static void M183PRG(void) { - setprg8(0x6000, prg[0] & 0x3F); - setprg8(0x8000, prg[1] & 0x3F); - setprg8(0xA000, prg[2] & 0x3F); - setprg8(0xC000, prg[3] & 0x3F); - setprg8(0xE000, (~0) & 0x3F); -} - -static DECLFW(M183Write) { - switch (A & 0xF800) { - case 0x6800: - prg[0] = A; - VRC24_FixPRG(); - break; - case 0x8800: - prg[1] = V; - VRC24_FixPRG(); - break; - case 0xA800: - prg[2] = V; - VRC24_FixPRG(); - break; - case 0xA000: - prg[3] = V; - VRC24_FixPRG(); - break; - case 0x9800: - VRC24_Write(0x9000, V); - break; - case 0x6000: - case 0x7000: - case 0x7800: - case 0x8000: - case 0x9000: - return; - default: - VRC24_Write(A, V); - return; - } -} - -static void M183Power(void) { - VRC24_Power(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0xFFFF, M183Write); -} - -void Mapper183_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x04, 0x08, 0, 1); - info->Power = M183Power; - VRC24_FixPRG = M183PRG; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper184.c b/src/mappers/mapper184.c deleted file mode 100644 index 654123182..000000000 --- a/src/mappers/mapper184.c +++ /dev/null @@ -1,56 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REG" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, 0); - setchr4(0x0000, reg & 0x0F); - setchr4(0x1000, (reg >> 4) & 0x0F); -} - -static DECLFW(M184Write) { - reg = V; - Sync(); -} - -static void M184Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, M184Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper184_Init(CartInfo *info) { - info->Power = M184Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper185.c b/src/mappers/mapper185.c deleted file mode 100644 index e26337c43..000000000 --- a/src/mappers/mapper185.c +++ /dev/null @@ -1,63 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 *DummyCHR = NULL; - -static void Sync(void) { - /* on off - 1 0x0F, 0xF0 - Bird Week - 2 0x33, 0x00 - B-Wings - 3 0x11, 0x00 - Mighty Bomb Jack - 4 0x22, 0x20 - Sansuu 1 Nen, Sansuu 2 Nen - 5 0xFF, 0x00 - Sansuu 3 Nen - 6 0x21, 0x13 - Spy vs Spy - 7 0x20, 0x21 - Seicross */ - uint8 chrEnable = ( - ((iNESCart.submapper != 4) && ((latch.data & 3) != 0) && (latch.data != 0x13)) || /* 1, 2, 3, 4, 5, 6 */ - ((iNESCart.submapper == 4) && ((latch.data & 1) == 0)) /* 7 */ - ) ? 0 : 0x10; - setprg32(0x8000, 0); - setchr8r(chrEnable, 0); -} - -static void M185Close(void) { - Latch_Close(); - if (DummyCHR) { - FCEU_gfree(DummyCHR); - } - DummyCHR = NULL; -} - -void Mapper185_Init(CartInfo *info) { - int x; - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Close = M185Close; - - DummyCHR = (uint8 *)FCEU_gmalloc(8192); - SetupCartCHRMapping(0x10, DummyCHR, 8192, 0); - for (x = 0; x < 8192; x++) { - DummyCHR[x] = 0xff; - } -} diff --git a/src/mappers/mapper186.c b/src/mappers/mapper186.c deleted file mode 100644 index 2c10a1d0b..000000000 --- a/src/mappers/mapper186.c +++ /dev/null @@ -1,95 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Family Study Box by Fukutake Shoten - */ - -#include "mapinc.h" - -static uint8 SWRAM[3072]; -static uint8 reg[4]; - -static SFORMAT StateRegs[] = { - { reg, 4, "DREG" }, - { SWRAM, 3072, "SWRM" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, reg[0] >> 6); - setprg16(0x8000, reg[1]); - setprg16(0xc000, 0); - setchr8(0); -} - -static DECLFW(M186Write) { - if (A & 0x4203) - reg[A & 3] = V; - Sync(); -} - -static DECLFR(M186Read) { - switch (A) { - case 0x4200: - return 0x00; - case 0x4201: - return 0x00; - case 0x4202: - return 0x40; - case 0x4203: - return 0x00; - } - return 0xFF; -} - -static DECLFR(ASWRAM) { - return (SWRAM[A - 0x4400]); -} -static DECLFW(BSWRAM) { - SWRAM[A - 0x4400] = V; -} - -static void M186Power(void) { - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0xFFFF, CartBW); - SetReadHandler(0x4200, 0x43FF, M186Read); - SetWriteHandler(0x4200, 0x43FF, M186Write); - SetReadHandler(0x4400, 0x4FFF, ASWRAM); - SetWriteHandler(0x4400, 0x4FFF, BSWRAM); - FCEU_CheatAddRAM(32, 0x6000, WRAM); - reg[0] = reg[1] = reg[2] = reg[3]; - Sync(); -} - -static void M186Close(void) { -} - -static void M186Restore(int version) { - Sync(); -} - -void Mapper186_Init(CartInfo *info) { - info->Power = M186Power; - info->Close = M186Close; - GameStateRestore = M186Restore; - WRAM = (uint8 *)FCEU_gmalloc(32768); - SetupCartPRGMapping(0x10, WRAM, 32768, 1); - AddExState(WRAM, 32768, 0, "WRAM"); - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper187.c b/src/mappers/mapper187.c deleted file mode 100644 index 248a48de0..000000000 --- a/src/mappers/mapper187.c +++ /dev/null @@ -1,78 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * A98402 board, A9711, A9746 similar - * King of Fighters 96, The (Unl), Street Fighter Zero 2 (Unl) - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M187CW(uint16 A, uint16 V) { - if ((A & 0x1000) == ((mmc3.cmd & 0x80) << 5)) { - setchr1(A, V | 0x100); - } else { - setchr1(A, V); - } -} - -static void M187PW(uint16 A, uint16 V) { - if (reg & 0x80) { - uint8 bank = (reg >> 1) & 0x0F; - - if (reg & 0x20) { - setprg32(0x8000, bank >> 1); - } else { - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } else { - setprg8(A, V & 0x3F); - } -} - -static DECLFW(M187Write) { - if (!(A & 0x01)) { - reg = V; - MMC3_FixPRG(); - } -} - -static DECLFR(M187Read) { - return CPU_OPENBUS | 0x80; -} - -static void M187Power(void) { - reg = 0; - MMC3_Power(); - SetReadHandler(0x5000, 0x5FFF, M187Read); - SetWriteHandler(0x5000, 0x5FFF, M187Write); -} - -void Mapper187_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M187PW; - MMC3_cwrap = M187CW; - info->Power = M187Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper188.c b/src/mappers/mapper188.c deleted file mode 100644 index 95d1fbc5f..000000000 --- a/src/mappers/mapper188.c +++ /dev/null @@ -1,47 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.data & 0x10) { - setprg16(0x8000, (latch.data & 0x07)); - } else { - setprg16(0x8000, (0x08 | latch.data)); - } - setprg16(0xC000, 0x07); - setchr8(0); -} - -static DECLFR(ExtDev) { - return(3); -} - -static void M118Power(void) { - Latch_Power(); - SetReadHandler(0x6000, 0x7FFF, ExtDev); -} - -void Mapper188_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M118Power; -} diff --git a/src/mappers/mapper189.c b/src/mappers/mapper189.c deleted file mode 100644 index 85b9fe4af..000000000 --- a/src/mappers/mapper189.c +++ /dev/null @@ -1,57 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M189PW(uint16 A, uint16 V) { - setprg32(0x8000, reg | (reg >> 4)); -} - -static DECLFW(M189Write4) { - if (A & 0x100) { - reg = V; - MMC3_FixPRG(); - } -} - -static DECLFW(M189Write6) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - } -} - -static void M189Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x4120, 0x5FFF, M189Write4); - SetWriteHandler(0x6000, 0x7FFF, M189Write6); -} - -void Mapper189_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M189PW; - info->Power = M189Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper190.c b/src/mappers/mapper190.c deleted file mode 100644 index d66e546ae..000000000 --- a/src/mappers/mapper190.c +++ /dev/null @@ -1,86 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2017 FCEUX Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Magic Kid GooGoo - */ - -#include "mapinc.h" - -static uint8 prg, chr[4]; - -static SFORMAT StateRegs[] = { - { &prg, 1, "PREG" }, - { chr, 4, "CREG" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, prg); - setprg16(0xC000, 0); - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr2(0x1000, chr[2]); - setchr2(0x1800, chr[3]); -} - -static DECLFW(M190Write) { - switch (A & 0xE000) { - case 0x8000: - case 0xC000: - prg = (A << 11) | (V & 0x07); - Sync(); - break; - case 0xA000: - chr[A & 0x03] = V; - Sync(); - break; - } -} - -static void M190Power(void) { - chr[0] = chr[1] = chr[2] = chr[3] = 0; - prg = 0; - setmirror(MI_V); - Sync(); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, M190Write); - FCEU_CheatAddRAM(0x2000 >> 10, 0x6000, WRAM); -} - -static void M190Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper190_Init(CartInfo *info) { - info->Power = M190Power; - info->Close = M190Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAM = (uint8 *)FCEU_gmalloc(0x2000); - SetupCartPRGMapping(0x10, WRAM, 0x2000, 1); - AddExState(WRAM, 0x2000, 0, "WRAM"); -} diff --git a/src/mappers/mapper191.c b/src/mappers/mapper191.c deleted file mode 100644 index 7492bb6ea..000000000 --- a/src/mappers/mapper191.c +++ /dev/null @@ -1,45 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M191CW(uint16 A, uint16 V) { - if (V & 0x80) { - setchr1r(0x10, A, V & 0x01); - } else { - setchr1(A, V); - } -} - -static void M191Close(void) { - MMC3_Close(); -} - -void Mapper191_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - info->Close = M191Close; - MMC3_cwrap = M191CW; - - CHRRAMSIZE = 2048; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} \ No newline at end of file diff --git a/src/mappers/mapper192.c b/src/mappers/mapper192.c deleted file mode 100644 index 97b476343..000000000 --- a/src/mappers/mapper192.c +++ /dev/null @@ -1,46 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M192CW(uint16 A, uint16 V) { - if ((V & ~0x03) == 0x08) { - setchr1r(0x10, A, V & 0x03); - } else { - setchr1(A, V); - } -} - -static void M192Close(void) { - MMC3_Close(); -} - -void Mapper192_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - info->Close = M192Close; - MMC3_cwrap = M192CW; - - CHRRAMSIZE = 4096; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} - diff --git a/src/mappers/mapper193.c b/src/mappers/mapper193.c deleted file mode 100644 index 2f279731d..000000000 --- a/src/mappers/mapper193.c +++ /dev/null @@ -1,68 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * MEGA-SOFT WAR IN THE GULF - * - */ - -#include "mapinc.h" - -static uint8 reg[8]; -static uint8 mirror; - -static SFORMAT StateRegs[] = { - { &mirror, 1, "MIRR" }, - { reg, 8, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, reg[3]); - setprg8(0xA000, ~2); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); - setchr4(0x0000, reg[0] >> 2); - setchr2(0x1000, reg[1] >> 1); - setchr2(0x1800, reg[2] >> 1); - setmirror((mirror & 0x01) ^ 0x01); -} - -static DECLFW(M193Write) { - reg[A & 7] = V; - Sync(); -} - -static void M193Power(void) { - memset(reg, 0, sizeof(reg)); - Sync(); - SetWriteHandler(0x6000, 0x7FFF, M193Write); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, CartBW); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper193_Init(CartInfo *info) { - info->Power = M193Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper194.c b/src/mappers/mapper194.c deleted file mode 100644 index f9ce0a4df..000000000 --- a/src/mappers/mapper194.c +++ /dev/null @@ -1,45 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M194CW(uint16 A, uint16 V) { - if ((V & ~0x01) == 0x00) { /* Dai-2-Ji - Super Robot Taisen (As).nes */ - setchr1r(0x10, A, V & 0x01); - } else { - setchr1(A, V); - } -} - -static void M194Close(void) { - MMC3_Close(); -} - -void Mapper194_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - info->Close = M194Close; - MMC3_cwrap = M194CW; - - CHRRAMSIZE = 2048; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} \ No newline at end of file diff --git a/src/mappers/mapper195.c b/src/mappers/mapper195.c deleted file mode 100644 index 2b76644e4..000000000 --- a/src/mappers/mapper195.c +++ /dev/null @@ -1,103 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 chrRamMask; -static uint8 chrRamBankSelect; - -static writefunc writePPU; -extern uint32 RefreshAddr; - -static void M195CW(uint16 A, uint16 V) { - if ((V & chrRamMask) == chrRamBankSelect) { - setchr1r(0x10, A, V); - } else { - setchr1(A, V); - } -} - -static const uint8 chrRamLut[8] = { - 0x28, 0x00, 0x4C, 0x64, 0x46, 0x7C, 0x04, 0xFF, -}; - -static DECLFW(M195PPUWrite) { - if (RefreshAddr < 0x2000) { - uint8 reg, chrBank; - uint32 addr = RefreshAddr; - - if (mmc3.cmd & 0x80) { - addr ^= 0x1000; - } - if (addr & 0x1000) { - reg = (addr >> 10) - 2; - } else { - reg = addr >> 11; - } - - chrBank = mmc3.reg[reg]; - if (chrBank & 0x80) { - if (chrBank & 0x10) { - /* CHR-RAM disable */ - chrRamMask = 0x00; - chrRamBankSelect = 0xFF; - } else { - uint8 index = ((chrBank >> 4) & 0x04) | ((chrBank >> 2) & 0x02) | ((chrBank >> 1) & 0x01); - - chrRamMask = (chrBank & 0x40) ? 0xFE : 0xFC; - chrRamBankSelect = chrRamLut[index]; - } - MMC3_FixCHR(); - } - } - writePPU(A, V); -} - -static void M195Power(void) { - chrRamMask = 0xFC; - chrRamBankSelect = 0x00; - MMC3_Power(); - setprg4r(0x10, 0x5000, 2); - SetWriteHandler(0x5000, 0x5FFF, CartBW); - SetReadHandler(0x5000, 0x5FFF, CartBR); - - writePPU = GetWriteHandler(0x2007); - SetWriteHandler(0x2007, 0x2007, M195PPUWrite); -} - -static void M195Close(void) { - MMC3_Close(); -} - -void Mapper195_Init(CartInfo *info) { - MMC3_Init(info, 16, info->battery); - info->Power = M195Power; - info->Close = M195Close; - MMC3_cwrap = M195CW; - - CHRRAMSIZE = 4096; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); - - AddExState(&chrRamMask, 1, 0, "CHRM"); - AddExState(&chrRamBankSelect, 1, 0, "CHRB"); -} diff --git a/src/mappers/mapper196.c b/src/mappers/mapper196.c deleted file mode 100644 index bbd378b79..000000000 --- a/src/mappers/mapper196.c +++ /dev/null @@ -1,68 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -/* MMC3 board with optional command address line connection, allows to - * make three-four different wirings to IRQ address lines and separately to - * CMD address line, Mali Boss additionally check if wiring are correct for - * game - */ - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void M196PW(uint16 A, uint16 V) { - if (reg[0]) { - setprg32(0x8000, reg[1]); - } else { - setprg8(A, V); - } -} - -static DECLFW(M196Write) { - A = (A & 0xF000) | (!!(A & 0x0E) ^ (A & 0x01)); - MMC3_Write(A, V); -} - -static DECLFW(M196WriteNROM) { - reg[0] = 1; - reg[1] = V | (V >> 4); - MMC3_FixPRG(); -} - -static void M196Power(void) { - reg[0] = reg[1] = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M196WriteNROM); - SetWriteHandler(0x8000, 0xFFFF, M196Write); -} - -void Mapper196_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M196PW; - info->Power = M196Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper197.c b/src/mappers/mapper197.c deleted file mode 100644 index 5cab3fa19..000000000 --- a/src/mappers/mapper197.c +++ /dev/null @@ -1,121 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M197PW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x08) ? 0x0F : 0x1F; - - switch (iNESCart.submapper) { - case 3: - setprg8(A, (reg << 4) | (V & mask)); - break; - default: - setprg8(A, V & 0x3F); - break; - } -} - -static void M197CHR(void) { - switch (iNESCart.submapper) { - case 1: - setchr2(0x0000, mmc3.reg[1] & ~0x01); - setchr2(0x0800, mmc3.reg[1] | 0x01); - setchr2(0x1000, mmc3.reg[4]); - setchr2(0x1800, mmc3.reg[5]); - break; - case 2: - setchr2(0x0000, mmc3.reg[0] & ~0x01); - setchr2(0x0800, mmc3.reg[1] | 0x01); - setchr2(0x1000, mmc3.reg[2]); - setchr2(0x1800, mmc3.reg[5]); - break; - case 0: - case 3: - default: - setchr2(0x0000, mmc3.reg[0] & ~0x01); - setchr2(0x0800, mmc3.reg[0] | 0x01); - setchr2(0x1000, mmc3.reg[2]); - setchr2(0x1800, mmc3.reg[3]); - break; - } -} - -static DECLFW(M197WriteReg) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - } -} - -static DECLFW(M197Write) { - switch (A & 0xE001) { - case 0x8001: - switch (mmc3.cmd & 0x07) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - mmc3.reg[mmc3.cmd & 0x07] = V; - MMC3_FixCHR(); - break; - default: - MMC3_CMDWrite(A, V); - break; - } - break; - default: - MMC3_CMDWrite(A, V); - break; - } -} - -static void M197Reset(void) { - reg = 0; - MMC3_FixCHR(); - MMC3_FixPRG(); - MMC3_FixMIR(); -} - -static void M197Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M197WriteReg); - SetWriteHandler(0x8000, 0x9FFF, M197Write); -} - -void Mapper197_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - info->Power = M197Power; - info->Reset = M197Reset; - MMC3_FixCHR = M197CHR; - MMC3_pwrap = M197PW; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper198.c b/src/mappers/mapper198.c deleted file mode 100644 index 09a557a8a..000000000 --- a/src/mappers/mapper198.c +++ /dev/null @@ -1,42 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M198PW(uint16 A, uint16 V) { - if (V >= 0x40) { - V = (0x40 | (V & 0x0F)); - } - setprg8(A, V); -} - -static void M198Power(void) { - MMC3_Power(); - setprg4r(0x10, 0x5000, 2); - SetWriteHandler(0x5000, 0x5fff, CartBW); - SetReadHandler(0x5000, 0x5fff, CartBR); -} - -void Mapper198_Init(CartInfo *info) { - MMC3_Init(info, 16, info->battery); - MMC3_pwrap = M198PW; - info->Power = M198Power; -} diff --git a/src/mappers/mapper199.c b/src/mappers/mapper199.c deleted file mode 100644 index 456543b66..000000000 --- a/src/mappers/mapper199.c +++ /dev/null @@ -1,40 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M199CW(uint16 A, uint16 V) { - setchr8(0); -} - -static void M199Power(void) { - MMC3_Power(); - setprg4r(0x10, 0x5000, 2); - SetReadHandler(0x5000, 0x5FFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, CartBW); -} - -void Mapper199_Init(CartInfo *info) { - MMC3_Init(info, 16, info->battery); - MMC3_cwrap = M199CW; - info->Power = M199Power; - info->Reset = MMC3_Reset; -} diff --git a/src/mappers/mapper200.c b/src/mappers/mapper200.c deleted file mode 100644 index 8a015a472..000000000 --- a/src/mappers/mapper200.c +++ /dev/null @@ -1,38 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.addr & 0x07); - setprg16(0xC000, latch.addr & 0x07); - setchr8(latch.addr & 0x07); - if (iNESCart.submapper == 1) { - setmirror(((latch.addr >> 2) & 0x01) ^ 0x01); - } else { - setmirror(((latch.addr >> 3) & 0x01) ^ 0x01); - } -} - -void Mapper200_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper201.c b/src/mappers/mapper201.c deleted file mode 100644 index 7bc6c8b11..000000000 --- a/src/mappers/mapper201.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.addr); - setchr8(latch.addr); -} - -void Mapper201_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper202.c b/src/mappers/mapper202.c deleted file mode 100644 index 1fbf5d941..000000000 --- a/src/mappers/mapper202.c +++ /dev/null @@ -1,38 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if ((latch.addr & 0x09) == 0x09) { - setprg32(0x8000, latch.addr >> 2); - } else { - setprg16(0x8000, latch.addr >> 1); - setprg16(0xC000, latch.addr >> 1); - } - setchr8(latch.addr >> 1); - setmirror((latch.addr & 0x01) ^ 0x01); -} - -void Mapper202_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper203.c b/src/mappers/mapper203.c deleted file mode 100644 index 7a0aedac8..000000000 --- a/src/mappers/mapper203.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.data >> 2); - setprg16(0xC000, latch.data >> 2); - setchr8(latch.data & 0x03); -} - -void Mapper203_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper204.c b/src/mappers/mapper204.c deleted file mode 100644 index 74d95d53d..000000000 --- a/src/mappers/mapper204.c +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x20) { - setprg32(0x8000, latch.addr >> 1); - setchr8(latch.addr & 0x0E); - } else { - setprg16(0x8000, latch.addr); - setprg16(0xC000, latch.addr); - setchr8(latch.addr & 0x0F); - } - setmirror(((latch.addr >> 4) & 0x01) ^ 0x01); -} - -void Mapper204_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper205.c b/src/mappers/mapper205.c deleted file mode 100644 index 3e7b146c2..000000000 --- a/src/mappers/mapper205.c +++ /dev/null @@ -1,78 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* iNES Mapper 205 - * UNIF boardname BMC-JC-016-2 - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M205PW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x02) ? 0x0F : 0x1F; - - setprg8(A, (reg << 4) | (V & mask)); -} - -static void M205CW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x02) ? 0x7F : 0xFF; - - setchr1(A, (reg << 7) | (V & mask)); -} - -static DECLFW(M205Write) { - CartBW(A, V); - reg = V & 0x03; - if ((V & 0x01) && dipsw) { - reg |= 0x02; - } - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M205Reset(void) { - reg = 0; - dipsw = (dipsw + 1) & 0x01; /* solder pad */ - MMC3_Reset(); -} - -static void M205Power(void) { - reg = dipsw = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M205Write); -} - -void Mapper205_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = M205PW; - MMC3_cwrap = M205CW; - info->Power = M205Power; - info->Reset = M205Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper206.c b/src/mappers/mapper206.c deleted file mode 100644 index 57edd8194..000000000 --- a/src/mappers/mapper206.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "n118.h" - -static void M206PW(uint16 A, uint16 V) { - if (iNESCart.submapper == 1) { - /* 3407, 3417 and 3451 PCBs */ - setprg32(0x8000, 0); - } else { - setprg8(A, V & 0x0F); - } -} - -void Mapper206_Init(CartInfo *info) { - N118_Init(info, 0, 0); - N118_pwrap = M206PW; -} diff --git a/src/mappers/mapper208.c b/src/mappers/mapper208.c deleted file mode 100644 index 0038ace56..000000000 --- a/src/mappers/mapper208.c +++ /dev/null @@ -1,132 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - - /* 2022-2-14 - * - add support for iNESCart.submapper 1, Mortal Kombat (JJ-01) (Ch) [!] - * - add mirroring - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 protIndex; -static uint8 protReg[4]; - -static const uint8 lut[256] = { - 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01, - 0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08, - 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00, - 0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -static void M208PRG(void) { - setprg32(0x8000, (reg & 0x01) | ((reg >> 3) & 0x02)); -} - -static void M208MIR(void) { - setmirror(((reg >> 5) & 0x01) ^ 0x01); -} - -static void M208PRG_Sub1(void) { - setprg32(0x8000, mmc3.reg[6] >> 2); -} - -static void M208MIR_Sub1(void) { - setmirror((mmc3.mirr & 0x01) ^ 0x01); -} - -static DECLFW(M208Write) { - reg = V; - MMC3_FixPRG(); - MMC3_FixMIR(); -} - -static DECLFW(M208ProtWrite) { - if (A & 0x800) { - protReg[(A & 0x03)] = V ^ lut[protIndex]; - } else { - protIndex = V; - } -} - -static DECLFR(M208ProtRead) { - return (protReg[(A & 0x3)]); -} - -static DECLFW(M208WriteCMD) { - switch (A & 0xE001) { - case 0x8001: - switch (mmc3.cmd & 0x07) { - case 6: - case 7: - mmc3.reg[mmc3.cmd & 0x07] = V; - MMC3_FixPRG(); - break; - default: - MMC3_CMDWrite(A, V); - break; - } - break; - default: - MMC3_CMDWrite(A, V); - break; - } -} - -static void M208Power(void) { - reg = 0x11; - MMC3_Power(); - SetWriteHandler(0x4800, 0x4FFF, M208Write); - SetWriteHandler(0x6800, 0x6FFF, M208Write); - SetWriteHandler(0x5000, 0x5FFF, M208ProtWrite); - SetReadHandler(0x5800, 0x5FFF, M208ProtRead); - SetReadHandler(0x8000, 0xFFFF, CartBR); - - if (iNESCart.submapper == 1) { - SetWriteHandler(0x8000, 0x9FFF, M208WriteCMD); - MMC3_FixPRG = M208PRG_Sub1; - MMC3_FixMIR = M208MIR_Sub1; - MMC3_Reset(); - } -} - -void Mapper208_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_FixPRG = M208PRG; - MMC3_FixMIR = M208MIR; - info->Power = M208Power; - AddExState(®, 1, 0, "EXPR"); - AddExState(&protIndex, 1, 0, "PRID"); - AddExState(&protReg, 4, 0, "PRRG"); -} diff --git a/src/mappers/mapper209.c b/src/mappers/mapper209.c deleted file mode 100644 index f6faa3634..000000000 --- a/src/mappers/mapper209.c +++ /dev/null @@ -1,62 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -static uint32 GetPRGBank(uint32 V) { - return (((jyasic.mode[3] << 5) & ~0x3F) | (V & 0x3F)); -} - -static uint32 GetCHRBank(uint32 V) { - if (jyasic.mode[3] & 0x20) { - return (((jyasic.mode[3] << 6) & 0x600) | (V & 0x1FF)); - } else { - return (((jyasic.mode[3] << 6) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); - } -} - -void Mapper035_Init(CartInfo *info) { - /* Basically mapper 90/209/211 with WRAM */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} - -void Mapper090_Init(CartInfo *info) { - /* Single cart, extended mirroring and ROM nametables disabled */ - JYASIC_Init(info, FALSE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} - -void Mapper209_Init(CartInfo *info) { - /* Single cart, extended mirroring and ROM nametables enabled */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} - -void Mapper211_Init(CartInfo *info) { - /* Duplicate of mapper 209 */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} diff --git a/src/mappers/mapper210.c b/src/mappers/mapper210.c deleted file mode 100644 index b84579164..000000000 --- a/src/mappers/mapper210.c +++ /dev/null @@ -1,146 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 210 - simplified version of Mapper 19 - * Namco 175 - submapper 1 - optional wram, hard-wired mirroring - * Namco 340 - submapper 2 - selectable H/V/0 mirroring - */ - -#include "mapinc.h" - -static uint8 prg[4]; -static uint8 chr[8]; -static uint8 wram_enable; - -static SFORMAT StateRegs[] = { - { prg, 3, "PRG" }, - { chr, 8, "CHR" }, - { &wram_enable, 1, "WREN" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0] & 0x3F); - setprg8(0xA000, prg[1] & 0x3F); - setprg8(0xC000, prg[2] & 0x3F); - setprg8(0xE000, prg[3] & 0x3F); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - if (iNESCart.submapper != 1) { - switch((prg[0] >> 6) & 0x03) { - case 0: setmirror(MI_0); break; - case 1: setmirror(MI_V); break; - case 2: setmirror(MI_H); break; - case 3: setmirror(MI_0); break; - } - } -} - -static DECLFR(AWRAM) { - A = ((A - 0x6000) & (WRAMSIZE -1)); - return WRAM[A]; -} - -static DECLFW(BWRAM) { - if (wram_enable) { - A = ((A - 0x6000) & (WRAMSIZE -1)); - WRAM[A] = V; - } -} - -static DECLFW(M210Write) { - switch (A & 0xF800) { - case 0x8000: - case 0x8800: - case 0x9000: - case 0x9800: - case 0xA000: - case 0xA800: - case 0xB000: - case 0xB800: - chr[(A - 0x8000) >> 11] = V; - Sync(); - break; - case 0xC000: - wram_enable = V & 0x01; - break; - case 0xE000: - case 0xE800: - case 0xF000: - prg[(A - 0xE000) >> 11] = V; - Sync(); - break; - } -} - -static void M210Power(void) { - int i; - for (i = 0; i < 4; i++) prg[i] = 0xFC | i; - for (i = 0; i < 4; i++) chr[0 | i] = 0 | i; - for (i = 0; i < 4; i++) chr[4 | i] = 4 | i; - wram_enable = 0; - Sync(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xffff, M210Write); - - if (WRAM) { - SetReadHandler(0x6000, 0x7FFF, AWRAM); - SetWriteHandler(0x6000, 0x7FFF, BWRAM); - FCEU_CheatAddRAM(8, 0x6000, WRAM); - } - - if (WRAM && !iNESCart.battery) { - FCEU_MemoryRand(WRAM, sizeof(WRAM)); - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper210_Init(CartInfo *info) { - GameStateRestore = StateRestore; - info->Power = M210Power; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } - - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } -} diff --git a/src/mappers/mapper212.c b/src/mappers/mapper212.c deleted file mode 100644 index 5967eb4e5..000000000 --- a/src/mappers/mapper212.c +++ /dev/null @@ -1,48 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x4000) { - setprg32(0x8000, latch.addr >> 1); - } else { - setprg16(0x8000, latch.addr); - setprg16(0xC000, latch.addr); - } - setchr8(latch.addr); - setmirror(((latch.addr >> 3) & 0x01) ^ 0x01); -} - -static DECLFR(M212Read) { - return (CPU_OPENBUS & ~0x80) | ((A & 0x10) ? 0 : 0x80); -} - -static void M212Power(void) { - Latch_Power(); - SetReadHandler(0x6000, 0x7FFF, M212Read); -} - -void Mapper212_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M212Power; -} diff --git a/src/mappers/mapper214.c b/src/mappers/mapper214.c deleted file mode 100644 index 818c3d39c..000000000 --- a/src/mappers/mapper214.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.addr >> 2); - setprg16(0xC000, latch.addr >> 2); - setchr8(latch.addr >> 2); -} - -void Mapper214_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper215.c b/src/mappers/mapper215.c deleted file mode 100644 index 1328645b6..000000000 --- a/src/mappers/mapper215.c +++ /dev/null @@ -1,184 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Submapper 0, UNIF board name UNL-8237: - * Earthworm Jim 2 - * Mortal Kombat 3 (SuperGame, not Extra 60, not to be confused by similarly-named games from other developers) - * Mortal Kombat 3 Extra 60 (both existing ROM images are just extracts of the 2-in-1 multicart containing this game) - * Pocahontas Part 2 - * 2-in-1: Aladdin, EarthWorm Jim 2 (Super 808) - * 2-in-1: The Lion King, Bomber Boy (GD-103) - * 2-in-1: Super Golden Card: EarthWorm Jim 2, Boogerman (king002) - * 2-in-1: Mortal Kombat 3 Extra 60, The Super Shinobi (king005) - * 3-in-1: Boogerman, Adventure Island 3, Double Dragon 3 (Super 308) - * 5-in-1: Golden Card: Aladdin, EarthWorm Jim 2, Garo Densetsu Special, Silkworm, Contra Force (SPC005) - * 6-in-1: Golden Card: EarthWorm Jim 2, Mortal Kombat 3, Double Dragon 3, Contra 3, The Jungle Book, Turtles Tournament Fighters (SPC009) - * - * Submapper 1, UNIF board name UNL-8237A: - * 9-in-1 High Standard Card: The Lion King, EarthWorm Jim 2, Aladdin, Boogerman, Somari, Turtles Tournament Fighters, Mortal Kombat 3, Captain Tsubasa 2, Taito Basketball (king001) - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; - -static const uint8 regperm[8][8] = -{ - { 0, 1, 2, 3, 4, 5, 6, 7 }, - { 0, 2, 6, 1, 7, 3, 4, 5 }, - { 0, 5, 4, 1, 7, 2, 6, 3 }, /* unused */ - { 0, 6, 3, 7, 5, 2, 4, 1 }, - { 0, 2, 5, 3, 6, 1, 7, 4 }, - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* empty */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* empty */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* empty */ -}; - -static const uint16 adrperm[8][8] = { - { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, - { 0xA001, 0xA000, 0x8000, 0xC000, 0x8001, 0xC001, 0xE000, 0xE001 }, - { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, /* unused */ - { 0xC001, 0x8000, 0x8001, 0xA000, 0xA001, 0xE001, 0xE000, 0xC000 }, - { 0xA001, 0x8001, 0x8000, 0xC000, 0xA000, 0xC001, 0xE000, 0xE001 }, - { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, /* empty */ - { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, /* empty */ - { 0x8000, 0x8001, 0xA000, 0xA001, 0xC000, 0xC001, 0xE000, 0xE001 }, /* empty */ -}; - -static const uint8 protarray[8][8] = { - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 0 Super Hang-On */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00 }, /* 1 Monkey King */ - { 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00 }, /* 2 Super Hang-On/Monkey King */ - { 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x05, 0x00 }, /* 3 Super Hang-On/Monkey King */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 4 */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 5 */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 6 */ - { 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0F, 0x00 } /* 7 (default) Blood of Jurassic */ -}; - -static void M215CW(uint16 A, uint16 V) { - uint16 mask = (reg[0] & 0x40) ? 0x7F : 0xFF; - uint16 base; - - if (iNESCart.submapper == 1) { - base = (reg[1] << 7) & 0x700; - } else { - base = (reg[1] << 6) & 0x300; - } - - base = (base & ~mask) | (((reg[1] << 2) & 0x80) & ~mask); - setchr1(A, base | (V & mask)); -} - -static void M215PW(uint16 A, uint16 V) { - uint16 mask = (reg[0] & 0x40) ? 0x0F : 0x1F; - uint16 base; - - if (iNESCart.submapper == 1) { - base = ((reg[1] << 5) & 0x60) | ((reg[1] << 4) & 0x80); - } else { - base = (reg[1] << 5) & 0x60; - } - - if (reg[0] & 0x80) { /* NROM */ - uint16 bank = (((reg[1] & 0x10) & ~mask) >> 1) | ((base & ~mask) >> 1) | (reg[0] & (mask >> 1)); - - if (reg[0] & 0x20) { /* NROM-256 */ - setprg32(0x8000, bank >> 1); - } else { /* NROM-128 */ - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } else { - setprg8(A, ((reg[1] & 0x10) & ~mask) | (base & ~mask) | (V & mask)); - } -} - -static DECLFR(M215ProtRead) { - return (CPU_OPENBUS & ~0x0F) | (protarray[reg[2]][A & 0x07] & 0x0F); -} - -static DECLFW(M215Write) { - A = adrperm[reg[3]][((A >> 12) & 0x06) | (A & 0x01)]; - switch (A & 0xE001) { - case 0x8000: - MMC3_Write(A, (V & 0xC0) | regperm[reg[3]][V & 0x07]); - break; - default: - MMC3_Write(A, V); - break; - } -} - -static DECLFW(M215Write5) { - switch (A & 0x07) { - case 0: - reg[0] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - break; - case 1: - reg[1] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - break; - case 2: - reg[2] = V & 0x07; - break; - case 7: - reg[3] = V & 0x07; - break; - } -} - -static void M215Power(void) { - reg[0] = 0x00; - reg[1] = 0x0F; - reg[3] = 0x04; - reg[2] = 0x07; - MMC3_Power(); - SetReadHandler(0x5000, 0x5FFF, M215ProtRead); - SetWriteHandler(0x5000, 0x5FFF, M215Write5); - SetWriteHandler(0x8000, 0xFFFF, M215Write); -} - -static void M215Reset(void) { - reg[0] = 0x00; - reg[1] = 0x0F; - reg[3] = 0x04; - reg[2] = 0x07; - MMC3_Reset(); -} - -void Mapper215_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M215CW; - MMC3_pwrap = M215PW; - - info->Power = M215Power; - info->Reset = M215Reset; - - AddExState(reg, 4, 0, "EXPR"); - - if ((!info->iNES2) && (PRG_ROM_SIZE >= (2048 * 1024))) { /* UNL-8237A */ - info->submapper = 1; - } -} diff --git a/src/mappers/mapper216.c b/src/mappers/mapper216.c deleted file mode 100644 index 7e6be09e5..000000000 --- a/src/mappers/mapper216.c +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.addr & 0x01); - setchr8(latch.addr >> 1); -} - -void Mapper216_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper217.c b/src/mappers/mapper217.c deleted file mode 100644 index f63858520..000000000 --- a/src/mappers/mapper217.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.addr >> 2); - setchr8(latch.addr); -} - -void Mapper217_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper218.c b/src/mappers/mapper218.c deleted file mode 100644 index 00af07206..000000000 --- a/src/mappers/mapper218.c +++ /dev/null @@ -1,57 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mapinc.h" - -extern uint8 **VPageR; -static const uint8 mirrorings[] = { MI_V, MI_H, MI_0, MI_1 }; -static const uint8 mapping[4][8] = { - { 0, 1, 0, 1, 0, 1, 0, 1 }, /* MI_V */ - { 0, 0, 1, 1, 0, 0, 1, 1 }, /* MI_H */ - { 0, 0, 0, 0, 1, 1, 1, 1 }, /* MI_0 */ - { 0, 0, 0, 0, 0, 0, 0, 0 } /* MI_1 */ -}; - -static void M218Power(void) { - setchr8(0); - setprg32(0x8000, 0); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -void Mapper218_Init(CartInfo *info) { - int mirror2bits = (head.ROM_type & 1) | ((head.ROM_type & 8) >> 2); - - info->Power = M218Power; - - /* similar to mapper 30, this mapper interprets the two bits in headers mirroring in idiosyncratic ways */ - SetupCartMirroring(mirrorings[mirror2bits], 1, NULL); - - /* cryptic logic to effect the CHR RAM mappings by mapping 1k blocks to NTARAM according to how the pins are wired - this could be done by bit logic, but this is self-documenting */ - VPageR[0] = &NTARAM[mapping[mirror2bits][0]]; - VPageR[1] = &NTARAM[mapping[mirror2bits][1]]; - VPageR[2] = &NTARAM[mapping[mirror2bits][2]]; - VPageR[3] = &NTARAM[mapping[mirror2bits][3]]; - VPageR[4] = &NTARAM[mapping[mirror2bits][4]]; - VPageR[5] = &NTARAM[mapping[mirror2bits][5]]; - VPageR[6] = &NTARAM[mapping[mirror2bits][6]]; - VPageR[7] = &NTARAM[mapping[mirror2bits][7]]; - PPUCHRRAM = 0xFF; -} diff --git a/src/mappers/mapper219.c b/src/mappers/mapper219.c deleted file mode 100644 index a85761d64..000000000 --- a/src/mappers/mapper219.c +++ /dev/null @@ -1,113 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 extMode; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { &extMode, 1, "MODE" }, - { 0 } -}; - -static void M219PW(uint16 A, uint16 V) { - setprg8(A, (reg << 4) | (V & 0x0F)); -} - -static void M219CW(uint16 A, uint16 V) { - setchr1(A, (reg << 7) | (V & 0x7F)); -} - -static DECLFW(M219WriteOuter) { - switch (A & 0x01) { - case 0: - reg = (reg & ~0x01) | ((V >> 3) & 0x01); - break; - case 1: - reg = (reg & ~0x02) | ((V >> 4) & 0x02); - break; - } - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static DECLFW(M219WriteASIC) { - uint8 oldcmd = mmc3.cmd; - - if (!(A & 0x01)) { /* Register index */ - mmc3.cmd = V; - if ((oldcmd & 0x40) != ((V & 0x40))) { - MMC3_FixPRG(); - } - if ((oldcmd & 0x80) != ((V & 0x80))) { - MMC3_FixPRG(); - } - if (A & 0x02) { - extMode = (V & 0x20) != 0; - } - } else { - if (!extMode) { /* Scrambled mode inactive */ - MMC3_CMDWrite(A, V); - } else { /* Scrambled mode active */ - if ((mmc3.cmd >= 0x08) && (mmc3.cmd <= 0x1F)) { /* Scrambled CHR register */ - uint8 index = (mmc3.cmd - 8) >> 2; - if (mmc3.cmd & 0x01) { /* LSB nibble */ - mmc3.reg[index] &= ~0x0F; - mmc3.reg[index] |= ((V >> 1) & 0x0F); - } else { /* MSB nibble */ - mmc3.reg[index] &= ~0xF0; - mmc3.reg[index] |= ((V << 4) & 0xF0); - } - MMC3_FixCHR(); - } else if ((mmc3.cmd >= 0x25) && (mmc3.cmd <= 0x26)) { /* Scrambled PRG register */ - V = ((V << 1) & 0x08) | ((V >> 1) & 0x04) | ((V >> 3) & 0x02) | ((V >> 5) & 0x01); - mmc3.reg[6 | (mmc3.cmd & 0x01)] = V; - MMC3_FixPRG(); - } - } - } -} - -static void M219Power(void) { - extMode = FALSE; - reg = 3; - MMC3_Power(); - SetWriteHandler(0x5000, 0x5FFF, M219WriteOuter); - SetWriteHandler(0x8000, 0x9FFF, M219WriteASIC); -} - -static void M219Reset(void) { - extMode = FALSE; - reg = ~0; - MMC3_Reset(); -} - -void Mapper219_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M219PW; - MMC3_cwrap = M219CW; - info->Power = M219Power; - info->Reset = M219Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper221.c b/src/mappers/mapper221.c deleted file mode 100644 index c2f4da0fe..000000000 --- a/src/mappers/mapper221.c +++ /dev/null @@ -1,92 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR reg[0] PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Mapper 221 - UNL-N625092 - * 700in1 and 400in1 carts - * 1000-in-1 - */ - -#include "mapinc.h" - -static uint16 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { 0 } -}; - -static uint16 GetPRGBank(void) { - return (((reg[0] >> 3) & 0x40) | ((reg[0] >> 2) & 0x38) | (reg[1] & 0x07)); -} - -static void Sync(void) { - uint16 prg = GetPRGBank(); - - if (!(reg[0] & 0x02)) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { - if (reg[0] & 0x100) { - setprg16(0x8000, prg); - setprg16(0xC000, prg | 0x07); - } else { - setprg16(0x8000, prg & ~1); - setprg16(0xC000, prg | 1); - } - } - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !(reg[1] & 0x08)); - setchr8(0); - setmirror((reg[0] & 0x01) ^ 0x01); -} - -static DECLFR(M221Read) { - if (GetPRGBank() >= PRG_BANK_COUNT(16)) { - return CPU_OPENBUS; - } - return CartBR(A); -} - -static DECLFW(M221Write) { - reg[(A >> 14) & 0x01] = A; - Sync(); -} - -static void M221Reset(void) { - reg[0] = reg[1] = 0; - Sync(); -} - -static void M221Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, M221Read); - SetWriteHandler(0x8000, 0xFFFF, M221Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper221_Init(CartInfo *info) { - info->Power = M221Power; - info->Reset = M221Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper222.c b/src/mappers/mapper222.c deleted file mode 100644 index 6f484fd15..000000000 --- a/src/mappers/mapper222.c +++ /dev/null @@ -1,76 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * iNES Mapper 222 - (CTC-31?) - * (VRC2 mapper) - * - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 IRQCount; -static uint8 IRQa; - -static SFORMAT StateRegs[] = { - { &IRQCount, 1, "IRQC" }, - { &IRQa, 1, "IRQA" }, - { 0 } -}; - -static void M222IRQ(void) { - if (IRQa) { - IRQCount++; - if (IRQCount >= 238) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static DECLFW(M222WriteCHR) { - if (!(A & 0x01)) { - VRC24_Write(A, V); - VRC24_Write(A | 0x01, V >> 4); - } -} - -static DECLFW(M222WriteIRQ) { - /* TODO: Update this */ - IRQa = IRQCount = V; - if (scanline < 240) - IRQCount -= 8; - else - IRQCount += 4; - X6502_IRQEnd(FCEU_IQEXT); -} - -static void M222Power(void) { - VRC24_Power(); - SetWriteHandler(0xB000, 0xEFFF, M222WriteCHR); - SetWriteHandler(0xF000, 0xFFFF, M222WriteIRQ); -} - -void Mapper222_Init(CartInfo *info) { - VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); - info->Power = M222Power; - MapIRQHook = NULL; - GameHBIRQHook = M222IRQ; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper225.c b/src/mappers/mapper225.c deleted file mode 100644 index 5f03d8160..000000000 --- a/src/mappers/mapper225.c +++ /dev/null @@ -1,86 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * PCB-018 board, discrete multigame cart 110-in-1 - * - * Mapper 225 - * Mapper 255 - * - */ - -/* 2020-2-20 - merge mapper 255, re-implement extra RAM */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 extraRAM[4]; - -static SFORMAT StateRegs[] = { - { extraRAM, 4, "PROT" }, - { 0 } -}; - -static void Sync(void) { - uint8 base = (latch.addr >> 8) & 0x40; - uint8 prg = (latch.addr >> 6) & 0x3F; - uint8 chr = latch.addr & 0x3F; - uint8 mirr = ((latch.addr >> 13) & 1) ^ 1; - - if (latch.addr & 0x1000) { - setprg16(0x8000, base | prg); - setprg16(0xC000, base | prg); - } else { - setprg32(0x8000, (base | prg) >> 1); - } - setchr8(base | chr); - setmirror(mirr); -} - -static DECLFW(M225LoWrite) { - /* e.g. 115-in-1 [p1][!] CRC32 0xb39d30b4 */ - if (A & 0x800) { - extraRAM[A & 3] = V & 0x0F; - } -} - -static DECLFR(M225LoRead) { - if (A & 0x800) { - return extraRAM[A & 3]; - } - return CPU_OPENBUS; -} - -static void M225Power(void) { - Latch_Power(); - SetReadHandler(0x5000, 0x5fff, M225LoRead); - SetWriteHandler(0x5000, 0x5fff, M225LoWrite); -} - -void Mapper225_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M225Power; - AddExState(StateRegs, ~0, 0, NULL); -} - -void Mapper255_Init(CartInfo *info) { - Mapper225_Init(info); -} diff --git a/src/mappers/mapper226.c b/src/mappers/mapper226.c deleted file mode 100644 index c0e109505..000000000 --- a/src/mappers/mapper226.c +++ /dev/null @@ -1,85 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2009 qeed - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Updated 2019-07-12 - * Mapper 226 - Updated and combine UNIF Ghostbusters63in1 board (1.5 MB carts), different bank order - * - some 1MB carts can switch game lists using Select - */ - -#include "mapinc.h" - -static uint8 reg[2], dipsw; -static SFORMAT StateRegs[] = { - { &dipsw, 1, "RST" }, - { reg, 2, "LATC" }, - { 0 } -}; - -static void Sync(void) { - uint8 base = (reg[0] >> 7) | ((reg[1] & 0x01) << 1); - uint8 prg = reg[0] & 0x1F; - - /* 1536KiB PRG roms have different bank order */ - if ((PRG_ROM_SIZE == (1536 * 1024)) && (base > 0)) { - base = (base - 1); - } - - if (reg[0] & 0x20) { - setprg16(0x8000, (base << 5) | prg); - setprg16(0xC000, (base << 5) | prg); - } else { - setprg32(0x8000, ((base << 5) | prg) >> 1); - } - - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !(reg[1] & 0x02)); - setchr8(0); - setmirror((reg[0] >> 6) & 0x01); -} - -static DECLFW(M226Write) { - reg[A & 0x01] = V; - Sync(); -} - -static void M226Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetWriteHandler(0x8000, 0xFFFF, M226Write); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void StateRestore(int version) { - Sync(); -} - -static void M226Reset(void) { - reg[0] = reg[1] = 0; - Sync(); -} - -void Mapper226_Init(CartInfo *info) { - info->Power = M226Power; - info->Reset = M226Reset; - AddExState(StateRegs, ~0, 0, NULL); - GameStateRestore = StateRestore; -} diff --git a/src/mappers/mapper227.c b/src/mappers/mapper227.c deleted file mode 100644 index 66ac20593..000000000 --- a/src/mappers/mapper227.c +++ /dev/null @@ -1,69 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static void Sync(void) { - uint32 prg = ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); - uint32 cpuA14 = latch.addr & 0x01; - uint32 nrom = (latch.addr >> 7) & 0x01; - uint32 unrom = (latch.addr >> 9) & 0x01; - - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, prg & ~cpuA14); - setprg16(0xC000, ((prg | cpuA14) & ~(0x07 * !nrom * !unrom)) | (0x07 * !nrom * unrom)); - - setchr8(0); - setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); - if (!iNESCart.battery && (latch.addr & 0x80) == 0x80) { - /* CHR-RAM write protect hack, needed for some multicarts */ - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); - } else { - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); - } -} - -static DECLFR(M227Read) { - if ((latch.addr & 0x400) && dipsw) { - A |= dipsw; - } - return CartBROB(A); -} - -static void M227Power(void) { - dipsw = 0; - Latch_Power(); -} - -static void M227Reset(void) { - dipsw = (dipsw + 1) & 0x1F; - Latch_RegReset(); -} - -void Mapper227_Init(CartInfo *info) { - Latch_Init(info, Sync, M227Read, TRUE, FALSE); - info->Power = M227Power; - info->Reset = M227Reset; - AddExState(&dipsw, 1, 0, "PADS"); -} diff --git a/src/mappers/mapper228.c b/src/mappers/mapper228.c deleted file mode 100644 index 5dc36df33..000000000 --- a/src/mappers/mapper228.c +++ /dev/null @@ -1,71 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - Mapper 228: - Action 52 is highly uncommon in that its PRG ROM has a non-power-of-two ROM size: three 512 KiB PRG ROMs alongside one - 512 KiB CHR ROM. - - It is claimed that there are four 4-bit RAM locations at $4020-$4023, mirrored throughout $4020-$5FFF. This 16-bit RAM - is definitely not present on either cartridge, Nestopia does not implement it at all, and neither cartridge ever writes - to these addresses. - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x20) { - setprg16(0x8000, (latch.addr >> 6) & 0x7F); - setprg16(0xC000, (latch.addr >> 6) & 0x7F); - } else { - setprg32(0x8000, (latch.addr >> 7) & 0x3F); - } - setchr8(((latch.addr << 2) & 0x3C) | (latch.data & 0x3)); - setmirror(((latch.addr >> 13) & 0x01) ^ 0x01); -} - -void Mapper228_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - - if (PRG_ROM_SIZE == 0x180000) { - int i; - size_t ssize = 0x200000; - uint8 *tmp = (uint8 *)FCEU_malloc(ssize); - - for (i = 0; i < (int)PRG_ROM_SIZE; i++) { - tmp[i] = PRG_ROM_PTR[i]; - } - for (i = 0x000000; i < 0x080000; i++) { - tmp[0x180000 + i] = tmp[0x100000 + i]; - tmp[0x100000 + i] = (i >> 8) & 0xFF; - } - - if (PRG_ROM_PTR) FCEU_free(PRG_ROM_PTR); - PRG_ROM_PTR = (uint8 *)FCEU_malloc(ssize); - for (i = 0; i < (int)ssize; i++) { - PRG_ROM_PTR[i] = tmp[i]; - } - FCEU_free(tmp); - - SetupCartPRGMapping(0, PRG_ROM_PTR, ssize, 0); - } -} diff --git a/src/mappers/mapper229.c b/src/mappers/mapper229.c deleted file mode 100644 index 2fc519e76..000000000 --- a/src/mappers/mapper229.c +++ /dev/null @@ -1,38 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x1E) { - setprg16(0x8000, latch.addr & 0x1F); - setprg16(0xC000, latch.addr & 0x1F); - } else { - setprg32(0x8000, 0); - } - setchr8(latch.addr & 0x1F); - setmirror(((latch.addr >> 5) & 0x01) ^ 0x01); -} - -void Mapper229_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper230.c b/src/mappers/mapper230.c deleted file mode 100644 index 8c505b03f..000000000 --- a/src/mappers/mapper230.c +++ /dev/null @@ -1,68 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2009 qeed - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * 22 + Contra Reset based custom mapper... - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 mode; - -static SFORMAT StateRegs[] = { - { &mode, 1, "MODE" }, - { 0 } -}; - -static void Sync(void) { - if (mode) { /* Contra mode */ - setprg16(0x8000, latch.data & 0x07); - setprg16(0xC000, 0x07); - setmirror(MI_V); - } else { /* multicart mode */ - if (latch.data & 0x20) { - setprg16(0x8000, 8 + (latch.data & 0x1F)); - setprg16(0xC000, 8 + (latch.data & 0x1F)); - } else { - setprg32(0x8000, (8 + (latch.data & 0x1F)) >> 1); - } - setmirror((latch.data >> 6) & 0x01); - } - setchr8(0); -} - -static void M230Reset(void) { - mode ^= 1; - Latch_RegReset(); -} - -static void M230Power(void) { - mode = 0; - Latch_Power(); -} - -void Mapper230_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M230Power; - info->Reset = M230Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper231.c b/src/mappers/mapper231.c deleted file mode 100644 index dca7c117c..000000000 --- a/src/mappers/mapper231.c +++ /dev/null @@ -1,43 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x20) { - setprg32(0x8000, (latch.addr >> 1) & 0x0F); - } else { - setprg16(0x8000, latch.addr & 0x1E); - setprg16(0xC000, latch.addr & 0x1E); - } - setchr8(0); - switch ((latch.addr >> 6) & 0x03) { - case 0: setmirror(MI_0); break; - case 1: setmirror(MI_V); break; - case 2: setmirror(MI_H); break; - case 3: setmirrorw(0, 1, 1, 1); break; - } -} - -void Mapper231_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper232.c b/src/mappers/mapper232.c deleted file mode 100644 index e004e819b..000000000 --- a/src/mappers/mapper232.c +++ /dev/null @@ -1,62 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint8 base = (reg[0] >> 1) & 0x0C; - - if (iNESCart.submapper == 1) { - base = ((base << 1) & 0x08) | ((base >> 1) & 0x04); - } - setprg16(0x8000, base | (reg[1] & 0x03)); - setprg16(0xC000, base | 0x03); - setchr8(0); -} - -static DECLFW(M232Write) { - reg[(A >> 14) & 0x01] = V; - Sync(); -} - -static void M232Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M232Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper232_Init(CartInfo *info) { - info->Power = M232Power; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper233.c b/src/mappers/mapper233.c deleted file mode 100644 index 5d271382b..000000000 --- a/src/mappers/mapper233.c +++ /dev/null @@ -1,72 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2009 qeed - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Updated 2019-07-12 - * Mapper 233 - UNIF 42in1ResetSwitch - reset-based switching - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reset; - -static SFORMAT StateRegs[] = { - { &reset, 1, "RST0" }, - { 0 } -}; - -static void Sync(void) { - uint8 bank = (latch.data & 0x1F) | (reset << 5); - - if (latch.data & 0x20) { - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } else { - setprg32(0x8000, bank >> 1); - } - setchr8(0); - switch ((latch.data >> 6) & 0x03) { - case 0: setmirror(MI_0); break; - case 1: setmirror(MI_V); break; - case 2: setmirror(MI_H); break; - case 3: setmirror(MI_1); break; - } -} - -static void M233Power(void) { - reset = 0; - Latch_Power(); -} - -static void M233Reset(void) { - reset ^= 1; - Sync(); -} - -void Mapper233_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M233Power; - info->Reset = M233Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper234.c b/src/mappers/mapper234.c deleted file mode 100644 index 3cbf5e46c..000000000 --- a/src/mappers/mapper234.c +++ /dev/null @@ -1,95 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[3]; - -static SFORMAT StateRegs[] = { - { reg, 3, "REGS" }, - { 0 } -}; - -static void Sync(void) { - if (reg[0] & 0x40) { - setprg32(0x8000, (reg[0] & 0x0E) | (reg[1] & 0x01)); - setchr8(((reg[0] & 0x0E) << 2) | ((reg[1] >> 4) & 0x07)); - } else { - setprg32(0x8000, reg[0] & 0x0F); - setchr8(((reg[0] & 0x0F) << 2) | ((reg[1] >> 4) & 0x03)); - } - setmirror((reg[0] >> 7) ^ 0x01); -} - -static DECLFR(M234Read) { - uint8 ret = CartBR(A); - - switch (A & 0xFFF8) { - case 0xFF80: - case 0xFF88: - case 0xFF90: - case 0xFF98: - if (!reg[0]) { - reg[0] = ret; - Sync(); - } - break; - case 0xFFC0: - case 0xFFC8: - case 0xFFD0: - case 0xFFD8: - if (!reg[0]) { - reg[2] = ret; - Sync(); - } - break; - case 0xFFE8: - case 0xFFF0: - reg[1] = ret; - Sync(); - break; - } - - return ret; -} - -static void M234Reset(void) { - reg[0] = reg[1] = reg[2] = 0; - Sync(); -} - -static void M234Power(void) { - reg[0] = reg[1] = reg[2] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0xFF80, 0xFFFF, M234Read); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper234_Init(CartInfo *info) { - info->Power = M234Power; - info->Reset = M234Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper235.c b/src/mappers/mapper235.c deleted file mode 100644 index 339ce377c..000000000 --- a/src/mappers/mapper235.c +++ /dev/null @@ -1,78 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 mode; - -static SFORMAT StateRegs[] = { - { &mode, 1, "UROM" }, - { 0 } -}; - -static void Sync(void) { - if (mode) { /* Contra mode */ - setprg16(0x8000, (PRG_BANK_COUNT(16) & 0xC0) | (latch.data & 0x07)); - setprg16(0xC000, (PRG_BANK_COUNT(16) & 0xC0) | 0x07); - setchr8(0); - setmirror(MI_V); - } else { - uint8 bank = ((latch.addr >> 3) & 0x60) | (latch.addr & 0x1F); - - if (latch.addr & 0x800) { - setprg16(0x8000, (bank << 1) | ((latch.addr >> 12) & 0x01)); - setprg16(0xC000, (bank << 1) | ((latch.addr >> 12) & 0x01)); - } else { - setprg32(0x8000, bank); - } - setchr8(0); - if (latch.addr & 0x400) { - setmirror(MI_0); - } else { - setmirror(((latch.addr >> 13) & 0x01) ^ 0x01); - } - } -} - -static DECLFR(M235Read) { - uint8 bank = ((latch.addr >> 3) & 0x60) | (latch.addr & 0x1F); - - if (!mode && (bank >= PRG_BANK_COUNT(32))) { - return CPU_OPENBUS; - } - return CartBR(A); -} - -static void M235Reset(void) { - if (PRG_ROM_SIZE & 0x20000) { - mode = (mode + 1) & 1; - } - Latch_RegReset(); - FCEU_printf("mode : %d\n", mode); -} - -void Mapper235_Init(CartInfo *info) { - Latch_Init(info, Sync, M235Read, FALSE, FALSE); - info->Reset = M235Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper236.c b/src/mappers/mapper236.c deleted file mode 100644 index c3b613e82..000000000 --- a/src/mappers/mapper236.c +++ /dev/null @@ -1,102 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[2]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &dipsw, 1, "DPSW " }, - { 0 } -}; - -static void Sync(void) { - uint8 prg; - uint8 chr; - - if (CHR_ROM_SIZE) { - prg = reg[1] & 0x0F; - chr = reg[0] & 0x0F; - } else { - prg = (reg[1] & 0x07) | (reg[0] << 3); - chr = 0; - } - switch (reg[1] >> 4 & 3) { - case 0: - case 1: - setprg16(0x8000, prg); - setprg16(0xC000, prg | 0x07); - break; - case 2: - setprg32(0x8000, prg >> 1); - break; - case 3: - setprg16(0x8000, prg); - setprg16(0xC000, prg); - break; - } - setchr8(chr); - setmirror(((reg[0] >> 5) & 0x01) ^ 0x01); -} - -static DECLFR(M236Read) { - uint8 ret = CartBR(A); - - if (((reg[1] >> 4) & 0x03) == 1) { - return ((ret & ~0x0F) | (dipsw & 0x0F)); - } - return CartBR(A); -} - -static DECLFW(M236WriteReg) { - reg[(A >> 14) & 0x01] = A & 0xFF; - Sync(); -} - -static void M236Power(void) { - dipsw = 0; - reg[0] = 0; - reg[1] = 0; - Sync(); - SetWriteHandler(0x8000, 0xFFFF, M236WriteReg); - SetReadHandler(0x8000, 0xFFFF, M236Read); -} - -static void M236Reset(void) { - ++dipsw; - /* Soft-reset returns to menu */ - reg[0] = 0; - reg[1] = 0; - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper236_Init(CartInfo *info) { - info->Power = M236Power; - info->Reset = M236Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper237.c b/src/mappers/mapper237.c deleted file mode 100644 index 259f0c33a..000000000 --- a/src/mappers/mapper237.c +++ /dev/null @@ -1,88 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 237 - "Teletubbies / Y2K" 420-in-1 pirate multicart. - * Dipswitch settings: - * 0: 42-in-1 - * 1: 5,000-in-1 - * 2: 420-in-1 - * 3: 10,000,000-in-1 (lol) - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - uint8 bank = (latch.data & 0x07); - uint8 base = ((latch.addr << 3) & 0x20) | (latch.data & 0x18); - uint8 A14 = (latch.data >> 6) & 0x01; - - setprg16(0x8000, base | (bank & ~A14)); - if (latch.data & 0x80) { - setprg16(0xC000, base | (bank | A14)); - } else { - setprg16(0xC000, base | 0x07); - } - setchr8(0); - setmirror(((latch.data & 0x20) >> 5) ^ 0x01); -} - -static DECLFW(M237Write) { - if (latch.addr & 0x02) { - latch.data = (latch.data & 0xF8) | (V & 0x07); - } else { - latch.addr = A; - latch.data = V; - } - Sync(); -} - -static DECLFR(M237Read) { - if (latch.addr & 0x01) { - return dipsw; - } - return CartBR(A); -} - -static void M237Reset(void) { - dipsw++; - dipsw &= 3; - Latch_RegReset(); -} - -static void M237Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M237Write); -} - -void Mapper237_Init(CartInfo *info) { - Latch_Init(info, Sync, M237Read, FALSE, FALSE); - info->Power = M237Power; - info->Reset = M237Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper238.c b/src/mappers/mapper238.c deleted file mode 100644 index b8499a31d..000000000 --- a/src/mappers/mapper238.c +++ /dev/null @@ -1,54 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * iNES Mapper 238 - * SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1) - * the same as 603-5052 board (TODO: add reading registers, merge) - * - * Contra Fighter prot board - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static const uint8 lut[4] = { 0x00, 0x02, 0x02, 0x03 }; - -static DECLFW(M238ProtWrite) { - reg = lut[V & 0x03]; -} - -static DECLFR(M238ProtRead) { - return reg; -} - -static void M238Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x4020, 0x7FFF, M238ProtWrite); - SetReadHandler(0x4020, 0x7FFF, M238ProtRead); -} - -void Mapper238_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - info->Power = M238Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper240.c b/src/mappers/mapper240.c deleted file mode 100644 index 2cf33c15e..000000000 --- a/src/mappers/mapper240.c +++ /dev/null @@ -1,71 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg >> 4); - setchr8(reg & 0x0F); - setprg8r(0x10, 0x6000, 0); -} - -static DECLFW(M240Write) { - reg = V; - Sync(); -} - -static void M240Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x4020, 0x4FFF, M240Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper240_Init(CartInfo *info) { - info->Power = M240Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - if (info->iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - } - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } -} diff --git a/src/mappers/mapper241.c b/src/mappers/mapper241.c deleted file mode 100644 index 7db733685..000000000 --- a/src/mappers/mapper241.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Map 241 */ -/* Mapper 7 mostly, but with SRAM or maybe prot circuit. */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, latch.data); - setchr8(0); -} - -void Mapper241_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper242.c b/src/mappers/mapper242.c deleted file mode 100644 index 4369db5d2..000000000 --- a/src/mappers/mapper242.c +++ /dev/null @@ -1,79 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static void Sync(void) { - uint32 prg = (latch.addr >> 2) & 0x1F; - uint32 cpuA14 = latch.addr & 0x01; - uint32 nrom = (latch.addr >> 7) & 0x01; - uint32 unrom = (latch.addr >> 9) & 0x01; - uint32 M242TwoChips = (PRG_ROM_SIZE & 0x20000) && (PRG_ROM_SIZE > 0x20000); - - if (M242TwoChips) { - if (latch.addr & 0x600) { /* First chip */ - prg &= ((PRG_BANK_COUNT(16) & ~0x08) - 1); - } else { /* Second chip */ - prg &= 0x07; - prg += (PRG_BANK_COUNT(16) & ~0x08); - } - } - - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, prg & ~cpuA14); - setprg16(0xC000, ((prg | cpuA14) & ~(0x07 * !nrom * !unrom)) | (0x07 * !nrom * unrom)); - - setchr8(0); - setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); - if (!iNESCart.battery && (latch.addr & 0x80) == 0x80 && (PRG_ROM_SIZE > (256 * 1024))) { - /* CHR-RAM write protect hack, needed for some multicarts */ - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); - } else { - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); - } -} - -static DECLFR(M242Read) { - if (latch.addr & 0x100) { - A |= dipsw; - } - return CartBROB(A); -} - -static void M242Power(void) { - dipsw = 0; - Latch_Power(); -} - -static void M242Reset(void) { - dipsw = (dipsw + 1) & 0x1F; - Latch_RegReset(); -} - -void Mapper242_Init(CartInfo *info) { - Latch_Init(info, Sync, M242Read, TRUE, FALSE); - info->Power = M242Power; - info->Reset = M242Reset; - AddExState(&dipsw, 1, 0, "PADS"); -} diff --git a/src/mappers/mapper244.c b/src/mappers/mapper244.c deleted file mode 100644 index 059af9713..000000000 --- a/src/mappers/mapper244.c +++ /dev/null @@ -1,77 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, reg[0]); - setchr8(reg[1]); -} - -static DECLFW(M244Write) { - if (V & 8) { - static const uint8 chr_perm[8][8] = { - { 0, 1, 2, 3, 4, 5, 6, 7, }, - { 0, 2, 1, 3, 4, 6, 5, 7, }, - { 0, 1, 4, 5, 2, 3, 6, 7, }, - { 0, 4, 1, 5, 2, 6, 3, 7, }, - { 0, 4, 2, 6, 1, 5, 3, 7, }, - { 0, 2, 4, 6, 1, 3, 5, 7, }, - { 7, 6, 5, 4, 3, 2, 1, 0, }, - { 7, 6, 5, 4, 3, 2, 1, 0, }, - }; - reg[1] = chr_perm[(V >> 4) & 0x07][V & 0x07]; - Sync(); - } else { - static const uint8 prg_perm[4][4] = { - { 0, 1, 2, 3, }, - { 3, 2, 1, 0, }, - { 0, 2, 1, 3, }, - { 3, 1, 2, 0, }, - }; - reg[0] = prg_perm[(V >> 4) & 0x03][V & 0x03]; - Sync(); - } -} - -static void M244Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetWriteHandler(0x8000, 0xFFFF, M244Write); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper244_Init(CartInfo *info) { - info->Power = M244Power; - AddExState(StateRegs, ~0, 0, NULL); - GameStateRestore = StateRestore; -} diff --git a/src/mappers/mapper245.c b/src/mappers/mapper245.c deleted file mode 100644 index 419a81d52..000000000 --- a/src/mappers/mapper245.c +++ /dev/null @@ -1,61 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M245PW(uint16 A, uint16 V) { - setprg8(A, ((mmc3.reg[0] & 0x02) << 5) | (V & 0x3F)); -} - -static void M245CW(uint16 A, uint16 V) { - setchr8(0); -} - -static DECLFW(M245Write) { - if (A & 0x01) { - mmc3.reg[mmc3.cmd & 0x07] = V; - } else { - mmc3.cmd = V; - } - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M245Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x8000, 0x9FFF, M245Write); -} - -void Mapper245_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - info->Power = M245Power; - MMC3_pwrap = M245PW; - MMC3_cwrap = M245CW; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper246.c b/src/mappers/mapper246.c deleted file mode 100644 index ecc161fdc..000000000 --- a/src/mappers/mapper246.c +++ /dev/null @@ -1,99 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[4]; -static uint8 chr[4]; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 4, "CREG" }, - { 0 } -}; - -static void Sync(void) { - setprg2r(0x10, 0x6800, 0); - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, prg[3]); - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr2(0x1000, chr[2]); - setchr2(0x1800, chr[3]); -} - -static DECLFR(M246Read) { - if ((A & 0xFFE4) == 0xFFE4) { - size_t prgOffset = ((prg[3] | 0x10) << 13) | 0x1000 | (A & 0xFFF); - return PRGptr[0][prgOffset & 0x7FFFF]; - } - return CartBR(A); -} - -static DECLFW(M246Write) { - if (A & 0x04) { - chr[A & 0x03] = V; - Sync(); - } else { - prg[A & 0x03] = V; - Sync(); - } -} - -static void M246Power(void) { - prg[0] = 0; - prg[1] = 1; - prg[2] = ~1; - prg[3] = ~0; - Sync(); - - SetReadHandler(0x6800, 0x6FFF, CartBR); - SetReadHandler(0x8000, 0xFFFF, M246Read); - SetWriteHandler(0x6000, 0x67FF, M246Write); - SetWriteHandler(0x6800, 0x6FFF, CartBW); - - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M246Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper246_Init(CartInfo *info) { - info->Power = M246Power; - info->Close = M246Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 2048; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } -} diff --git a/src/mappers/mapper249.c b/src/mappers/mapper249.c deleted file mode 100644 index dbdc25e37..000000000 --- a/src/mappers/mapper249.c +++ /dev/null @@ -1,89 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static uint32 scrambleBankOrder(uint32 V, const uint8 *source, const uint8 *target, uint32 length) { - uint32 bank = 0; - uint32 bit = 0; - - for (bit = 0; bit < 8; bit++) { - if (V & (0x01 << bit)) { - uint32 index = 0; - - for (index = 0; index < length; index++) { - if (source[index] == bit) { - break; - } - } - bank |= (0x01 << (index == length ? bit : target[index])); - } - } - return bank; -} - -static void M249PW(uint16 A, uint16 V) { - static const uint8 prg_pattern[4][4] = { - { 3, 4, 2, 1 }, - { 4, 3, 1, 2 }, - { 1, 2, 3, 4 }, - { 2, 1, 4, 3 }, - }; - uint32 bank = scrambleBankOrder(V, prg_pattern[reg & 0x03], prg_pattern[(iNESCart.mapper == 249) ? 0 : 2], 4); - setprg8(A, bank); -} - -static void M249CW(uint16 A, uint16 V) { - static const uint8 chr_pattern[8][6] = { - { 5, 2, 6, 7, 4, 3 }, - { 4, 5, 3, 2, 7, 6 }, - { 2, 3, 4, 5, 6, 7 }, - { 6, 4, 2, 3, 7, 5 }, - { 5, 3, 7, 6, 2, 4 }, - { 4, 2, 5, 6, 7, 3 }, - { 3, 6, 4, 5, 2, 7 }, - { 2, 5, 6, 7, 3, 4 }, - }; - uint32 bank = scrambleBankOrder(V, chr_pattern[reg & 0x07], chr_pattern[(iNESCart.mapper == 249) ? 0 : 2], 6); - setchr1(A, bank); -} - -static DECLFW(M249Write) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M249Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x5000, 0x5FFF, M249Write); -} - -void Mapper249_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - MMC3_cwrap = M249CW; - MMC3_pwrap = M249PW; - info->Power = M249Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper250.c b/src/mappers/mapper250.c deleted file mode 100644 index 0d1afd1d1..000000000 --- a/src/mappers/mapper250.c +++ /dev/null @@ -1,36 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static DECLFW(M250Write) { - MMC3_Write(((A & 0xE000) | ((A & 0x400) >> 10)), (A & 0xFF)); -} - -static void M250Power(void) { - MMC3_Power(); - SetWriteHandler(0x8000, 0xFFFF, M250Write); -} - -void Mapper250_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - info->Power = M250Power; -} diff --git a/src/mappers/mapper252.c b/src/mappers/mapper252.c deleted file mode 100644 index cf4f5cbe1..000000000 --- a/src/mappers/mapper252.c +++ /dev/null @@ -1,93 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 maskCHRCompare; -static uint8 maskCHRBank; - -static writefunc writePPU; -extern uint32 RefreshAddr; - -static void M252PW(uint16 A, uint16 V) { - setprg8(A, V & 0x1F); -} - -static void M252CW(uint16 A, uint16 V) { - if ((V & maskCHRBank) == maskCHRCompare) { - setchr1r(0x10, A, V & 0x01); - } else { - setchr1(A, V); - } -} - -static DECLFW(M252PPU_B2007) { - if (RefreshAddr < 0x2000) { - switch (vrc24.chr[RefreshAddr >> 10]) { - case 0x88: - maskCHRBank = 0xFC; - maskCHRCompare = 0x4C; - break; - case 0xC2: - maskCHRBank = 0xFE; - maskCHRCompare = 0x7C; - break; - case 0xC8: - maskCHRBank = 0xFE; - maskCHRCompare = 0x04; - break; - } - } - writePPU(A, V); -} - -static void M252Close(void) { - VRC24_Close(); -} - -static void M252Power(void) { - if (iNESCart.mapper == 252) { - maskCHRBank = 0xFE; - maskCHRCompare = 0x06; - } else { - maskCHRBank = 0xFE; - maskCHRCompare = 0x04; - } - VRC24_Power(); - - writePPU = GetWriteHandler(0x2007); - SetWriteHandler(0x2007, 0x2007, M252PPU_B2007); -} - -void Mapper252_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x04, 0x08, TRUE, TRUE); - VRC24_pwrap = M252PW; - VRC24_cwrap = M252CW; - - info->Power = M252Power; - info->Close = M252Close; - - CHRRAMSIZE = 2048; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); -} diff --git a/src/mappers/mapper254.c b/src/mappers/mapper254.c deleted file mode 100644 index e39d633fe..000000000 --- a/src/mappers/mapper254.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static DECLFR(M254ReadWRAM) { - if (reg == TRUE) { - return CPU_OPENBUS ^ (reg * 0x80); - } - return CartBR(A); -} - -static DECLFW(M254WriteWRAM) { - if (V & 0x01) { - reg = FALSE; - } - CartBW(A, V); -} - -static void M254Reset(void) { - reg = TRUE; - MMC3_FixCHR(); - MMC3_FixPRG(); -} - -static void M254Power(void) { - reg = 0x80; - MMC3_Power(); - SetReadHandler(0x6000, 0x7FFF, M254ReadWRAM); - SetWriteHandler(0x6000, 0x7FFF, M254WriteWRAM); -} - -void Mapper254_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - info->Power = M254Power; - info->Reset = M254Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper256.c b/src/mappers/mapper256.c deleted file mode 100644 index 8c13f068a..000000000 --- a/src/mappers/mapper256.c +++ /dev/null @@ -1,418 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007-2010 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * VR02/VT03 Console and OneBus System - * - * Street Dance (Dance pad) (Unl) - * 101-in-1 Arcade Action II - * DreamGEAR 75-in-1, etc. - * - */ - -#include "mapinc.h" - -static uint8 submapper; - -/* General Purpose Registers */ -static uint8 cpu410x[16], ppu201x[16], apu40xx[64]; - -/* IRQ Registers */ -static uint8 IRQCount, IRQa, IRQReload; -#define IRQLatch cpu410x[0x1] /* accc cccc, a = 0, AD12 switching, a = 1, HSYNC switching */ - -/* MMC3 Registers */ -#define mmc3cmd cpu410x[0x5] /* pcv- ----, p - program swap, c - video swap, v - internal VRAM enable */ -#define mirror cpu410x[0x6] /* ---- ---m, m = 0 - H, m = 1 - V */ - -/* APU Registers */ -static uint8 pcm_enable = 0, pcm_irq = 0; -static int16 pcm_addr, pcm_size, pcm_latch, pcm_clock = 0xE1; - -static writefunc defapuwrite[64]; -static readfunc defapuread[64]; - -static SFORMAT StateRegs[] = -{ - { cpu410x, 16, "REGC" }, - { ppu201x, 16, "REGS" }, - { apu40xx, 64, "REGA" }, - { &IRQReload, 1, "IRQR" }, - { &IRQCount, 1, "IRQC" }, - { &IRQa, 1, "IRQA" }, - { &pcm_enable, 1, "PCME" }, - { &pcm_irq, 1, "PCMI" }, - { &pcm_addr, 2, "PCMA" }, - { &pcm_size, 2, "PCMS" }, - { &pcm_latch, 2, "PCML" }, - { &pcm_clock, 2, "PCMC" }, - { 0 } -}; - -static void PSync(void) { - uint8 bankmode = cpu410x[0xb] & 7; - uint8 mask = (bankmode == 0x7) ? (0xff) : (0x3f >> bankmode); - uint32 block = ((cpu410x[0x0] & 0xf0) << 4) + (cpu410x[0xa] & (~mask)); - uint32 pswap = (mmc3cmd & 0x40) << 8; - -#if 0 - uint8 bank0 = (cpu410x[0xb] & 0x40)?(~1):(cpu410x[0x7]); - uint8 bank1 = cpu410x[0x8]; - uint8 bank2 = (cpu410x[0xb] & 0x40)?(cpu410x[0x9]):(~1); - uint8 bank3 = ~0; -#endif - uint8 bank0 = cpu410x[0x7]; - uint8 bank1 = cpu410x[0x8]; - uint8 bank2 = (cpu410x[0xb] & 0x40) ? (cpu410x[0x9]) : (~1); - uint8 bank3 = ~0; - -/* FCEU_printf(" PRG: %04x [%02x]",0x8000^pswap,block | (bank0 & mask)); */ - setprg8(0x8000 ^ pswap, block | (bank0 & mask)); -/* FCEU_printf(" %04x [%02x]",0xa000^pswap,block | (bank1 & mask)); */ - setprg8(0xa000, block | (bank1 & mask)); -/* FCEU_printf(" %04x [%02x]",0xc000^pswap,block | (bank2 & mask)); */ - setprg8(0xc000 ^ pswap, block | (bank2 & mask)); -/* FCEU_printf(" %04x [%02x]\n",0xe000^pswap,block | (bank3 & mask)); */ - setprg8(0xe000, block | (bank3 & mask)); -} - -static void CSync(void) { - static const uint8 midx[8] = { 0, 1, 2, 0, 3, 4, 5, 0 }; - uint8 mask = 0xff >> midx[ppu201x[0xa] & 7]; - uint32 block = ((cpu410x[0x0] & 0x0f) << 11) + ((ppu201x[0x8] & 0x70) << 4) + (ppu201x[0xa] & (~mask)); - uint32 cswap = (mmc3cmd & 0x80) << 5; - - uint8 bank0 = ppu201x[0x6] & (~1); - uint8 bank1 = ppu201x[0x6] | 1; - uint8 bank2 = ppu201x[0x7] & (~1); - uint8 bank3 = ppu201x[0x7] | 1; - uint8 bank4 = ppu201x[0x2]; - uint8 bank5 = ppu201x[0x3]; - uint8 bank6 = ppu201x[0x4]; - uint8 bank7 = ppu201x[0x5]; - - setchr1(0x0000 ^ cswap, block | (bank0 & mask)); - setchr1(0x0400 ^ cswap, block | (bank1 & mask)); - setchr1(0x0800 ^ cswap, block | (bank2 & mask)); - setchr1(0x0C00 ^ cswap, block | (bank3 & mask)); - setchr1(0x1000 ^ cswap, block | (bank4 & mask)); - setchr1(0x1400 ^ cswap, block | (bank5 & mask)); - setchr1(0x1800 ^ cswap, block | (bank6 & mask)); - setchr1(0x1C00 ^ cswap, block | (bank7 & mask)); - - setmirror((mirror ^ 1) & 1); -} - -static void Sync(void) { - PSync(); - CSync(); -} - -static const uint8 cpuMangle[16][4] = { - { 0, 1, 2, 3 }, /* Submapper 0: Normal */ - { 0, 1, 2, 3 }, /* Submapper 1: Waixing VT03 */ - { 1, 0, 2, 3 }, /* Submapper 2: Trump Grand */ - { 0, 1, 2, 3 }, /* Submapper 3: Zechess */ - { 0, 1, 2, 3 }, /* Submapper 4: Qishenglong */ - { 0, 1, 2, 3 }, /* Submapper 5: Waixing VT02 */ - { 0, 1, 2, 3 }, /* Submapper 6: unused so far */ - { 0, 1, 2, 3 }, /* Submapper 7: unused so far */ - { 0, 1, 2, 3 }, /* Submapper 8: unused so far */ - { 0, 1, 2, 3 }, /* Submapper 9: unused so far */ - { 0, 1, 2, 3 }, /* Submapper A: unused so far */ - { 0, 1, 2, 3 }, /* Submapper B: unused so far */ - { 0, 1, 2, 3 }, /* Submapper C: unused so far */ - { 0, 1, 2, 3 }, /* Submapper D: Cube Tech (CPU opcode encryption only) */ - { 0, 1, 2, 3 }, /* Submapper E: Karaoto (CPU opcode encryption only) */ - { 0, 1, 2, 3 } /* Submapper F: Jungletac (CPU opcode encryption only) */ -}; -static DECLFW(M256WriteCPU410X) { - /* FCEU_printf("CPU %04x:%04x\n",A,V); */ - A &= 0xF; - switch (A) { - case 0x1: - IRQLatch = V & 0xfe; - break; /* �� �� �������� */ - case 0x2: - IRQReload = 1; - break; - case 0x3: - X6502_IRQEnd(FCEU_IQEXT); - IRQa = 0; - break; - case 0x4: - IRQa = 1; - break; - default: - if (A >= 0x7 && A <= 0xA) - A = 0x7 + cpuMangle[submapper][A - 0x7]; - cpu410x[A] = V; - Sync(); - } -} - -static const uint8 ppuMangle[16][6] = { - { 0, 1, 2, 3, 4, 5 }, /* Submapper 0: Normal */ - { 1, 0, 5, 4, 3, 2 }, /* Submapper 1: Waixing VT03 */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper 2: Trump Grand */ - { 5, 4, 3, 2, 0, 1 }, /* Submapper 3: Zechess */ - { 2, 5, 0, 4, 3, 1 }, /* Submapper 4: Qishenglong */ - { 1, 0, 5, 4, 3, 2 }, /* Submapper 5: Waixing VT02 */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper 6: unused so far */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper 7: unused so far */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper 8: unused so far */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper 9: unused so far */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper A: unused so far */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper B: unused so far */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper C: unused so far */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper D: Cube Tech (CPU opcode encryption only) */ - { 0, 1, 2, 3, 4, 5 }, /* Submapper E: Karaoto (CPU opcode encryption only) */ - { 0, 1, 2, 3, 4, 5 } /* Submapper F: Jungletac (CPU opcode encryption only) */ -}; -static DECLFW(M256WritePPU201X) { - /* FCEU_printf("PPU %04x:%04x\n",A,V); */ - A &= 0x0F; - if (A >= 2 && A <= 7) - A = 2 + ppuMangle[submapper][A - 2]; - ppu201x[A] = V; - Sync(); -} - -static const uint8 mmc3Mangle[16][8] = { - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 0: Normal */ - { 5, 4, 3, 2, 1, 0, 6, 7 }, /* Submapper 1: Waixing VT03 */ - { 0, 1, 2, 3, 4, 5, 7, 6 }, /* Submapper 2: Trump Grand */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 3: Zechess */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 4: Qishenglong */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 5: Waixing VT02 */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 6: unused so far */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 7: unused so far */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 8: unused so far */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper 9: unused so far */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper A: unused so far */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper B: unused so far */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper C: unused so far */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper D: Cube Tech (CPU opcode encryption only) */ - { 0, 1, 2, 3, 4, 5, 6, 7 }, /* Submapper E: Karaoto (CPU opcode encryption only) */ - { 0, 1, 2, 3, 4, 5, 6, 7 } /* Submapper F: Jungletac (CPU opcode encryption only) */ -}; -static DECLFW(M256WriteMMC3) { - /* FCEU_printf("MMC %04x:%04x\n",A,V); */ - switch (A & 0xe001) { - case 0x8000: - V = (V & 0xF8) | mmc3Mangle[submapper][V & 0x07]; - mmc3cmd = (mmc3cmd & 0x38) | (V & 0xc7); - Sync(); - break; - case 0x8001: { - switch (mmc3cmd & 7) { - case 0: - ppu201x[0x6] = V; - CSync(); - break; - case 1: - ppu201x[0x7] = V; - CSync(); - break; - case 2: - ppu201x[0x2] = V; - CSync(); - break; - case 3: - ppu201x[0x3] = V; - CSync(); - break; - case 4: - ppu201x[0x4] = V; - CSync(); - break; - case 5: - ppu201x[0x5] = V; - CSync(); - break; - case 6: - cpu410x[0x7] = V; - PSync(); - break; - case 7: - cpu410x[0x8] = V; - PSync(); - break; - } - break; - } - case 0xa000: - mirror = V; - CSync(); - break; - case 0xc000: - IRQLatch = V & 0xfe; - break; - case 0xc001: - IRQReload = 1; - break; - case 0xe000: - X6502_IRQEnd(FCEU_IQEXT); - IRQa = 0; - break; - case 0xe001: - IRQa = 1; - break; - } -} - -static void M256IRQHook(void) { - uint32 count = IRQCount; - if (!count || IRQReload) { - IRQCount = IRQLatch; - IRQReload = 0; - } else - IRQCount--; - if (count && !IRQCount) { - if (IRQa) - X6502_IRQBegin(FCEU_IQEXT); - } -} - -static DECLFW(M256WriteAPU40XX) { -/* if(((A & 0x3f)!=0x16) && ((apu40xx[0x30] & 0x10) || ((A & 0x3f)>0x17)))FCEU_printf("APU %04x:%04x\n",A,V); */ - apu40xx[A & 0x3f] = V; - switch (A & 0x3f) { - case 0x12: - if (apu40xx[0x30] & 0x10) { - pcm_addr = V << 6; - } - break; - case 0x13: - if (apu40xx[0x30] & 0x10) { - pcm_size = (V << 4) + 1; - } - break; - case 0x15: - if (apu40xx[0x30] & 0x10) { - pcm_enable = V & 0x10; - if (pcm_irq) { - X6502_IRQEnd(FCEU_IQEXT); - pcm_irq = 0; - } - if (pcm_enable) - pcm_latch = pcm_clock; - V &= 0xef; - } - break; - } - defapuwrite[A & 0x3f](A, V); -} - -static DECLFR(M256ReadAPU40XX) { - uint8 result = defapuread[A & 0x3f](A); -/* FCEU_printf("read %04x, %02x\n",A,result); */ - switch (A & 0x3f) { - case 0x15: - if (apu40xx[0x30] & 0x10) { - result = (result & 0x7f) | pcm_irq; - } - break; - } - return result; -} - -static void M256CpuHook(int a) { - if (pcm_enable) { - pcm_latch -= a; - if (pcm_latch <= 0) { - pcm_latch += pcm_clock; - pcm_size--; - if (pcm_size < 0) { - pcm_irq = 0x80; - pcm_enable = 0; - X6502_IRQBegin(FCEU_IQEXT); - } else { - uint16 addr = pcm_addr | ((apu40xx[0x30] ^ 3) << 14); - uint8 raw_pcm = ARead[addr](addr) >> 1; - defapuwrite[0x11](0x4011, raw_pcm); - pcm_addr++; - pcm_addr &= 0x7FFF; - } - } - } -} - -static void M256Power(void) { - uint32 i; - IRQReload = IRQCount = IRQa = 0; - - memset(cpu410x, 0x00, sizeof(cpu410x)); - memset(ppu201x, 0x00, sizeof(ppu201x)); - memset(apu40xx, 0x00, sizeof(apu40xx)); - - SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0); - - for (i = 0; i < 64; i++) { - defapuread[i] = GetReadHandler(0x4000 | i); - defapuwrite[i] = GetWriteHandler(0x4000 | i); - } - SetReadHandler(0x4000, 0x403f, M256ReadAPU40XX); - SetWriteHandler(0x4000, 0x403f, M256WriteAPU40XX); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x2010, 0x201f, M256WritePPU201X); - SetWriteHandler(0x4100, 0x410f, M256WriteCPU410X); - SetWriteHandler(0x8000, 0xffff, M256WriteMMC3); - - FCEU_CheatAddRAM(8, 0x6000, WRAM); - setprg8r(0x10, 0x6000, 0); - Sync(); -} - -static void M256Reset(void) { - IRQReload = IRQCount = IRQa = 0; - - memset(cpu410x, 0x00, sizeof(cpu410x)); - memset(ppu201x, 0x00, sizeof(ppu201x)); - memset(apu40xx, 0x00, sizeof(apu40xx)); - - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -static void M256Close(void) { -} - -void Mapper256_Init(CartInfo *info) { - info->Power = M256Power; - info->Reset = M256Reset; - info->Close = M256Close; - - if (info->iNES2) - submapper = info->submapper; - else - submapper = (((*(uint32 *)&(info->MD5)) == 0x305fcdc3) || ((*(uint32 *)&(info->MD5)) == 0x6abfce8e)) ? 2 : 0; /* PowerJoy Supermax Carts */ - - GameHBIRQHook = M256IRQHook; - MapIRQHook = M256CpuHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAM = (uint8 *)FCEU_gmalloc(8192); - SetupCartPRGMapping(0x10, WRAM, 8192, 1); -} diff --git a/src/mappers/mapper257.c b/src/mappers/mapper257.c deleted file mode 100644 index 5d19d90d8..000000000 --- a/src/mappers/mapper257.c +++ /dev/null @@ -1,123 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[8]; -static uint32 lastnt = 0; - -static SFORMAT StateRegs[] = -{ - { reg, 2, "REG" }, - { &lastnt, 4, "LNT" }, - { 0 } -}; - -static uint8 bs_tbl[128] = { - 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, /* 00 */ - 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, /* 10 */ - 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, /* 20 */ - 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, /* 30 */ - 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, /* 40 */ - 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, /* 50 */ - 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x00, 0x10, 0x20, 0x30, /* 60 */ - 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, /* 70 */ -}; - -static uint8 br_tbl[16] = { - 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, -}; - -static void Sync(void) { - setchr8(0); - setprg8r(0x10, 0x6000, 0); - if(PRGsize[0] == 512 * 1024) { - if(reg[0] & 0x010) { - setprg32(0x8000, reg[0] & 7); - } else { - if(reg[0] & 0x40) - setprg8(0x8000, (reg[0] & 0x0F) | 0x20 | ((reg[0] & 0x20) >> 1)); - } - if((reg[0] & 0x18) == 0x18) - setmirror(MI_H); - else - setmirror(MI_V); - } else { - setprg16(0x8000, bs_tbl[reg[0] & 0x7f] >> 4); - setprg16(0xc000, bs_tbl[reg[0] & 0x7f] & 0xf); - setmirror(MI_V); - } -} - -static DECLFW(M257Write) { - reg[(A & 0x700) >> 8] = V; - PEC586Hack = (reg[0] & 0x80) ? TRUE : FALSE; -/* FCEU_printf("bs %04x %02x\n", A, V); */ - Sync(); -} - -static DECLFR(M257Read) { -/* FCEU_printf("read %04x\n", A); */ - return (CPU_OPENBUS & 0xD8) | br_tbl[reg[4] >> 4]; -} - -static DECLFR(M257ReadHi) { - if((reg[0] & 0x10) || ((reg[0] & 0x40) && (A < 0xA000))) - return CartBR(A); - else - return PRGptr[0][((0x0107 | ((A >> 7) & 0x0F8)) << 10) | (A & 0x3FF)]; -} - -static void M257Power(void) { - if(PRGsize[0] == 512 * 1024) - reg[0] = 0x00; - else - reg[0] = 0x0E; - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - if(PRGsize[0] == 512 * 1024) - SetReadHandler(0x8000, 0xFFFF, M257ReadHi); - else - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5fff, M257Write); - SetReadHandler(0x5000, 0x5fff, M257Read); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M257Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper257_Init(CartInfo *info) { - info->Power = M257Power; - info->Close = M257Close; - GameStateRestore = StateRestore; - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper259.c b/src/mappers/mapper259.c deleted file mode 100644 index d12bd4579..000000000 --- a/src/mappers/mapper259.c +++ /dev/null @@ -1,70 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2015 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 259 - BMC-F-15 - * BMC F-15 PCB (256+266 MMC3 based, with 16/32Kb banking discrete logic) - * 150-in-1 Unchaied Melody FIGHT version with system test (START+SELECT) - * - * CHR - MMC3 stock regs - * PRG - MMC3 regs disabled, area 6000-7FFF used instead - * 011xxxxxxxxxxxxx addr mask, - * ----APPp reg bits mask - * A - higher 128K PRG bank select/32K bank mode override - * PP - bank number in 32K mode - * PPp - bank number in 16K mode - * initial state of extra regs is undefined, A001 enables/disables the 6000 area - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M259PW(uint16 A, uint16 V) { - uint8 mode = (reg & 0x08) >> 3; - - setprg16(0x8000, ((reg & 0x0F) & ~mode)); - setprg16(0xC000, ((reg & 0x0F) | mode)); -} - -static DECLFW(M259Write) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - } -} - -static void M259Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M259Write); -} - -void Mapper259_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M259PW; - info->Power = M259Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper260.c b/src/mappers/mapper260.c deleted file mode 100644 index e0f221c1e..000000000 --- a/src/mappers/mapper260.c +++ /dev/null @@ -1,119 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2017 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -/* added on 2019-5-23 - NES 2.0 Mapper 260 - * HP10xx/HP20xx - a simplified version of FK23C mapper with pretty strict and better - * organized banking behaviour. It seems that some 176 mapper assigned game may be - * actually this kind of board instead but in common they aren't compatible at all, - * the games on the regular FK23C boards couldn't run on this mapper and vice versa... - */ - -static uint8 reg[4]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M260CW(uint16 A, uint16 V) { - uint16 base = reg[2] & 0x7F; - - switch (reg[0] & 0x07) { - case 0: setchr1(A, ((base << 3) & ~0xFF) | (V & 0xFF)); break; - case 1: setchr1(A, ((base << 3) & ~0x7F) | (V & 0x7F)); break; - case 2: setchr1(A, ((base << 3) & ~0xFF) | (V & 0xFF)); break; - case 3: setchr1(A, ((base << 3) & ~0x7F) | (V & 0x7F)); break; - case 4: setchr8(base); break; - case 5: setchr8(base); break; - case 6: setchr8((base & ~0x01) | (reg[3] & 0x01)); break; - case 7: setchr8((base & ~0x03) | (reg[3] & 0x03)); break; - } -} - -static void M260PW(uint16 A, uint16 V) { - uint8 base = reg[1] & 0x3F; - - switch (reg[0] & 0x07) { - case 0: setprg8(A, ((base << 1) & ~0x1F) | (V & 0x1F)); break; - case 1: setprg8(A, ((base << 1) & ~0x1F) | (V & 0x1F)); break; - case 2: setprg8(A, ((base << 1) & ~0x0F) | (V & 0x0F)); break; - case 3: setprg8(A, ((base << 1) & ~0x0F) | (V & 0x0F)); break; - case 4: - setprg16(0x8000, base); - setprg16(0xC000, base); - break; - case 5: setprg32(0x8000, base >> 1); break; - case 6: setprg32(0x8000, base >> 1); break; - case 7: setprg32(0x8000, base >> 1); break; - } -} - -static DECLFR(M260Read) { - return ((CPU_OPENBUS & ~0x03) | (dipsw & 0x03)); -} - -static DECLFW(M260WriteReg) { - if (!(reg[0] & 0x80)) { - reg[A & 0x03] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static DECLFW(M260WriteLatch) { - if((reg[0] & 0xE6) == 0x06 ) { - reg[3] = V; - MMC3_FixCHR(); - } else { - MMC3_Write(A, V); - } -} - -static void M260Reset(void) { - dipsw++; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Reset(); - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M260Power(void) { - dipsw = 0; - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Power(); - SetReadHandler(0x5000, 0x5FFF, M260Read); - SetWriteHandler(0x5000, 0x5FFF, M260WriteReg); - SetWriteHandler(0x8000, 0xFFFF, M260WriteLatch); -} - -void Mapper260_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M260CW; - MMC3_pwrap = M260PW; - info->Power = M260Power; - info->Reset = M260Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper261.c b/src/mappers/mapper261.c deleted file mode 100644 index 589741dc8..000000000 --- a/src/mappers/mapper261.c +++ /dev/null @@ -1,40 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 261 - BMC810544-C-A1 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x40) - setprg32(0x8000, latch.addr >> 7); - else { - setprg16(0x8000, ((latch.addr >> 6) & 0x0E) | ((latch.addr >> 5) & 0x01)); - setprg16(0xC000, ((latch.addr >> 6) & 0x0E) | ((latch.addr >> 5) & 0x01)); - } - setchr8(latch.addr & 0x0F); - setmirror(((latch.addr >> 4) & 0x01) ^ 0x01); -} - -void Mapper261_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper262.c b/src/mappers/mapper262.c deleted file mode 100644 index be94d5c34..000000000 --- a/src/mappers/mapper262.c +++ /dev/null @@ -1,89 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 262 - UNL-SHERO */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M262CW(uint16 A, uint16 V) { - if (reg & 0x40) { - setchr8r(0x10, 0); - } else { - uint8 lsh[] = { 3, 2, 0, 1 }; - uint8 bank = (A >> 11) & 0x03; - - setchr1(A, (((reg >> lsh[bank]) << 8) & 0x100) | (V & 0xFF)); - } -} - -static DECLFW(M262Write) { - if (A & 0x100) { - reg = V; - MMC3_FixCHR(); - } -} - -static DECLFR(M262Read) { - if (A & 0x100) { - return(dipsw); - } - return CPU_OPENBUS; -} - -static void M262Reset(void) { - MMC3_Reset(); - dipsw ^= 0xFF; -} - -static void M262Power(void) { - dipsw = 0x00; - MMC3_Power(); - SetWriteHandler(0x4100, 0x4FFF, M262Write); - SetReadHandler(0x4100, 0x4FFF, M262Read); -} - -static void M262Close(void) { - MMC3_Close(); -} - -void Mapper262_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M262CW; - info->Power = M262Power; - info->Reset = M262Reset; - info->Close = M262Close; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper263.c b/src/mappers/mapper263.c deleted file mode 100644 index 053033b95..000000000 --- a/src/mappers/mapper263.c +++ /dev/null @@ -1,47 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 263 - UNL-KOF97 */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint32 unscrambleAddr(uint32 A) { - return ((A & 0xE000) | ((A >> 12) & 0x01)); -} - -static uint8 unscrambleData(uint8 V) { - return ((V & 0xD8) | ((V & 0x20) >> 4) | ((V & 0x04) << 3) | ((V & 0x02) >> 1) | ((V & 0x01) << 2)); -} - -static DECLFW(M263Write) { - MMC3_Write(unscrambleAddr(A), unscrambleData(V)); -} - -static void M263Power(void) { - MMC3_Power(); - SetWriteHandler(0x8000, 0xFFFF, M263Write); -} - -void Mapper263_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - info->Power = M263Power; -} diff --git a/src/mappers/mapper265.c b/src/mappers/mapper265.c deleted file mode 100644 index c8188af0c..000000000 --- a/src/mappers/mapper265.c +++ /dev/null @@ -1,65 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 265 - BMC-T-262 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 bank = ((latch.addr >> 3) & 0x60) | ((latch.addr >> 2) & 0x18) | (latch.data & 0x07); - - if (latch.addr & 0x80) { - if (!bank) { - /* NOTE: Unofficial support but Tetris II in 11-in-1 variant - works as if its NROM-256 */ - setprg32(0x8000, bank >> 1); - } else { - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } else { - setprg16(0x8000, bank); - setprg16(0xC000, bank | 0x07); - } - setchr8(0); - setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); -} - -static DECLFW(M265Write) { - if (!(latch.addr & 0x2000)) { - latch.addr = A; - } - latch.data = V; - Sync(); -} - -static void M265Power(void) { - Latch_Power(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M265Write); -} - -void Mapper265_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M265Power; - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper266.c b/src/mappers/mapper266.c deleted file mode 100644 index 481b78392..000000000 --- a/src/mappers/mapper266.c +++ /dev/null @@ -1,67 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * City Fighter IV sith Sound VRC4 hacked - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 reg; -static writefunc pcm; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M266PW(uint16 A, uint16 V) { - setprg32(0x8000, reg >> 2); -} - -static DECLFW(M266Write) { - /* FCEU_printf("%04x %02x",A,V); */ - A = (A & 0x9FFF) | ((A << 1) & 0x4000) | ((A >> 1) & 0x2000); - VRC24_Write(A, V); -} - -static void M266WriteMisc(uint16 A, uint8 V) { - if (A & 0x800) { - pcm(0x4011, (V & 0x0F) << 3); - } else { - reg = V & 0x0C; - VRC24_FixPRG(); - } -} - -static void M266Power(void) { - reg = 0; - VRC24_Power(); - pcm = GetWriteHandler(0x4011); - SetWriteHandler(0x8000, 0xFFFF, M266Write); -} - -void Mapper266_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x04, 0x08, FALSE, TRUE); - info->Power = M266Power; - VRC24_pwrap = M266PW; - VRC24_miscWrite = M266WriteMisc; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper267.c b/src/mappers/mapper267.c deleted file mode 100644 index 8facccc71..000000000 --- a/src/mappers/mapper267.c +++ /dev/null @@ -1,69 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 267 - 8-in-1 JY-119 */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M267CW(uint16 A, uint16 V) { - uint16 base = ((reg & 0x20) >> 2) | (reg & 0x06); - - setchr1(A, (base << 6) | (V & 0x7F)); -} - -static void M267PW(uint16 A, uint16 V) { - uint16 base = ((reg & 0x20) >> 2) | (reg & 0x06); - - setprg8(A, (base << 4) | (V & 0x1F)); -} - -static DECLFW(M267Write) { - if (MMC3_WramIsWritable()) { - if (!(reg & 0x80)) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } - } -} - -static void M267Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M267Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x6FFF, M267Write); -} - -void Mapper267_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M267CW; - MMC3_pwrap = M267PW; - info->Reset = M267Reset; - info->Power = M267Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper268.c b/src/mappers/mapper268.c deleted file mode 100644 index 5020bcb32..000000000 --- a/src/mappers/mapper268.c +++ /dev/null @@ -1,210 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[8]; - -static void M268CW(uint16 A, uint16 V) { - uint16 base = ((reg[0] << 4) & 0x380) | ((reg[2] << 3) & 0x078); - uint16 mask = (reg[0] & 0x80) ? 0x7F : 0xFF; - uint8 vram = CHRRAM && (reg[4] & 0x01) && ((V & 0xFE) == (reg[4] & 0xFE)); - - /* CHR-RAM write protect on submapper 8/9) */ - if ((iNESCart.submapper & ~1) == 8) { - if (reg[0] & 0x10) { - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 1); - } else { - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], 0); - } - } - - if (reg[3] & 0x10) { - /* GNROM */ - mask = 0x07; - V = A >> 10; - } - setchr1r(vram ? 0x10 : 0x00, A, (base & ~mask) | (V & mask)); -} - -static void M268PW(uint16 A, uint16 V) { - uint16 base; - uint16 mask = 0x0F /* PRG A13-A16 */ - | ((~reg[0] >> 2) & 0x10) /* PRG A17 */ - | ((~reg[1] >> 2) & 0x20) /* PRG A18 */ - | ((reg[1] >> 0) & 0x40) /* PRG A19 */ - | ((reg[1] << 2) & 0x80) /* PRG A20 */ - ; - - switch (iNESCart.submapper & ~1) { - default: /* Original implementation */ - base = (reg[3] & 0x0E) | ((reg[0] << 4) & 0x70) | ((reg[1] << 3) & 0x80) | - ((reg[1] << 6) & 0x300) | ((reg[0] << 6) & 0xC00); - break; - case 2: /* Later revision with different arrangement of register 1 */ - base = (reg[3] & 0x0E) | ((reg[0] << 4) & 0x70) | ((reg[1] << 4) & 0x80) | - ((reg[1] << 6) & 0x100) | ((reg[1] << 8) & 0x200) | ((reg[0] << 6) & 0xC00); - break; - case 4: /* LD622D: PRG A20-21 moved to register 0 */ - base = (reg[3] & 0x0E) | ((reg[0] << 4) & 0x70) | ((reg[0] << 3) & 0x180); - break; - case 6: /* J-852C: CHR A17 selects between two PRG chips */ - base = (reg[3] & 0x0E) | ((reg[0] << 4) & 0x70) | ((reg[1] << 3) & 0x80) | - ((reg[1] << 6) & 0x300) | ((reg[0] << 6) & 0xC00); - base &= PRG_BANK_COUNT(16) - 1; - if ((reg[0] & 0x80) ? !!(reg[0] & 0x08) : !!(mmc3.reg[0] & 0x80)) { - base |= PRG_BANK_COUNT(16); - } - break; - } - if (reg[3] & 0x10) { - /* GNROM */ - switch (iNESCart.submapper & ~1) { - default: mask = (reg[1] & 0x02) ? 0x03 : 0x01; break; - case 2: mask = (reg[1] & 0x10) ? 0x01 : 0x03; break; - } - V = A >> 13; - } - setprg8(A, (base & ~mask) | (V & mask)); - - if (mmc3.wram & 0x20) { - /* Hack for FS005 games on Mindkids board that only work with emulation. */ - mmc3.wram &= ~0x40; - } -} - -static void M268MIR(void) { - if (!(reg[0] & 0x20)) { - switch (iNESCart.submapper) { - case 10: - case 11: - setmirror(MI_0 + ((reg[0] >> 4) & 0x01)); - break; - default: - setmirror((mmc3.mirr & 0x01) ^ 0x01); - break; - } - } else { - setmirror((mmc3.mirr & 0x01) ^ 0x01); - } -} - -static DECLFR(M268WramRead) { - if (mmc3.wram & 0x80) { - return CartBR(A); - } - return CPU_OPENBUS; -} - -static DECLFW(M268WramWrite) { - if (MMC3_WramIsWritable()) { - CartBW(A, V); - } -} - -static DECLFW(M268Write) { - uint8 index = A & 0x07; - - if (!(iNESCart.submapper & 0x01) && (A >= 0x6000)) { - M268WramWrite(A, V); - } - - if (!(reg[3] & 0x80) || (index == 2)) { - if (index == 2) { - if (reg[2] & 0x80) { - V = (V & 0x0F) | (reg[2] & ~0x0F); - } - V &= 0xF1 | ((~reg[2] >> 3) & 0x0E); - } - reg[index] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } -} - -static void M268Reset(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0x00; - reg[4] = reg[5] = reg[6] = reg[7] = 0x00; - MMC3_Reset(); -} - -static void M268Power(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0x00; - reg[4] = reg[5] = reg[6] = reg[7] = 0x00; - MMC3_Power(); - SetReadHandler(0x6000, 0x7FFF, M268WramRead); - SetWriteHandler(0x6000, 0x7FFF, M268WramWrite); - if (iNESCart.mapper == 224 || (iNESCart.submapper & 0x01)) { - SetWriteHandler(0x5000, 0x5FFF, M268Write); - } else { - SetWriteHandler(0x6000, 0x7FFF, M268Write); - } -} - -static void M268Close(void) { - MMC3_Close(); -} - -static void Common_Init(CartInfo *info) { - int ws = info->PRGRamSize + info->PRGRamSaveSize; - - MMC3_Init(info, ws / 1024, info->battery); - MMC3_FixMIR = M268MIR; - MMC3_pwrap = M268PW; - MMC3_cwrap = M268CW; - - info->Power = M268Power; - info->Reset = M268Reset; - info->Close = M268Close; - - AddExState(reg, 8, 0, "EXPR"); - - if (CHR_ROM_SIZE) { - CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; - if (CHRRAMSIZE) { - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0x00, "CRAM"); - } - } -} - -void Mapper268_Init(CartInfo *info) { - Common_Init(info); -} - -/* UNIF loader */ - -void COOLBOY_Init(CartInfo *info) { - info->mapper = 268; - info->submapper = 0; - info->PRGRamSize = 8192; - Common_Init(info); -} - -void MINDKIDS_Init(CartInfo *info) { /* M224 */ - info->mapper = 224; - info->submapper = 1; - info->PRGRamSize = 8192; - Common_Init(info); -} - diff --git a/src/mappers/mapper269.c b/src/mappers/mapper269.c deleted file mode 100644 index ddd344358..000000000 --- a/src/mappers/mapper269.c +++ /dev/null @@ -1,95 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 269 - * Games Xplosion 121-in-1 - * 15000-in-1 - * 18000-in-1 - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; -static uint8 cmd; - -static void M269CW(uint16 A, uint16 V) { - uint16 mask = 0xFF >> (~reg[2] & 0xF); - uint16 base = ((reg[3] << 6) & 0x1000) | ((reg[2] << 4) & 0xF00) | reg[0]; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M269PW(uint16 A, uint16 V) { - uint16 mask = ~reg[3] & 0x3F; - uint16 base = ((reg[3] << 2) & 0x100) | reg[1]; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M269Write5) { - if (!(reg[3] & 0x80)) { - reg[cmd] = V; - cmd = (cmd + 1) & 3; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M269Reset(void) { - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - MMC3_Reset(); -} - -static void M269Power(void) { - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - MMC3_Power(); - SetWriteHandler(0x5000, 0x5FFF, M269Write5); -} - -static uint8 unscrambleCHR(uint8 data) { - return ((data & 0x01) << 6) | ((data & 0x02) << 3) | ((data & 0x04) << 0) | ((data & 0x08) >> 3) | - ((data & 0x10) >> 3) | ((data & 0x20) >> 2) | ((data & 0x40) >> 1) | ((data & 0x80) << 0); -} - -void Mapper269_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_cwrap = M269CW; - MMC3_pwrap = M269PW; - info->Power = M269Power; - info->Reset = M269Reset; - AddExState(reg, 4, 0, "EXPR"); - AddExState(&cmd, 1, 0, "CMD0"); - - if (CHR_ROM_SIZE == 0) { - size_t i; - if (CHR_ROM_PTR) { - FCEU_free(CHR_ROM_PTR); - } - CHR_ROM_PTR = (uint8*)FCEU_malloc(PRGsize[0]); - /* unscramble CHR data from PRG */ - for (i = 0; i < PRGsize[0]; i++) { - CHR_ROM_PTR[i] = unscrambleCHR(PRG_ROM_PTR[i]); - } - SetupCartCHRMapping(0, CHR_ROM_PTR, PRGsize[0], 0); - } -} diff --git a/src/mappers/mapper271.c b/src/mappers/mapper271.c deleted file mode 100644 index 2b3448409..000000000 --- a/src/mappers/mapper271.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.data >> 4); - setchr8(latch.data & 0x0F); - setmirror((latch.data >> 5) & 0x01); -} - -void Mapper271_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper272.c b/src/mappers/mapper272.c deleted file mode 100644 index ec35536a6..000000000 --- a/src/mappers/mapper272.c +++ /dev/null @@ -1,162 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 272 is used for a bootleg implementation of - * 悪魔城 Special: ぼくDracula君 (Akumajō Special: Boku Dracula-kun). - * - * as implemented from - * https://forums.nesdev.org/viewtopic.php?f=9&t=15302&start=60#p205862 - * - */ - -#include "mapinc.h" - -static uint8 prg[2]; -static uint8 chr[8]; -static uint8 mirr; -static uint8 pal_mirr; -static uint8 IRQCount; -static uint8 IRQa; - -static uint16 lastAddr; - -static SFORMAT StateRegs[] = { - { prg, 2, "PREG" }, - { chr, 8, "CREG" }, - { &mirr, 1, "MIRR" }, - { &pal_mirr, 1, "PALM" }, - { &IRQCount, 1, "CNTR" }, - { &IRQa, 1, "CCLK" }, - { &lastAddr, 2, "LADR" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg16(0xC000, ~0); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - if (pal_mirr & 0x02) { - setmirror(MI_0 + (pal_mirr & 0x01)); - } else { - setmirror((mirr & 0x01) ^ 0x01); - } -} - -static DECLFW(M272Write) { - /* writes to VRC chip */ - switch (A & 0xF000) { - case 0x8000: - prg[0] = V; - break; - case 0x9000: - mirr = V; - break; - case 0xA000: - prg[1] = V; - break; - case 0xB000: - case 0xC000: - case 0xD000: - case 0xE000: { - int bank = (((A - 0xB000) >> 11) & 0x06) | ((A >> 1) & 0x01); - if (A & 0x01) { - chr[bank] = (chr[bank] & ~0xF0) | (V << 4); - } else { - chr[bank] = (chr[bank] & ~0x0F) | (V & 0x0F); - } - break; - } - } - - /* writes to PAL chip */ - switch (A & 0xC00C) { - case 0x8004: - pal_mirr = V; - break; - case 0x800c: - X6502_IRQBegin(FCEU_IQEXT); - break; - case 0xc004: - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xc008: - IRQa = 1; - break; - case 0xc00c: - IRQa = 0; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - } - - Sync(); -} - -static void M272Reset(void) { - prg[0] = prg[1] = 0; - chr[0] = chr[1] = chr[2] = chr[3] = 0; - chr[4] = chr[5] = chr[6] = chr[7] = 0; - mirr = pal_mirr = 0; - lastAddr = 0; - IRQCount = 0; - IRQa = 0; - Sync(); -} - -static void M272Power(void) { - M272Reset(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M272Write); -} - -static void M272Hook(uint32 A) { - if ((lastAddr & 0x2000) && !(A & 0x2000)) { - if (IRQa) { - IRQCount++; - if (IRQCount == 84) { - IRQCount = 0; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } - lastAddr = A; -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper272_Init(CartInfo *info) { - info->Power = M272Power; - info->Reset = M272Reset; - PPU_hook = M272Hook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper274.c b/src/mappers/mapper274.c deleted file mode 100644 index 3370825d7..000000000 --- a/src/mappers/mapper274.c +++ /dev/null @@ -1,84 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 274 is used for the 90-in-1 Hwang Shinwei multicart. - * Its UNIF board name is BMC-80013-B. - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_274 */ - - /* 2020-03-22 - Update support for Cave Story II, FIXME: Arabian does not work for some reasons... */ - -#include "mapinc.h" - -static uint8 reg[2], extraChip; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &extraChip, 1, "CHIP" }, - { 0 } -}; - -static void Sync(void) { - if (extraChip) { - setprg16(0x8000, 0x80 | (reg[0] & ((PRG_BANK_COUNT(16) - 1) & 0x0F))); - } else { - setprg16(0x8000, (reg[1] & 0x70) | (reg[0] & 0x0F)); - } - setprg16(0xC000, reg[1] & 0x7F); - setchr8(0); - setmirror(((reg[0] >> 4) & 0x01) ^ 0x01); -} - -static DECLFW(M274Write8) { - reg[0] = V; - Sync(); -} - -static DECLFW(M274WriteA) { - reg[1] = V; - extraChip = (A & 0x4000) == 0; - Sync(); -} - -static void M274Power(void) { - reg[0] = reg[1] = 0; - extraChip = 1; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0x9FFF, M274Write8); - SetWriteHandler(0xA000, 0xFFFF, M274WriteA); -} - -static void M274Reset(void) { - reg[0] = reg[1] = 0; - extraChip = 1; - Sync(); -} - -static void M274Restore(int version) { - Sync(); -} - -void Mapper274_Init(CartInfo *info) { - info->Power = M274Power; - info->Reset = M274Reset; - GameStateRestore = M274Restore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper277.c b/src/mappers/mapper277.c deleted file mode 100644 index a76640c9a..000000000 --- a/src/mappers/mapper277.c +++ /dev/null @@ -1,67 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = latch.data & 0x0F; - - if (latch.data & 0x08) { - if (latch.data & 0x01) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { - setprg32(0x8000, prg >> 1); - } - } else { - setprg16(0x8000, prg); - setprg16(0xC000, prg | 0x07); - } - setchr8(0); - setmirror(((latch.data >> 4) & 0x01) ^ 0x01); -} - -static DECLFW(M277Write) { - if (!(latch.data & 0x20)) { - Latch_Write(A, V); - } -} - -static void M277Power(void) { - latch.addr = 0; - latch.data = 8; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBROB); - SetWriteHandler(0x8000, 0xFFFF, M277Write); -} - -static void M277Reset(void) { - latch.addr = 0; - latch.data = 8; - Sync(); -} - -void Mapper277_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M277Power; - info->Reset = M277Reset; -} diff --git a/src/mappers/mapper281.c b/src/mappers/mapper281.c deleted file mode 100644 index ac59ebda1..000000000 --- a/src/mappers/mapper281.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -static uint32 GetPRGBank(uint32 V) { - return ((jyasic.mode[3] << 5) | (V & 0x1F)); -} - -static uint32 GetCHRBank(uint32 V) { - return ((jyasic.mode[3] << 8) | (V & 0xFF)); -} - -void Mapper281_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} diff --git a/src/mappers/mapper282.c b/src/mappers/mapper282.c deleted file mode 100644 index 11e02019e..000000000 --- a/src/mappers/mapper282.c +++ /dev/null @@ -1,41 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -static uint32 GetPRGBank(uint32 V) { - return (((jyasic.mode[3] << 4) & ~0x1F) | (V & 0x1F)); -} - -static uint32 GetCHRBank(uint32 V) { - if (jyasic.mode[3] & 0x20) { - return (((jyasic.mode[3] << 6) & 0x600) | (V & 0x1FF)); - } else { - return (((jyasic.mode[3] << 6) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0xFF)); - } -} - -void Mapper282_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} diff --git a/src/mappers/mapper283.c b/src/mappers/mapper283.c deleted file mode 100644 index 9e8c02eb3..000000000 --- a/src/mappers/mapper283.c +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg8(0x6000, (PRG_ROM_SIZE & 0x6000) ? 32 : 31); - setprg32(0x8000, latch.data); - setchr8(0); -} - -void Mapper283_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, FALSE); -} diff --git a/src/mappers/mapper284.c b/src/mappers/mapper284.c deleted file mode 100644 index df78ad89e..000000000 --- a/src/mappers/mapper284.c +++ /dev/null @@ -1,228 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* FIXME: - * The extender nametable mirroring only works in NEWPPU. -*/ - -#include "mapinc.h" -#include "dripsound.h" - -static uint8 extattrib[2][1024]; -static uint8 jumper; -static uint8 control; -static uint8 prg; -static uint8 chr[4]; -static uint8 IRQa; -static uint8 IRQLatch; -static int16 IRQCount; -static uint16 lastAddr; - -static uint8 DRIPHack = FALSE; - -static SFORMAT StateRegs[] = { - { &jumper, 1, "JUMP" }, - { &control, 1, "CTRL" }, - { &prg, 1, "PREG" }, - { chr, 4, "CREG" }, - { &IRQa, 1, "IRQA" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQCount, 2, "IRQC" }, - { &lastAddr, 2, "LADD" }, - { 0 } -}; - -static uint8 Sync(void) { - if (control & 0x08) { - setprg8r(0x10, 0x6000, 0); - } - - setprg16(0x8000, prg); - setprg16(0xC000, 0x0F); - - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr2(0x1000, chr[2]); - setchr2(0x1800, chr[3]); - - switch (control & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -static DECLFW(M284Write) { - switch (A & 0xE000) { - case 0x8000: - case 0xA000: - switch (A & 0x0F) { - case 0x0: - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: - DRIPSound_Write(A, V); - break; - case 0x8: - IRQLatch = V; - break; - case 0x9: - IRQCount = ((V & 0x7F) << 8) | IRQLatch; - IRQa = V & 0x80; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xA: - control = V & 0x0F; - Sync(); - break; - case 0xB: - prg = V & 0x0F; - Sync(); - break; - case 0xC: - case 0xD: - case 0xE: - case 0xF: - chr[A & 0x03] = V & 0x0F; - Sync(); - break; - } - break; - case 0xC000: - case 0xE000: - extattrib[(A & 0x400) >> 10][A & 0x3FF] = V & 0x03; - break; - } -} - -static DECLFR(M284Read) { - switch (A & 0xF800) { - case 0x4800: - return (jumper | 'd'); - case 0x5000: - case 0x5800: - return DRIPSound_Read(A); - } - return CartBR(A); -} - -#ifdef NEWPPU -uint8 M284PPURead(uint32 A) { - if ((A > 0x2000) && (A < 0x3F00)) { - if (control & 0x04) { - if ((A & 0x3FF) < 0x3C0) { - lastAddr = A & 0x3FF; - } else { - const uint8 ext_attrib[4] = { 0x00, 0x55, 0xAA, 0xFF }; - uint8 bank = 0; - - A &= 0x0FFF; - - switch (iNESCart.mirror) { - default: - case MI_0: bank = 0; break; - case MI_1: bank = 1; break; - case MI_V: bank = (A & 0x800) ? 1 : 0; break; - case MI_H: bank = (A & 0x400) ? 1 : 0; break; - } - return (ext_attrib[(extattrib[bank][lastAddr & 0x3FF]) & 0x03]); - } - } - } - return FFCEUX_PPURead_Default(A); -} -#endif - -static void M284Reset(void) { - control = 0; - prg = 0; - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - memset(&extattrib[0][0], 0x00, sizeof(extattrib)); - jumper = !jumper ? 0x80 : 0; - - Sync(); -} - -static void M284Power(void) { - control = 0; - prg = 0; - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - memset(&extattrib[0][0], 0x00, sizeof(extattrib)); - - jumper = 0; - - Sync(); - - SetReadHandler(0x4800, 0x5FFF, M284Read); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, M284Write); - -#ifdef NEWPPU - FFCEUX_PPURead = M284PPURead; -#endif -} - -static void M284CPUIRQHook(int a) { - if (IRQa) { - IRQCount -= a; - if (IRQCount <= 0) { - IRQa = FALSE; - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper284_Init(CartInfo *info) { - info->Power = M284Power; - MapIRQHook = M284CPUIRQHook; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - AddExState(extattrib[0], 1024, 0, "ATT0"); - AddExState(extattrib[1], 1024, 0, "ATT1"); - - WRAMSIZE = 8192; - WRAM = FCEU_malloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - DRIPSound_ESI(); - DRIPSound_AddStateInfo(); - - DRIPHack = TRUE; - - FCEU_printf(" DRIPGAME Mapper warning: Set video to use NEWPPU for game to work properly.\n"); -} diff --git a/src/mappers/mapper285.c b/src/mappers/mapper285.c deleted file mode 100644 index 8cb88fe63..000000000 --- a/src/mappers/mapper285.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Mapper 285 - A65AS */ -/* actually, there is two cart in one... First have extra mirroring - * mode (one screen) and 32K bankswitching, second one have only - * 16 bankswitching mode and normal mirroring... But there is no any - * correlations between modes and they can be used in one mapper code. - * - * Submapper 0 - 3-in-1 (N068) - * Submapper 0 - 3-in-1 (N080) - * Submapper 1 - 4-in-1 (JY-066) - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.data & 0x40) { - setprg32(0x8000, (latch.data >> 1) & 0x0F); - } else { - if (iNESCart.submapper == 1) { - setprg16(0x8000, ((latch.data & 0x30) >> 1) | (latch.data & 0x07)); - setprg16(0xC000, ((latch.data & 0x30) >> 1) | 0x07); - } else { - setprg16(0x8000, latch.data & 0x0F); - setprg16(0xC000, (latch.data & 0x0F) | 0x07); - } - } - setchr8(0); - if (latch.data & 0x80) { - setmirror(MI_0 + (((latch.data >> 5) & 0x01))); - } else { - setmirror(((latch.data >> 3) & 0x01) ^ 0x01); - } -} - -void Mapper285_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper286.c b/src/mappers/mapper286.c deleted file mode 100644 index e5bd861d2..000000000 --- a/src/mappers/mapper286.c +++ /dev/null @@ -1,98 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[4]; -static uint8 chr[4]; -static uint8 mirr; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 4, "CREG" }, - { &mirr, 1, "MIRR" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0]); - setprg8(0xa000, prg[1]); - setprg8(0xc000, prg[2]); - setprg8(0xe000, prg[3]); - - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr2(0x1000, chr[2]); - setchr2(0x1800, chr[3]); - - setmirror((mirr & 0x01) ^ 0x01); -} - -static DECLFW(M286Write) { - switch (A & 0xF000) { - case 0x8000: - case 0x9000: - chr[(A & 0xC00) >> 10] = A & 0x1F; - Sync(); - break; - case 0xA000: - case 0xB000: - if (A & (1 << (dipsw + 4))) { - prg[(A & 0xC00) >> 10] = A & 0x0F; - Sync(); - } - break; - case 0xC000: - mirr = V; - Sync(); - break; - } -} - -static void M286Reset(void) { - dipsw++; - dipsw &= 3; - prg[0] = prg[1] = prg[2] = prg[3] = ~0; - mirr = 0; - Sync(); -} - -static void M286Power(void) { - dipsw = 0; - prg[0] = prg[1] = prg[2] = prg[3] = ~0; - mirr = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M286Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper286_Init(CartInfo *info) { - info->Power = M286Power; - info->Reset = M286Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper287.c b/src/mappers/mapper287.c deleted file mode 100644 index 4e84a63ba..000000000 --- a/src/mappers/mapper287.c +++ /dev/null @@ -1,98 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2008 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 287 - * BMC-411120-C, actually cart ID is 811120-C, sorry ;) K-3094 - another ID - * - 4-in-1 (411120-C) - * - 4-in-1 (811120-C,411120-C) [p4][U] - * - * BMC-K-3088, similar to BMC-411120-C but without jumper or dipswitch - * - 19-in-1(K-3088)(810849-C)(Unl) - */ - -/* 2023-03-02 - - use PRG size to determine variant - - remove forced mask for outer-bank (rely on internal mask set during PRG/CHR mapping) - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M287CW(uint16 A, uint16 V) { - uint16 base = reg & 0x07; - - setchr1(A, (base << 7) | (V & 0x7F)); -} - -static void M287PW(uint16 A, uint16 V) { - uint16 mode = reg & ((dipsw && (PRG_ROM_SIZE <= (512 * 1024))) ? 0x0C : 0x08); - uint16 base = reg & 0x07; - - if (mode) { - /* 32K Mode */ - setprg32(0x8000, (base << 2) | ((reg >> 4) & 0x03)); - /* FCEU_printf("32K mode: bank:%02x\n", ((reg >> 4) & 3) | ((reg & 7) << 2)); */ - } else { - /* MMC3 Mode */ - setprg8(A, (base << 4) | (V & 0x0F)); - /* FCEU_printf("MMC3: %04x:%02x\n", A, (V & 0x0F) | ((reg & 7) << 4)); */ - } -} - -static DECLFW(M287WriteReg) { - /* printf("Wr: A:%04x V:%02x\n", A, V); */ - if (MMC3_WramIsWritable()) { - reg = A; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M287Reset(void) { - reg = 0; - dipsw ^= 4; - MMC3_Reset(); -} - -static void M287Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M287WriteReg); -} - -void Mapper287_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M287PW; - MMC3_cwrap = M287CW; - info->Power = M287Power; - info->Reset = M287Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper288.c b/src/mappers/mapper288.c deleted file mode 100644 index b32ab63f0..000000000 --- a/src/mappers/mapper288.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 288 is used for two GKCX1 21-in-1 multicarts - * - 21-in-1 (GA-003) - * - 64-in-1 (CF-015) - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static void Sync(void) { - setprg32(0x8000, latch.addr >> 3); - setchr8(latch.addr); - setmirror(((latch.addr >> 5) & 0x01) ^ 0x01); -} - -static DECLFR(M288Read) { - uint8 ret = CartBR(A); - if (latch.addr & 0x20) { - return CartBR(A | (dipsw & 0x0F)); - } - return ret; -} - -static void M288Reset(void) { - dipsw++; - Sync(); -} - -void Mapper288_Init(CartInfo *info) { - Latch_Init(info, Sync, M288Read, FALSE, FALSE); - info->Reset = M288Reset; - AddExState(&dipsw, 1, 0, "DIPSW"); -} diff --git a/src/mappers/mapper289.c b/src/mappers/mapper289.c deleted file mode 100644 index 48d2cac83..000000000 --- a/src/mappers/mapper289.c +++ /dev/null @@ -1,81 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright (C) 2019 Libretro Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* added 2019-5-23 - * UNIF: BMC-60311C: - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_289 - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[2]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - uint32 bank = reg[1] & 0x7F; - - if (reg[0] & 0x02) { - setprg16(0x8000, (bank & ~0x07) | ((reg[0] & 0x01) ? 0x07 : (latch.data & 0x07))); - setprg16(0xC000, bank | 0x07); - } else { - setprg16(0x8000, bank & ~(reg[0] & 0x01)); - setprg16(0xC000, bank | (reg[0] & 0x01)); - } - /* CHR-RAM write-protect */ - SetupCartCHRMapping(0, CHRptr[0], 0x2000, ((reg[0] >> 2) & 0x01) ^ 0x01); - setchr8(0); - setmirror(((reg[0] >> 3) & 0x01) ^ 0x01); -} - -static DECLFR(M289Read) { - return (CPU_OPENBUS & ~0x03) | (dipsw & 0x03); -} - -static DECLFW(M289Write) { - reg[A & 0x01] = V; - Sync(); -} - -static void M289Power(void) { - dipsw = 0; - reg[0] = reg[1] = 0; - Latch_Power(); - SetReadHandler(0x6000, 0x7FFF, M289Read); - SetWriteHandler(0x6000, 0x7FFF, M289Write); -} - -static void M289Reset(void) { - dipsw++; - reg[0] = reg[1] = 0; - Latch_RegReset(); -} - -void Mapper289_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M289Power; - info->Reset = M289Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper290.c b/src/mappers/mapper290.c deleted file mode 100644 index b51d63ba8..000000000 --- a/src/mappers/mapper290.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 290 - BMC-NTD-03 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint32 prg = ((latch.addr >> 10) & 0x1E) | ((latch.addr >> 6) & 0x01); - uint32 chr = ((latch.addr >> 5) & 0x18) | (latch.addr & 0x07); - - if (latch.addr & 0x80) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { - setprg32(0x8000, prg >> 1); - } - setchr8(chr); - setmirror(((latch.addr >> 10) & 0x01) ^ 0x01); -} - -void Mapper290_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper291.c b/src/mappers/mapper291.c deleted file mode 100644 index 4a4aeb45c..000000000 --- a/src/mappers/mapper291.c +++ /dev/null @@ -1,68 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M291CW(uint16 A, uint16 V) { - setchr1(A, ((reg << 2) & 0x100) | (V & 0xFF)); -} - -static void M291PW(uint16 A, uint16 V) { - if (reg & 0x20) { - setprg32(0x8000, ((reg >> 4) & 0x04) | ((reg >> 1) & 0x03)); - } else { - setprg8(A, ((reg >> 2) & 0x10) | (V & 0x0F)); - } -} - -static DECLFW(M291Write) { - /* The Outer Bank Register responds even when the MMC3 clone's WRAM bit is clear. */ - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M291Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M291Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M291Write); -} - -void Mapper291_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M291CW; - MMC3_pwrap = M291PW; - info->Power = M291Power; - info->Reset = M291Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper292.c b/src/mappers/mapper292.c deleted file mode 100644 index 5b30dd803..000000000 --- a/src/mappers/mapper292.c +++ /dev/null @@ -1,80 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2015 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 292 - PCB BMW8544 - * UNIF UNL-DRAGONFIGHTER - * "Dragon Fighter" protected MMC3 based custom mapper board - * mostly hacky implementation, I can't verify if this mapper can read a RAM of the - * console or watches the bus writes somehow. - * - * TODO: needs updating - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[3]; - -static SFORMAT StateRegs[] = { - { reg, 3, "REGS" }, - { 0 } -}; - -static void M292PW(uint16 A, uint16 V) { - setprg8(A, V); - setprg8(0x8000, reg[0] & 0x1F); -} - -static void M292CW(uint16 A, uint16 V) { - setchr2(0x0000, (mmc3.reg[0] >> 1) ^ reg[1]); - setchr2(0x0800, (mmc3.reg[1] >> 1) ^ ((reg[2] & 0x40) << 1)); - setchr4(0x1000, reg[2] & 0x3F); -} - -static DECLFW(M292ProtWrite) { - reg[0] = V; - MMC3_FixPRG(); -} - -static DECLFR(M292ProtRead) { - if ((reg[0] & 0xE0) == 0xC0) { - reg[1] = ARead[0x6A](0x6A); - } else { - reg[2] = ARead[0xFF](0xFF); - } - MMC3_FixCHR(); - return CPU_OPENBUS; -} - -static void M292Power(void) { - reg[0] = reg[1] = reg[2] = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M292ProtWrite); - SetReadHandler(0x6000, 0x7FFF, M292ProtRead); -} - -void Mapper292_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M292PW; - MMC3_cwrap = M292CW; - info->Power = M292Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper293.c b/src/mappers/mapper293.c deleted file mode 100644 index 1e5244fbb..000000000 --- a/src/mappers/mapper293.c +++ /dev/null @@ -1,87 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NewStar 12-in-1 and 76-in-1 - */ - -#include "mapinc.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint8 mode = ((reg[0] >> 2) & 0x02) | ((reg[1] >> 6) & 0x01); - uint8 base = ((reg[1] << 5) & 0x20) | ((reg[1] >> 1) & 0x18); - uint8 bank = (reg[0] & 0x07); - - switch (mode) { - case 0: /* UNROM */ - setprg16(0x8000, base | bank); - setprg16(0xC000, base | 0x07); - break; - case 1: - setprg16(0x8000, base | (bank & 0xFE)); - setprg16(0xC000, base | 0x07); - break; - case 2: /* NROM-128 */ - setprg16(0x8000, base | bank); - setprg16(0xC000, base | bank); - break; - case 3: /* NROM-256 */ - setprg16(0x8000, (base | bank) & 0xFE); - setprg16(0xC000, (base | bank) | 1); - break; - } - setchr8(0); - setmirror(((reg[1] >> 7) & 0x01) ^ 0x01); -} - -static DECLFW(M293Write) { - if (!(A & 0x2000)) { - /* First Banking Register ($8000-$9FFF, $C000-$DFFF) */ - reg[0] = V; - } - if (!(A & 0x4000)) { - /* Second Banking Register ($8000-$BFFF) */ - reg[1] = V; - } -} - -static void M293Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xDFFF, M293Write); -} - -static void StateRestore(int version) { - Sync(); -} - -/* BMC 12-in-1/76-in-1 (NewStar) (Unl) */ -void Mapper293_Init(CartInfo *info) { - info->Power = M293Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper294.c b/src/mappers/mapper294.c deleted file mode 100644 index 16478c291..000000000 --- a/src/mappers/mapper294.c +++ /dev/null @@ -1,63 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 NewRisingSun - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, (reg << 3) | (latch.data & 0x07)); - setprg16(0xC000, (reg << 3) | 0x07); - setchr8(0); - setmirror(((reg >> 4) & 0x01) ^ 0x01); -} - -static DECLFW(M294Write) { - if (A & 0x100) { - reg = V; - Sync(); - } -} - -static void M294Reset(void) { - reg = 0; - Latch_RegReset(); -} - -static void M294Power(void) { - reg = 0; - Latch_Power(); - SetWriteHandler(0x4100, 0x5FFF, M294Write); -} - -void Mapper294_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M294Power; - info->Reset = M294Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper295.c b/src/mappers/mapper295.c deleted file mode 100644 index 0b4881de9..000000000 --- a/src/mappers/mapper295.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" -#include "fdssound.h" - -static uint32 GetPRGBank(uint32 V) { - return ((jyasic.mode[3] << 4) | (V & 0x0F)); -} - -static uint32 GetCHRBank(uint32 V) { - return ((jyasic.mode[3] << 7) | (V & 0x7F)); -} - -static void M295Power(void) { - JYASIC_Power(); - FDSSound_Power(); -} - -void Mapper295_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; - info->Power = M295Power; -} diff --git a/src/mappers/mapper297.c b/src/mappers/mapper297.c deleted file mode 100644 index fa0ff36fb..000000000 --- a/src/mappers/mapper297.c +++ /dev/null @@ -1,94 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 297 - 2-in-1 Uzi Lightgun (MGC-002) */ - -#include "mapinc.h" -#include "mmc1.h" - -static uint8 mode; -static uint8 latch; - -static SFORMAT StateRegs[] = { - { &mode, 1, "MODE" }, - { &latch, 1, "LATC" }, - { 0 } -}; - -static void M297PRG(uint16 A, uint16 V) { - setprg16(A, 0x08 | (V & 0x07)); -} - -static void M297CHR(uint16 A, uint16 V) { - setchr4(A, 0x20 | (V & 0x1F)); -} - -static void Sync(void) { - if (mode & 0x01) { - /* MMC1 */ - MMC1_FixPRG(); - MMC1_FixCHR(); - MMC1_FixMIR(); - } else { - /* Mapper 70 */ - setprg16(0x8000, ((mode & 0x02) << 1) | ((latch >> 4) & 0x03)); - setprg16(0xC000, ((mode & 0x02) << 1) | 0x03); - setchr8(latch & 0x0F); - setmirror(MI_V); - } -} - -static DECLFW(M297Mode) { - if (A & 0x100) { - mode = V; - Sync(); - } -} - -static DECLFW(M297Latch) { - if (mode & 0x01) { - MMC1_Write(A, V); - } else { - latch = V; - Sync(); - } -} - -static void M297Power(void) { - latch = 0; - mode = 0; - Sync(); - MMC1_Power(); - SetWriteHandler(0x4100, 0x5FFF, M297Mode); - SetWriteHandler(0x8000, 0xFFFF, M297Latch); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper297_Init(CartInfo *info) { - MMC1_Init(info, 0, 0); - info->Power = M297Power; - MMC1_cwrap = M297CHR; - MMC1_pwrap = M297PRG; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper298.c b/src/mappers/mapper298.c deleted file mode 100644 index 3f563748e..000000000 --- a/src/mappers/mapper298.c +++ /dev/null @@ -1,30 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * iNES Mapper 298 - UNL-TF1201 - * Lethal Weapon (VRC4 mapper) - */ - -#include "mapinc.h" -#include "vrc24.h" - -void Mapper298_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x02, 0x01, FALSE, FALSE); -} diff --git a/src/mappers/mapper299.c b/src/mappers/mapper299.c deleted file mode 100644 index 6c0853f96..000000000 --- a/src/mappers/mapper299.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* BMC-11160 (m299) */ -/* Simple BMC discrete mapper by TXC */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, (latch.data >> 4) & 0x07); - setchr8(((latch.data >> 2) & 0x1C) | (latch.data & 0x03)); - setmirror((latch.data >> 7) & 0x01); -} - -void Mapper299_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper300.c b/src/mappers/mapper300.c deleted file mode 100644 index 02d3cb584..000000000 --- a/src/mappers/mapper300.c +++ /dev/null @@ -1,36 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 300 - BMC-190in1 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.addr >> 2); - setprg16(0xC000, latch.addr >> 2); - setchr8(latch.addr >> 2); - setmirror((latch.addr & 0x01) ^ 0x01); -} - -void Mapper300_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper301.c b/src/mappers/mapper301.c deleted file mode 100644 index f16f57edf..000000000 --- a/src/mappers/mapper301.c +++ /dev/null @@ -1,68 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * GG1 boards, similar to T-262, with no Data latch - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - uint8 prg = (latch.addr >> 2) & 0x1F; - uint8 nrom = (latch.addr & 0x80) != 0; - uint8 unrom = (latch.addr & 0x200) != 0; - - setprg16(0x8000, prg); - setprg16(0xC000, (prg & ~(0x07 * nrom)) | (0x07 * unrom)); - setchr8(0); - setmirror(((latch.addr & 2) >> 1) ^ 1); -} - -static DECLFR(M301Read) { - if ((latch.addr & 0x100) && (PRGsize[0] <= (512 * 1024))) { - A = (A & 0xFFFE) + (dipsw & 0x01); - } - return CartBR(A); -} - -static void M301Power(void) { - dipsw = 0; - Latch_Power(); -} - -static void M301Reset(void) { - dipsw++; - Latch_RegReset(); -} - -void Mapper301_Init(CartInfo *info) { - Latch_Init(info, Sync, M301Read, FALSE, FALSE); - info->Power = M301Power; - info->Reset = M301Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper302.c b/src/mappers/mapper302.c deleted file mode 100644 index 3b7148d06..000000000 --- a/src/mappers/mapper302.c +++ /dev/null @@ -1,54 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 302 - UNL-KS7057 - * FDS Conversion - */ - -#include "mapinc.h" -#include "vrc24.h" - -static void M302PW(uint16 A, uint16 V) { - setprg8( 0x8000, 0x00); - setprg8( 0xA000, 0x0D); - setprg16(0xC000, 0x07); -} - -static void M302CW(uint16 A, uint16 V) { - setchr8(0); -} - -static DECLFR(M302Read) { - uint8 bank = (((A - 0x6000) >> 11) & 0x06) | ((A >> 11) & 0x01); - - return PRGptr[0][(vrc24.chr[bank ^ 4] << 11) | (A & 0x07FF)]; -} - -static void M302Power(void) { - VRC24_Power(); - SetReadHandler(0x6000, 0x9FFF, M302Read); -} - -void Mapper302_Init(CartInfo *info) { - VRC24_Init(info, VRC2, 0x01, 0x02, FALSE, TRUE); - info->Power = M302Power; - VRC24_pwrap = M302PW; - VRC24_cwrap = M302CW;; -} diff --git a/src/mappers/mapper303.c b/src/mappers/mapper303.c deleted file mode 100644 index e6c140d87..000000000 --- a/src/mappers/mapper303.c +++ /dev/null @@ -1,144 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 303 - Kaiser 7017 - * UNIF UNL-KS7017 - * FDS Conversion - Almana No Kiseki - * - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 latch; -static uint8 prg, mirr; -static int32 IRQa, IRQCount, IRQLatch; - -static SFORMAT StateRegs[] = { - { &mirr, 1, "MIRR" }, - { &prg, 1, "REGS" }, - { &latch, 1, "LATC" }, - { &IRQa, 4, "IRQA" }, - { &IRQCount, 4, "IRQC" }, - { &IRQLatch, 4, "IRQL" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, prg); - setprg16(0xC000, 2); - setchr8(0); - setprg8r(0x10, 0x6000, 0); - setmirror(mirr); -} - -static DECLFW(M303Write) { - /* FCEU_printf("bs %04x %02x\n",A,V); */ - if ((A & 0xFF00) == 0x4A00) { - latch = ((A >> 2) & 0x03) | ((A >> 4) & 0x04); - } else if ((A & 0xFF00) == 0x5100) { - prg = latch; - Sync(); - } else { - if (A == 0x4020) { - X6502_IRQEnd(FCEU_IQEXT); - IRQCount &= 0xFF00; - IRQCount |= V; - } else if (A == 0x4021) { - X6502_IRQEnd(FCEU_IQEXT); - IRQCount &= 0x00FF; - IRQCount |= V << 8; - IRQa = 1; - } else if (A == 0x4025) { - mirr = ((V & 8) >> 3) ^ 0x01; - } - } - if (A >= 0x4040 && A <= 0x407F) { - FDSWaveWrite(A, V); - } - switch (A) { - case 0x4080: FDSSReg0Write(A, V); break; - case 0x4082: FDSSReg1Write(A, V); break; - case 0x4083: FDSSReg2Write(A, V); break; - case 0x4084: FDSSReg3Write(A, V); break; - case 0x4085: FDSSReg4Write(A, V); break; - case 0x4086: FDSSReg5Write(A, V); break; - case 0x4087: FDSSReg6Write(A, V); break; - case 0x4088: FDSSReg7Write(A, V); break; - case 0x4089: FDSSReg8Write(A, V); break; - case 0x408A: FDSSReg9Write(A, V); break; - } -} - -static DECLFR(FDSRead4030) { - uint8 ret = (X.IRQlow & FCEU_IQEXT) ? 1 : 0; - - X6502_IRQEnd(FCEU_IQEXT); - return ret; -} - -static void UNL7017IRQ(int a) { - if (IRQa) { - IRQCount -= a; - if (IRQCount <= 0) { - IRQa = 0; - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void M303Power(void) { - latch = prg = mirr = IRQa = IRQCount = IRQLatch = 0; - FDSSound_Power(); - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetReadHandler(0x4030, 0x4030, FDSRead4030); - SetWriteHandler(0x4020, 0x5FFF, M303Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M303Reset(void) { - Sync(); - FDSSoundRegReset(); - FDSSound_SC(); -} - -static void M303Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper303_Init(CartInfo *info) { - info->Power = M303Power; - info->Close = M303Close; - info->Reset = M303Reset; - MapIRQHook = UNL7017IRQ; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper304.c b/src/mappers/mapper304.c deleted file mode 100644 index 1c2147ccc..000000000 --- a/src/mappers/mapper304.c +++ /dev/null @@ -1,99 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversions - * - * Super Mario Bros 2j (Alt Full) is a BAD incomplete dump, should be mapper 43 - * - * Both Voleyball and Zanac by Whirlind Manu shares the same PCB, but with - * some differences: Voleyball has 8K CHR ROM and 8K ROM at 6000K, Zanac - * have 8K CHR RAM and banked 16K ROM mapper at 6000 as two 8K banks. - * - * NES 2.0 Mapper 304 - UNL-SMB2J - * Super Mario Bros 2j (Alt Small) uses additionally IRQ timer to drive framerate - * - * PCB for this mapper is "09-034A" - */ - -#include "mapinc.h" - -static uint8 prg; -static uint32 IRQCount, IRQa; - -static SFORMAT StateRegs[] = -{ - { &IRQCount, 4, "IRQC" }, - { &IRQa, 4, "IRQA" }, - { &prg, 1, "PRG" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x6000, 4 | prg); - setprg32(0x8000, 0); - setchr8(0); -} - -static DECLFW(M304Write1) { - prg = V & 0x01; - Sync(); -} - -static DECLFW(M304Write2) { - IRQa = V & 0x01; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); -} - -static DECLFR(M304Read) { - return 0xFF; -} - -static void M304Power(void) { - prg = 0; - IRQCount = IRQa = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetReadHandler(0x4020, 0x4FFF, M304Read); - SetWriteHandler(0x4068, 0x4068, M304Write2); - SetWriteHandler(0x4027, 0x4027, M304Write1); -} - -static void M304IRQHook(int a) { - if (IRQa) { - if (IRQCount < 5750) { - IRQCount += a; - } else { - IRQa = 0; - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper304_Init(CartInfo *info) { - info->Power = M304Power; - MapIRQHook = M304IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper305.c b/src/mappers/mapper305.c deleted file mode 100644 index e25040386..000000000 --- a/src/mappers/mapper305.c +++ /dev/null @@ -1,86 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 305 - * UNIF UNL-KS7031 - * FDS Conversion - dracula ii - noroi no fuuin [u][!] - * - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg[4]; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg2(0x6000, reg[0]); - setprg2(0x6800, reg[1]); - setprg2(0x7000, reg[2]); - setprg2(0x7800, reg[3]); - - setprg2(0x8000, 15); - setprg2(0x8800, 14); - setprg2(0x9000, 13); - setprg2(0x9800, 12); - setprg2(0xa000, 11); - setprg2(0xa800, 10); - setprg2(0xb000, 9); - setprg2(0xb800, 8); - - setprg2(0xc000, 7); - setprg2(0xc800, 6); - setprg2(0xd000, 5); - setprg2(0xd800, 4); - setprg2(0xe000, 3); - setprg2(0xe800, 2); - setprg2(0xf000, 1); - setprg2(0xf800, 0); - - setchr8(0); -} - -static DECLFW(M305Write) { - reg[(A >> 11) & 0x03] = V; - Sync(); -} - -static void M305Power(void) { - memset(reg, 0, sizeof(reg)); - FDSSound_Power(); - Sync(); - setmirror(MI_V); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M305Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper305_Init(CartInfo *info) { - info->Power = M305Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper306.c b/src/mappers/mapper306.c deleted file mode 100644 index b140bb633..000000000 --- a/src/mappers/mapper306.c +++ /dev/null @@ -1,75 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2016 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 306 - Kaiser 7016 - * UNIF UNL-KS7016 - * FDS Conversion (Exciting Basket), weird banking addressing, seems because - * of used addressing scheme, made to disable the lower system banks from 6000 - * but the kaiser mapper chip and PCB are the same as usual - * probably need a hard eprom dump to verify actual banks layout - * - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8( 0x6000, reg); - setprg32(0x8000, 3); - setchr8(0); -} - -static DECLFW(M306Write) { - if ((A & 0xD903) == 0xD903) { - if (A & 0x40) { - reg = (A >> 2) & 0x0F; - } else { - reg = 0x08 | ((A >> 2) & 0x03); - } - Sync(); - } -} - -static void M306Power(void) { - FDSSound_Power(); - - reg = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0xD000, 0xDFFF, M306Write); - SetWriteHandler(0xF000, 0xFFFF, M306Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper306_Init(CartInfo *info) { - info->Power = M306Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper307.c b/src/mappers/mapper307.c deleted file mode 100644 index 3b82baa53..000000000 --- a/src/mappers/mapper307.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - Metroid - Jin Ji Zhi Ling (Kaiser)(KS7037)[U][!] - * NES 2.0 Mapper 307 - UNL-KS7037 - * - */ - -#include "mapinc.h" -#include "n118.h" -#include "fdssound.h" - -static void M307FixPRG(void) { - setprg4r(0x10, 0x6000, 0); - setprg4(0x7000, 15); - setprg8(0x8000, n118.reg[6]); - setprg4(0xA000, ~3); - setprg4r(0x10, 0xB000, 0x01); - setprg8(0xC000, n118.reg[7]); - setprg8(0xE000, ~0); -} - -static void M307FixCHR(void) { - setchr8(0); - setmirrorw(n118.reg[2] & 0x01, n118.reg[4] & 0x01, n118.reg[3] & 0x01, n118.reg[5] & 0x01); -} - -static void M307Power(void) { - FDSSound_Power(); - N118_Power(); - SetWriteHandler(0xB000, 0xBFFF, CartBW); -} - -void Mapper307_Init(CartInfo *info) { - N118_Init(info, 8, info->battery); - info->Power = M307Power; - N118_FixPRG = M307FixPRG; - N118_FixCHR = M307FixCHR; -} diff --git a/src/mappers/mapper308.c b/src/mappers/mapper308.c deleted file mode 100644 index a921a34a3..000000000 --- a/src/mappers/mapper308.c +++ /dev/null @@ -1,76 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 308 - UNL-TH2131-1 */ -/* https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_308 - * NES 2.0 Mapper 308 is used for a bootleg version of the Sunsoft game Batman - * similar to Mapper 23 Submapper 3) with custom IRQ functionality. - * UNIF board name is UNL-TH2131-1. - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 IRQLatch, IRQa; -static uint16 IRQCount; - -static SFORMAT IRQStateRegs[] = { - { &IRQCount, 2, "IRQC" }, - { &IRQLatch, 1, "IRQL" }, - { &IRQa, 1, "IRQA" }, - - { 0 } -}; - -static DECLFW(M308Write) { - switch (A & 0xF003) { - case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; IRQCount = 0; break; - case 0xF001: IRQa = 1; break; - case 0xF003: IRQLatch = (V & 0xF0) >> 4; break; - } -} - -static void M308IRQHook(int a) { - if (IRQa) { - while (a--) { - IRQCount++; - if ((IRQCount & 0x0FFF) == 2048) { - IRQLatch--; - } - if (!IRQLatch && (IRQCount & 0x0FFF) < 2048) { - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void M308Power(void) { - IRQa = IRQCount = IRQLatch = 0; - VRC24_Power(); - SetWriteHandler(0xF000, 0xFFFF, M308Write); -} - -void Mapper308_Init(CartInfo *info) { - VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); - info->Power = M308Power; - MapIRQHook = M308IRQHook; - AddExState(IRQStateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper309.c b/src/mappers/mapper309.c deleted file mode 100644 index 8c1b3cb0a..000000000 --- a/src/mappers/mapper309.c +++ /dev/null @@ -1,83 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* FDS Conversion - * NES 2.0 Mapper 309 is used for Whirlwind Manu's ROM cartridge conversion - * of game 愛戦士ニコル (Ai Senshi Nicol, cartridge code M309). - * Its UNIF board name is UNL-LH51. - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_309 - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg, mirr; - -static SFORMAT StateRegs[] = { - { ®, 1, "REG" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg8(0x8000, reg); - setprg8(0xA000, ~2); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); - setchr8(0); - setmirror(((mirr >> 3) & 0x01) ^ 0x01); -} - -static DECLFW(M309Write) { - switch (A & 0xF000) { - case 0x8000: reg = V; Sync(); break; - case 0xF000: mirr = V; Sync(); break; - } -} - -static void M309Power(void) { - FDSSound_Power(); - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0xFFFF, M309Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M309Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper309_Init(CartInfo *info) { - info->Power = M309Power; - info->Close = M309Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper310.c b/src/mappers/mapper310.c deleted file mode 100644 index 7ddb5ae2f..000000000 --- a/src/mappers/mapper310.c +++ /dev/null @@ -1,93 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 NewRisingSun - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" - -static uint8 regData[2]; -static uint8 regAddr; - -static SFORMAT K1053_state[] = -{ - { regData, 2, "REGD" }, - { ®Addr, 1, "REGA" }, - { 0 } -}; - -static void K1053_sync(void) { - int prg = (regData[0] & 0x3F) | ((regAddr << 4) & ~0x3F); - int chrWritable; - switch (regAddr & 3) { - case 0: - setprg32(0x8000, prg >> 1); - chrWritable = 0; - break; - case 1: - setprg16(0x8000, prg); - setprg16(0xC000, prg | 7); - chrWritable = 1; - break; - case 2: - prg = prg << 1 | regData[0] >> 7; - setprg8(0x8000, prg); - setprg8(0xA000, prg); - setprg8(0xC000, prg); - setprg8(0xE000, prg); - chrWritable = 1; - break; - case 3: - setprg16(0x8000, prg); - setprg16(0xC000, prg); - chrWritable = 0; - break; - } - SetupCartCHRMapping(0, CHRptr[0], 0x8000, chrWritable); - setchr8(regData[1]); - setmirror((regData[0] & 0x40) ? MI_H : MI_V); -} - -static void K1053_restore(int version) { - K1053_sync(); -} - -static DECLFW(K1053_write) { - regData[(A >> 14) & 1] = V; - if (A & 0x4000) - regAddr = A & 0xFF; - K1053_sync(); -} - -static void K1053_reset(void) { - regData[0] = regData[1] = regAddr = 0; - K1053_sync(); -} - -static void K1053_power(void) { - K1053_reset(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, K1053_write); -} - -void Mapper310_Init(CartInfo *info) { - info->Power = K1053_power; - info->Reset = K1053_reset; - GameStateRestore = K1053_restore; - AddExState(&K1053_state, ~0, 0, 0); -} diff --git a/src/mappers/mapper312.c b/src/mappers/mapper312.c deleted file mode 100644 index 5fb9e16bd..000000000 --- a/src/mappers/mapper312.c +++ /dev/null @@ -1,60 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 312 - Kaiser 7013B - * UNIF UNL-KS7013B - * Just another pirate cart with pirate mapper, instead of original MMC1 - * Kaiser Highway Star - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, reg); - setprg16(0xc000, ~0); - setmirror((latch.data & 0x01) ^ 0x01); - setchr8(0); -} - -static DECLFW(M312LoWrite) { - reg = V; - Sync(); -} - -static void M312Power(void) { - reg = 0; - Latch_Power(); - SetWriteHandler(0x6000, 0x7FFF, M312LoWrite); -} - -void Mapper312_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M312Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper313.c b/src/mappers/mapper313.c deleted file mode 100644 index 56b3e5d78..000000000 --- a/src/mappers/mapper313.c +++ /dev/null @@ -1,78 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 313 is used for MMC3-based multicarts that switch - * between 128 KiB PRG-ROM/128 KiB CHR-ROM-sized games on each reset and - * thus require no additional registers. - * Its UNIF board name is BMC-RESET-TXROM. - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M313CW(uint16 A, uint16 V) { - switch (iNESCart.submapper) { - default: setchr1(A, (reg << 7) | (V & 0x7F)); break; - case 1: setchr1(A, (reg << 7) | (V & 0x7F)); break; - case 2: setchr1(A, (reg << 8) | (V & 0xFF)); break; - case 3: setchr1(A, (reg << 8) | (V & 0xFF)); break; - case 4: setchr1(A, (reg << 7) | (V & 0x7F)); break; - } -} - -static void M313PW(uint16 A, uint16 V) { - switch (iNESCart.submapper) { - default: setprg8(A, (reg << 4) | (V & 0x0F)); break; - case 1: setprg8(A, (reg << 5) | (V & 0x1F)); break; - case 2: setprg8(A, (reg << 4) | (V & 0x0F)); break; - case 3: setprg8(A, (reg << 5) | (V & 0x1F)); break; - case 4: - if (reg == 0) { - setprg8(A, (reg << 5) | (V & 0x1F)); - } else { - setprg8(A, (reg << 4) | (V & 0x0F)); - } - break; - } -} - -static void M313Reset(void) { - reg++; - reg &= 0x03; - MMC3_Reset(); -} - -static void M313Power(void) { - reg = 0; - MMC3_Power(); -} - -/* NES 2.0 313, UNIF BMC-RESET-TXROM */ -void Mapper313_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_cwrap = M313CW; - MMC3_pwrap = M313PW; - info->Power = M313Power; - info->Reset = M313Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper314.c b/src/mappers/mapper314.c deleted file mode 100644 index ce2dd47b7..000000000 --- a/src/mappers/mapper314.c +++ /dev/null @@ -1,81 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * BMC 42-in-1 "reset switch" type - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 regs[4]; - -static SFORMAT StateRegs[] = { - { regs, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint8 prg = regs[1] & 0x3F; - - if (regs[0] & 0x80) { /* NROM mode */ - if (regs[1] & 0x80) { - setprg32(0x8000, prg); - } else { - setprg16(0x8000, (prg << 1) | ((regs[1] >> 6) & 0x01)); - setprg16(0xC000, (prg << 1) | ((regs[1] >> 6) & 0x01)); - } - } else { /* UNROM mode */ - setprg16(0x8000, (prg << 1) | (latch.data & 0x07)); - setprg16(0xC000, (prg << 1) | 0x07); - } - setchr8((regs[2] << 2) | ((regs[0] >> 1) & 0x03)); - setmirror(((regs[0] >> 5) & 0x01) ^ 0x01); - -} - -static DECLFW(M314Write) { - A &= 0x03; - if (A == 0x03) A = 0x01; /* K-42001's "Aladdin III" */ - regs[A] = V; - Sync(); -} - -static void M314Reset(void) { - /* Reset returns to menu */ - regs[0] = 0x80; - regs[1] = 0x43; - regs[2] = regs[3] = 0; - Sync(); -} - -static void M314Power(void) { - regs[0] = 0x80; - regs[1] = 0x43; - regs[2] = regs[3] = 0; - Latch_Power(); - SetWriteHandler(0x5000, 0x5FFF, M314Write); -} - -void Mapper314_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Power = M314Power; - info->Reset = M314Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper315.c b/src/mappers/mapper315.c deleted file mode 100644 index 38f866d38..000000000 --- a/src/mappers/mapper315.c +++ /dev/null @@ -1,81 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 315 - * BMC-830134C - * Used for multicarts using 820732C- and 830134C-numbered PCBs such as 4-in-1 Street Blaster 5 - * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_315 - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M315CCW(uint16 A, uint16 V) { - uint16 mask = 0xFF; - uint16 base = reg << 8; - - V = ((reg << 6) & 0x80) | ((reg << 3) & 0x40) | (V & 0xFF); - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M315CPW(uint16 A, uint16 V) { - uint16 mask = 0x0F; - uint16 base = reg << 3; - - if ((reg & 0x06) == 0x06) { /* GNROM-like */ - setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & ~0x02) & mask)); - setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & ~0x02) & mask)); - setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] | 0x02) & mask)); - setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] | 0x02) & mask)); - } else { - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static DECLFW(M315CWrite) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M315CReset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M315CPower(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M315CWrite); -} - -void Mapper315_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M315CPW; - MMC3_cwrap = M315CCW; - info->Power = M315CPower; - info->Reset = M315CReset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper319.c b/src/mappers/mapper319.c deleted file mode 100644 index 2b44cb632..000000000 --- a/src/mappers/mapper319.c +++ /dev/null @@ -1,92 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[2]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = -{ - { reg, 2, "REG" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M319Sync(void) { - uint16 bank, mask; - - if (iNESCart.CRC32 == 0xE5B9AB1F || iNESCart.PRGCRC32 == 0xC25FD362) { - /* The publicly-available UNIF (UNL-HP898F) ROM file of Prima Soft 9999999-in-1 has - * the order of the 16 KiB PRG-ROM banks slightly mixed up, so that the - * PRG A14 mode bit operates on A16 instead of A14. To obtain the - * correct bank order, use UNIF 16 KiB PRG banks 0, 4, 1, 5, 2, 6, 3, 7. - */ - bank = (reg[1] >> 3) & 7; - mask = (reg[1] >> 4) & 4; - - setprg16(0x8000, bank & ~mask); - setprg16(0xC000, bank | mask); - } else { - bank = ((reg[1] >> 2) & 0x06) | ((reg[1] >> 5) & 0x01); - mask = (reg[1] >> 6) & 0x01; - - setprg16(0x8000, (bank & ~mask)); - setprg16(0xC000, (bank | mask)); - } - - bank = reg[0] >> 4; - mask = (reg[0] << 2) & 0x04; - - setchr8((bank & ~mask) | ((latch.data << 2) & mask)); - setmirror(reg[1] >> 7); -} - -static DECLFR(M319ReadDIP) { - return dipsw; -} - -static DECLFW(M319Write) { - reg[(A >> 2) & 0x01] = V; - M319Sync(); -} - -static void M319Reset(void) { - reg[0] = reg[1] = 0; - dipsw ^= 0x40; - M319Sync(); -} - -static void M319Power(void) { - reg[0] = reg[1] = dipsw = 0; - Latch_Power(); - SetReadHandler(0x5000, 0x5FFF, M319ReadDIP); - SetWriteHandler(0x6000, 0x7FFF, M319Write); -} - -void Mapper319_Init(CartInfo *info) { - Latch_Init(info, M319Sync, NULL, 0, 0); - info->Power = M319Power; - info->Reset = M319Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper320.c b/src/mappers/mapper320.c deleted file mode 100644 index 0fe0bb324..000000000 --- a/src/mappers/mapper320.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 320 is used for the Super HiK 6-in-1 A-030 multicart. - * Basically UxROM with an address-latch-based outer bank register. - * UNIF board name is BMC-830425C-4391T. Mirroring is hard-wired. - * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_320 - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint16 mask = (latch.addr & 0x10) ? 0x07 : 0x0F; - uint16 base = latch.addr << 3; - - setprg16(0x8000, base | (latch.data & mask)); - setprg16(0xC000, base | (latch.data & mask) | ((~latch.addr >> 1) & 0x08) | 0x07); - setchr8(0); - setmirror(MI_V); -} - -static DECLFW(M320Write) { - if ((A & 0xFFE0) == 0xF0E0) { - latch.addr = A; - } - latch.data = V; - Sync(); -} - -static void M320Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M320Write); -} - -void Mapper320_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M320Power; - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper322.c b/src/mappers/mapper322.c deleted file mode 100644 index 7e003cb45..000000000 --- a/src/mappers/mapper322.c +++ /dev/null @@ -1,97 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 322 - * BMC-K-3033 - * 35-in-1 (K-3033) - * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_322 - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M322CW(uint16 A, uint16 V) { - if (reg & 0x20) { - uint16 base = ((reg >> 4) & 0x04) | ((reg >> 3) & 0x03); - - if (reg & 0x80) { - setchr1(A, (base << 8) | (V & 0xFF)); - } else { - setchr1(A, (base << 7) | (V & 0x7F)); - } - } else { - setchr1(A, (V & 0x7F)); - } -} - -static void M322PW(uint16 A, uint16 V) { - uint16 base = ((reg >> 4) & 0x04) | ((reg >> 3) & 0x03); - - if (reg & 0x20) { - if (reg & 0x80) { - setprg8(A, (base << 5) | (V & 0x1F)); - } else { - setprg8(A, (base << 4) | (V & 0x0F)); - } - } else { - if (reg & 0x03) { - setprg32(0x8000, (base << 3) | ((reg >> 1) & 0x03)); - } else { - setprg16(0x8000, (base << 3) | (reg & 0x07)); - setprg16(0xC000, (base << 3) | (reg & 0x07)); - } - } -} - -static DECLFW(M322Write) { - if (MMC3_WramIsWritable()) { - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M322Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M322Write); -} - -static void M322Reset(void) { - reg = 0; - MMC3_Reset(); -} - -void Mapper322_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M322PW; - MMC3_cwrap = M322CW; - info->Power = M322Power; - info->Reset = M322Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper323.c b/src/mappers/mapper323.c deleted file mode 100644 index cb179cebf..000000000 --- a/src/mappers/mapper323.c +++ /dev/null @@ -1,74 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 323 - UNIF FARID_SLROM_8-IN-1 */ - -#include "mapinc.h" -#include "mmc1.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M323PW(uint16 A, uint16 V) { - uint8 mask = 0x07; - uint8 base = reg >> 1; - - setprg16(A, (base & ~mask) | (V & mask)); -} - -static void M323CW(uint16 A, uint16 V) { - uint16 mask = 0x1F; - uint16 base = reg << 1; - - setchr4(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M323Write) { - if (!(mmc1.reg[3] & 0x10) && !(reg & 0x08)) { - reg = V; - MMC1_FixCHR(); - MMC1_FixPRG(); - MMC1_FixMIR(); - } -} - -static void M323Power(void) { - reg = 0; - MMC1_Power(); - SetWriteHandler(0x6000, 0x7FFF, M323Write); -} - -static void M323Reset(void) { - reg = 0; - MMC1_Reset(); -} - -void Mapper323_Init(CartInfo *info) { - MMC1_Init(info, 0, 0); - MMC1_cwrap = M323CW; - MMC1_pwrap = M323PW; - info->Power = M323Power; - info->Reset = M323Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper324.c b/src/mappers/mapper324.c deleted file mode 100644 index 9b694a509..000000000 --- a/src/mappers/mapper324.c +++ /dev/null @@ -1,54 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 324 - * FARID_UNROM_8-IN-1 - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_324 - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setchr8(0); - setprg16(0x8000, ((latch.data & 0x70) >> 1) | (latch.data & 0x07)); - setprg16(0xC000, ((latch.data & 0x70) >> 1) | 0x07 ); -} - -static DECLFW(M324Write) { - if ((V & 0x80) && !(latch.data & 0x80) && !(latch.data & 0x08)) { - Latch_Write(A, V); - } else { - latch.data = (latch.data & ~0x07) | (V & 0x07); - Sync(); - } -} - -static void M324Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M324Write); -} - -void Mapper324_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Power = M324Power; - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper325.c b/src/mappers/mapper325.c deleted file mode 100644 index c53d8f4a1..000000000 --- a/src/mappers/mapper325.c +++ /dev/null @@ -1,51 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 325 - * UNIF UNL-MALISB - */ - -#include "mapinc.h" -#include "mmc3.h" - -static void M325PW(uint16 A, uint16 V) { - setprg8(A, ((V << 1) & 0x08) | ((V >> 1) & 0x04) | (V & 0x03)); -} - -static void M325CW(uint16 A, uint16 V) { - setchr1(A, (V & 0xDD) | ((V << 4) & 0x20) | ((V >> 4) & 0x02)); -} - -static DECLFW(M325Write) { - A = (A & 0xFFFE) | ((A >> 3) & 1); - MMC3_Write(A, V); -} - -static void M325Power(void) { - MMC3_Power(); - SetWriteHandler(0x8000, 0xFFFF, M325Write); -} - -void Mapper325_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M325PW; - MMC3_cwrap = M325CW; - info->Power = M325Power; -} diff --git a/src/mappers/mapper326.c b/src/mappers/mapper326.c deleted file mode 100644 index eec1b010d..000000000 --- a/src/mappers/mapper326.c +++ /dev/null @@ -1,89 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 326 is used for a bootleg version of Contra/Gryzor. - * as implemented from - * http://forums.nesdev.org/viewtopic.php?f=9&t=17352&p=218722#p218722 - */ - -#include "mapinc.h" - -static uint8 prg[4], chr[8], nt[4]; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { nt, 4, "NTAR" }, - { 0 } -}; - -static void Sync(void) { - int i; - - for (i = 0; i < 4; i++) setprg8(0x8000 + (i << 13), prg[i]); - for (i = 0; i < 8; i++) setchr1(i << 10, chr[i]); - for (i = 0; i < 3; i++) setntamem(NTARAM + 0x400 * (nt[i] & 0x01), 1, i); -} - -static DECLFW(M326Write) { - switch (A & 0xE010) { - case 0x8000: prg[0] = V; break; - case 0xA000: prg[1] = V; break; - case 0xC000: prg[2] = V; break; - default: break; - } - - switch (A & 0x1F) { - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x14: case 0x15: case 0x16: case 0x17: - chr[A & 0x07] = V; - break; - case 0x18: case 0x19: case 0x1A: case 0x1B: - nt[A & 0x03] = V; - break; - default: - break; - } - - Sync(); -} - -static void M326Power(void) { - int i; - - for (i = 0; i < 4; i++) prg[i] = 0xFC | i; - for (i = 0; i < 8; i++) chr[i] = i; - for (i = 0; i < 4; i++) nt[i] = (i >> 1) & 0x01; - - Sync(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M326Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper326_Init(CartInfo *info) { - info->Power = M326Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper327.c b/src/mappers/mapper327.c deleted file mode 100644 index 195065af9..000000000 --- a/src/mappers/mapper327.c +++ /dev/null @@ -1,108 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2015 Cluster - * http://clusterrr.com - * clusterrr@clusterrr.com - * - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - NES 2.0 mapper 327 is used for a 6-in-1 multicart. Its UNIF board name is BMC-10-24-C-A1. - - MMC3-based multicart mapper with CHR RAM, CHR ROM and PRG RAM - - $6000-7FFF: A~[011xxxxx xxMRSBBB] Multicart reg - This register can only be written to if PRG-RAM is enabled and writable (see $A001) - and BBB = 000 (power on state) - - BBB = CHR+PRG block select bits (A19, A18, A17 for both PRG and CHR) - S = PRG block size (0=256k 1=128k) - R = CHR mode (0=CHR ROM 1=CHR RAM) - M = CHR block size (0=256k 1=128k) - ignored when S is 0 for some reason - - Example Game: - -------------------------- - 6 in 1 multicart (SMB3, TMNT2, Contra, Ninja Cat, Ninja Crusaders, Rainbow Islands 2) -*/ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M327PW(uint16 A, uint16 V) { - uint8 base = (reg << 4) & 0x70; - uint8 mask = (reg & 0x08) ? 0x1F : 0x0F; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M327CW(uint16 A, uint16 V) { - if (reg & 0x10) { - setchr8r(0x10, 0); - } else { - uint16 base = (reg << 7) & 0x380; - uint16 mask = (reg & 0x20) ? 0xFF : 0x7F; - - setchr1(A, base | (V & mask)); - } -} - -static DECLFW(M327Write) { - if (MMC3_WramIsWritable()) { - CartBW(A, V); - if ((reg & 7) == 0) { - reg = A & 0x3F; - MMC3_FixPRG(); - MMC3_FixCHR(); - } - } -} - -static void M327Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M327Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M327Write); -} - -static void M327Close(void) { - MMC3_Close(); -} - -void Mapper327_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = M327PW; - MMC3_cwrap = M327CW; - - info->Power = M327Power; - info->Reset = M327Reset; - info->Close = M327Close; - AddExState(®, 1, 0, "EXPR"); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper328.c b/src/mappers/mapper328.c deleted file mode 100644 index 286ef204b..000000000 --- a/src/mappers/mapper328.c +++ /dev/null @@ -1,51 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2016 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Test Ver. 1.01 Dlya Proverki TV Pristavok (RT-01, by SS aka Snake) - * A simple board with 16K PRG ROM + 2K CHR ROM with no mapper, hardwired mirroring - * PRG EPROM has copy protected areas with "weak bits", which is tested at some - * points of the program. Trying to simalate "weak bits" behaviour - * - */ - -/* NES 2.0 Mapper 328 - UNL-RT-01 */ - -#include -#include "mapinc.h" - -static DECLFR(M328Read) { - if (((A >= 0xCE80) && (A < 0xCF00)) || ((A >= 0xFE80) && (A < 0xFF00))) { - return 0xF2 | (rand() & 0x0D); - } - return CartBR(A); -} - -static void M328Power(void) { - setprg16(0x8000, 0); - setprg16(0xC000, 0); - setchr2(0x0000,0); - setchr2(0x0800,0); - setchr2(0x1000,0); - setchr2(0x1800,0); - SetReadHandler(0x8000, 0xFFFF, M328Read); -} - -void Mapper328_Init(CartInfo *info) { - info->Power = M328Power; -} diff --git a/src/mappers/mapper329.c b/src/mappers/mapper329.c deleted file mode 100644 index fda93319a..000000000 --- a/src/mappers/mapper329.c +++ /dev/null @@ -1,37 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2006 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 329 - UNL-EDU2000 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg8r(0x10, 0x6000, latch.data >> 6); - setprg32(0x8000, latch.data & 0x1F); - setchr8(0); - setmirror(((latch.data >> 5) & 0x01) ^ 0x01); -} - -void Mapper329_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper330.c b/src/mappers/mapper330.c deleted file mode 100644 index bf44bcd33..000000000 --- a/src/mappers/mapper330.c +++ /dev/null @@ -1,135 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 330 is used for a bootleg version of Contra/Gryzor. - * as implemented from - * http://forums.nesdev.org/viewtopic.php?f=9&t=17352&p=218722#p218722 - */ - -#include "mapinc.h" -#include "n163sound.h" - -static uint8 IRQa; -static uint16 IRQCount; - -static uint8 prg[4], chr[8], nt[4]; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { nt, 4, "NTAR" }, - { 0 } -}; - -static void Sync(void) { - int i; - - setprg8r(0x10, 0x6000, 0); - setprg8(0xE000, ~0); - - for (i = 0; i < 3; i++) setprg8(0x8000 + (i << 13), prg[i]); - for (i = 0; i < 8; i++) setchr1(i << 10, chr[i]); - for (i = 0; i < 3; i++) setntamem(NTARAM + 0x400 * (nt[i] & 0x01), 1, i); -} - -static DECLFW(M330WriteCHR) { - if ((A & 0x400) && !(A & 0x4000)) { - if (A & 0x2000) { - IRQCount &= 0x00FF; - IRQCount |= (V & 0x7F) << 8; - IRQa = V & 0x80; - X6502_IRQEnd(FCEU_IQEXT); - } else { - IRQCount &= 0xFF00; - IRQCount |= V; - } - } else { - int index = (A >> 11) & 0x07; - chr[index] = V; - Sync(); - } -} - -static DECLFW(M330WriteNT) { - if (!(A & 0x400)) { - int index = (A >> 11) & 0x03; - nt[index] = V; - Sync(); - } -} - -static DECLFW(M330WritePRG) { - if ((A >= 0xF000) && (A & 0x800)) { - N163Sound_Write(A, V); - } else if (!(A & 0x400)) { - int index = (A >> 11) & 0x03; - prg[index] = V; - Sync(); - } -} - -static void M330Power(void) { - int i; - - for (i = 0; i < 4; i++) prg[i] = i; - for (i = 0; i < 8; i++) chr[i] = i; - for (i = 0; i < 4; i++) nt[i] = (i >> 1) & 0x01; - - IRQa = IRQCount = 0; - - Sync(); - - SetReadHandler(0x4800, 0x4FFF, N163Sound_Read); - SetWriteHandler(0x4800, 0x4FFF, N163Sound_Write); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - - SetWriteHandler(0x8000, 0xBFFF, M330WriteCHR); - SetWriteHandler(0xC000, 0xDFFF, M330WriteNT); - SetWriteHandler(0xE000, 0xFFFF, M330WritePRG); -} - -static void M330IRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount > 0x7FFF) { - X6502_IRQBegin(FCEU_IQEXT); - IRQa = 0; - IRQCount = 0; - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper330_Init(CartInfo *info) { - info->Power = M330Power; - MapIRQHook = M330IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAM = (uint8 *)FCEU_gmalloc(8192); - SetupCartPRGMapping(0x10, WRAM, 8192, 1); - AddExState(WRAM, 8192, 0, "WRAM"); - - N163Sound_ESI(); -} diff --git a/src/mappers/mapper331.c b/src/mappers/mapper331.c deleted file mode 100644 index a8deb637f..000000000 --- a/src/mappers/mapper331.c +++ /dev/null @@ -1,84 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * 7-in-1 Darkwing Duck, Snake, MagicBlock (PCB marked as "12 in 1") - * 12-in-1 1991 New Star Co. Ltd. - * - */ - -#include "mapinc.h" - -static uint8 reg[3]; -static uint8 PPUCHRBus; - -static SFORMAT StateRegs[] = { - { reg, 3, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint8 base = (reg[2] & 0x03) << 3; - - if (reg[2] & 8) { - setprg16(0x8000, base | ((reg[PPUCHRBus] & 0x06) & ~0x01)); /* actually, both 0 and 1 registers used, but they will switch each PA12 transition */ - setprg16(0xc000, base | ((reg[PPUCHRBus] & 0x06) | 0x01)); /* if bits are different for both registers, so they must be programmed strongly the same! */ - } else { - setprg16(0x8000, base | (reg[PPUCHRBus] & 0x07)); - setprg16(0xc000, base | 0x07); - } - setchr4(0x0000, (base << 2) | (reg[0] >> 3)); - setchr4(0x1000, (base << 2) | (reg[1] >> 3)); - setmirror(((reg[2] & 4) >> 2) ^ 1); -} - -static DECLFW(M331Write) { - switch (A & 0xE000) { - case 0xA000: reg[0] = V; Sync(); break; - case 0xC000: reg[1] = V; Sync(); break; - case 0xE000: reg[2] = V; Sync(); break; - } -} - -static void M331Power(void) { - reg[0] = reg[1] = reg[2] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M331Write); -} - -static void StateRestore(int version) { - Sync(); -} - -static void M331PPUHook(uint32 A) { - uint8 bank = (A & 0x1000) >> 12; - - if ((PPUCHRBus != bank) && ((A & 0x3000) != 0x2000)) { - PPUCHRBus = bank; - Sync(); - } -} - -void Mapper331_Init(CartInfo *info) { - info->Power = M331Power; - PPU_hook = M331PPUHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper332.c b/src/mappers/mapper332.c deleted file mode 100644 index 1dc852b89..000000000 --- a/src/mappers/mapper332.c +++ /dev/null @@ -1,89 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* added 2019-5-23 - * NES 2.0 Mapper 332 - * BMC-WS Used for Super 40-in-1 multicart - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_332 */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[2], dipsw; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - uint32 prg = ((reg[0] >> 3) & 0x08) | (reg[0] & 0x07); - uint32 chr = ((reg[0] >> 3) & 0x08) | (reg[1] & 0x07); - uint32 mask = (reg[1] & 0x10) ? 0 : (reg[1] & 0x20) ? 1 : 3; - - if (reg[0] & 0x08) { - setprg16(0x8000, prg); - setprg16(0xc000, prg); - } else { - setprg32(0x8000, prg >> 1); - } - setchr8((chr & ~mask) | (latch.data & mask)); - setmirror(((reg[0] >> 4) & 0x01) ^ 0x01); -} - -static DECLFR(M332Read) { - if ((reg[1] >> 6) & (dipsw & 0x03)) { - return CPU_OPENBUS; - } - return CartBR(A); -} - -static DECLFW(M332Write) { - if (!(reg[0] & 0x20)) { - reg[A & 0x01] = V; - Sync(); - } -} - -static void M332Reset(void) { - dipsw++; /* Soft-resetting cycles through solder pad or DIP switch settings */ - if (dipsw == 3) { - dipsw = 0; /* Only 00b, 01b and 10b settings are valid */ - } - /* Always reset to menu */ - reg[0] = reg[1] = 0; - Latch_RegReset(); -} - -static void M332Power(void) { - dipsw = 0; - reg[0] = reg[1] = 0; - Latch_Power(); - SetReadHandler(0x8000, 0xFFFF, M332Read); - SetWriteHandler(0x6000, 0x7FFF, M332Write); -} - -void Mapper332_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = M332Reset; - info->Power = M332Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper333.c b/src/mappers/mapper333.c deleted file mode 100644 index 6018f105f..000000000 --- a/src/mappers/mapper333.c +++ /dev/null @@ -1,72 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2016 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * 8-in-1 Rockin' Kats, Snake, (PCB marked as "8 in 1"), similar to 12IN1, - * but with MMC3 on board, all games are hacked the same, Snake is buggy too! - * - * no reset-citcuit, so selected game can be reset, but to change it you must use power - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M333CW(uint16 A, uint16 V) { - setchr1(A, ((reg & 0x0C) << 5) | (V & 0x7F)); -} - -static void M333PW(uint16 A, uint16 V) { - if (reg & 0x10) { /* MMC3 mode */ - setprg8(A, ((reg & 0x0C) << 2) | (V & 0x0F)); - } else { - setprg32(0x8000, reg & 0x0F); - } -} - -static DECLFW(M333Write) { - if (A & 0x1000) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } else { - MMC3_Write(A, V); - } -} - -static void M333Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x8000, 0xFFFF, M333Write); -} - -void Mapper333_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M333CW; - MMC3_pwrap = M333PW; - info->Power = M333Power; - AddExState(&StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper334.c b/src/mappers/mapper334.c deleted file mode 100644 index b2c94bc21..000000000 --- a/src/mappers/mapper334.c +++ /dev/null @@ -1,73 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M334PW(uint16 A, uint16 V) { - setprg32(0x8000, reg >> 1); -} - -static DECLFW(M334Write) { - if (!(A & 0x01) && MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - } -} - -static DECLFR(M334Read) { - if (A & 0x02) { - return ((CPU_OPENBUS & 0xFE) | (dipsw & 0x01)); - } - return CPU_OPENBUS; -} - -static void M334Reset(void) { - dipsw++; - reg = 0; - MMC3_Reset(); -} - -static void M334Power(void) { - dipsw = 0; - reg = 0; - MMC3_Power(); - SetReadHandler(0x6000, 0x7FFF, M334Read); - SetWriteHandler(0x6000, 0x7FFF, M334Write); -} - -void Mapper334_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M334PW; - info->Power = M334Power; - info->Reset = M334Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper335.c b/src/mappers/mapper335.c deleted file mode 100644 index 57a615976..000000000 --- a/src/mappers/mapper335.c +++ /dev/null @@ -1,77 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 mapper 335 is used for a 10-in-1 multicart. - * Its UNIF board name is BMC-CTC-09. - * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_335 */ - -#include "mapinc.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - if (reg[1] & 0x10) { - setprg16(0x8000, ((reg[1] & 0x07) << 1) | ((reg[1] >> 3) & 0x01)); - setprg16(0xC000, ((reg[1] & 0x07) << 1) | ((reg[1] >> 3) & 0x01)); - } else { - setprg32(0x8000, reg[1] & 0x07); - } - setchr8(reg[0] & 0x0F); - setmirror(((reg[1] >> 5) & 0x01) ^ 0x01); -} - -static DECLFW(M335Write) { - switch (A & 0xE000) { - case 0x8000: - case 0xA000: - reg[0] = V; - Sync(); - break; - case 0xC000: - case 0xE000: - reg[1] = V; - Sync(); - break; - } -} - -static void M335Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M335Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper335_Init(CartInfo *info) { - info->Power = M335Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper336.c b/src/mappers/mapper336.c deleted file mode 100644 index b3681b731..000000000 --- a/src/mappers/mapper336.c +++ /dev/null @@ -1,50 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* BMC-K-3046 */ -/* NES 2.0 mapper 336 is used for an 11-in-1 multicart - * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_336 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.data); - setprg16(0xC000, latch.data | 0x07); - setchr8(0); -} - -static DECLFW(M336Write) { - latch.addr = A; - latch.data = V | CartBR(A); - Sync(); -} - -static void M336Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M336Write); -} - -void Mapper336_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M336Power; - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper337.c b/src/mappers/mapper337.c deleted file mode 100644 index 83ae9f1bd..000000000 --- a/src/mappers/mapper337.c +++ /dev/null @@ -1,79 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 337 - BMC-CTC-12IN1 - * 12-in-1 Game Card multicart - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_337 - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint8 bank = reg & 0x1F; - - setprg8(0x6000, 1); - if (reg & 0x80) { /* UNROM */ - setprg16(0x8000, bank); - setprg16(0xC000, bank | 0x07); - } else { - if (reg & 0x40) { /* NROM-256 */ - setprg32(0x8000, bank >> 1); - } else { /* NROM-128 */ - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } - setchr8(0); - setmirror(((reg >> 5) & 0x01) ^ 0x01); -} - -static DECLFW(M337Write) { - if (A < 0xC000) { - reg = (reg & 0x07) | (V & ~0x07); - } else { - reg = (reg & ~0x07) | (V & 0x07); - } - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -static void M337Power(void) { - reg = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M337Write); -} - -void Mapper337_Init(CartInfo *info) { - info->Power = M337Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper338.c b/src/mappers/mapper338.c deleted file mode 100644 index 69c0c3f56..000000000 --- a/src/mappers/mapper338.c +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* BMC-SA005-A */ -/* NES 2.0 mapper 338 is used for a 16-in-1 and a 200/300/600/1000-in-1 multicart. - * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_338 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.addr); - setprg16(0xC000, latch.addr); - setchr8(latch.addr); - setmirror((latch.addr >> 3) & 0x01); -} - -void Mapper338_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper339.c b/src/mappers/mapper339.c deleted file mode 100644 index 72f7ce483..000000000 --- a/src/mappers/mapper339.c +++ /dev/null @@ -1,77 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 mapper 339 is used for a 21-in-1 multicart. - * Its UNIF board name is BMC-K-3006. - * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_339 - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M339CW(uint16 A, uint16 V) { - setchr1(A, ((reg << 4) & ~0x7F) | (V & 0x7F)); -} - -static void M339PW(uint16 A, uint16 V) { - uint16 base = reg & 0x1F; - - if (reg & 0x20) { /* MMC3 mode */ - setprg8(A, ((base << 1) & ~0x0F) | (V & 0x0F)); - } else { - if ((reg & 0x07) == 0x06) { /* NROM-256 */ - setprg32(0x8000, base >> 1); - } else { /* NROM-128 */ - setprg16(0x8000, base); - setprg16(0xC000, base); - } - } -} - -static DECLFW(M339Write) { - if (MMC3_WramIsWritable()) { - reg = A & 0x3F; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M339Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M339Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M339Write); -} - -void Mapper339_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = M339PW; - MMC3_cwrap = M339CW; - info->Power = M339Power; - info->Reset = M339Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper340.c b/src/mappers/mapper340.c deleted file mode 100644 index 5b0c026ab..000000000 --- a/src/mappers/mapper340.c +++ /dev/null @@ -1,50 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 340 - * UNIF BMC-K-3036 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint16 prg = ((latch.addr >> 2) & 0x20) | (latch.addr & 0x1F); - - if (latch.addr & 0x20) { /* NROM-128 */ - if (latch.addr & 0x01) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { /* NROM-256 */ - setprg32(0x8000, prg >> 1); - } - } else { /* UNROM */ - setprg16(0x8000, prg); - setprg16(0xC000, prg | 0x07); - } - SetupCartCHRMapping(0, CHRptr[0], 0x2000, (~latch.addr & 0x20)); - setchr8(0); - setmirror(((latch.addr & 0x40) || ((latch.addr & 0x20) && (latch.addr & 0x04))) ? MI_H : MI_V); -} - -void Mapper340_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper341.c b/src/mappers/mapper341.c deleted file mode 100644 index 4596abb58..000000000 --- a/src/mappers/mapper341.c +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* BMC-TJ-03 */ -/* NES 2.0 mapper 341 is used for a simple 4-in-1 multicart */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 mirr = (latch.addr & ((PRGsize[0] & 0x40000) ? 0x800 : 0x200)) ? MI_H : MI_V; - - setprg32(0x8000, latch.addr >> 8); - setchr8(latch.addr >> 8); - setmirror(mirr); -} - -void Mapper341_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper342.c b/src/mappers/mapper342.c deleted file mode 100644 index 1c2e9fc83..000000000 --- a/src/mappers/mapper342.c +++ /dev/null @@ -1,2304 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator -* -* Copyright notice for this file: -* Copyright (C) 2022 Cluster -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Very complicated homebrew multicart mapper with. -* The code is so obscured and weird because it's ported from Verilog CPLD source code: -* https://github.com/ClusterM/coolgirl-famicom-multicart/blob/master/CoolGirl_mappers.vh -* -* Range: $5000-$5FFF -* -* Mask: $5007 -* -* All registers are $00 on power-on and reset. -* -* $5xx0 -* 7 bit 0 -* ---- ---- -* PPPP PPPP -* |||| |||| -* ++++-++++-- PRG base offset (A29-A22) -* -* $5xx1 -* 7 bit 0 -* ---- ---- -* PPPP PPPP -* |||| |||| -* ++++-++++-- PRG base offset (A21-A14) -* -* $5xx2 -* 7 bit 0 -* ---- ---- -* AMMM MMMM -* |||| |||| -* |+++-++++-- PRG mask (A20-A14, inverted+anded with PRG address) -* +---------- CHR mask (A18, inverted+anded with CHR address) -* -* $5xx3 -* 7 bit 0 -* ---- ---- -* BBBC CCCC -* |||| |||| -* |||+-++++-- CHR bank A (bits 7-3) -* +++-------- PRG banking mode (see below) -* -* $5xx4 -* 7 bit 0 -* ---- ---- -* DDDE EEEE -* |||| |||| -* |||+-++++-- CHR mask (A17-A13, inverted+anded with CHR address) -* +++-------- CHR banking mode (see below) -* -* $5xx5 -* 7 bit 0 -* ---- ---- -* CDDE EEWW -* |||| |||| -* |||| ||++-- 8KiB WRAM page at $6000-$7FFF -* |+++-++---- PRG bank A (bits 5-1) -* +---------- CHR bank A (bit 8) -* -* $5xx6 -* 7 bit 0 -* ---- ---- -* FFFM MMMM -* |||| |||| -* |||+ ++++-- Mapper code (bits 4-0, see below) -* +++-------- Flags 2-0, functionality depends on selected mapper -* -* $5xx7 -* 7 bit 0 -* ---- ---- -* LMTR RSNO -* |||| |||+-- Enable WRAM (read and write) at $6000-$7FFF -* |||| ||+--- Allow writes to CHR RAM -* |||| |+---- Allow writes to flash chip -* |||+-+----- Mirroring (00=vertical, 01=horizontal, 10=1Sa, 11=1Sb) -* ||+-------- Enable four-screen mode -* |+-- ------ Mapper code (bit 5, see below) -* +---------- Lockout bit (prevent further writes to all registers) -* -*/ - -#include "mapinc.h" - -#define SAVE_FLASH_SIZE (1024 * 1024 * 8) -#define FLASH_SECTOR_SIZE (128 * 1024) -#define ROM_CHIP 0x00 -#define WRAM_CHIP 0x10 -#define FLASH_CHIP 0x11 -#define CFI_CHIP 0x13 - -static uint32 CHR_SIZE = 0; -static uint8 *SAVE_FLASH = NULL; -static uint8 *CFI = NULL; - -static uint8 sram_enabled = 0; -static uint8 sram_page = 0; /* [1:0] */ -static uint8 can_write_chr = 0; -static uint8 map_rom_on_6000 = 0; -static uint8 flags = 0; /* [2:0] */ -static uint8 mapper = 0; /* [5:0] */ -static uint8 can_write_flash = 0; -static uint8 mirroring = 0; /* [1:0] */ -static uint8 four_screen = 0; -static uint8 lockout = 0; - -static uint32 prg_base = 0; /* [26:14] */ -static uint32 prg_mask = 0xF8; /* 11111000, 128KB */ /* [20:14] */ -static uint8 prg_mode = 0; /* [2:0] */ -static uint8 prg_bank_6000 = 0; /* [7:0] */ -static uint8 prg_bank_a = 0; /* [7:0] */ -static uint8 prg_bank_b = 1; /* [7:0] */ -static uint8 prg_bank_c = ~1; /* [7:0] */ -static uint8 prg_bank_d = ~0; /* [7:0] */ - -static uint32 chr_mask = 0; /* [18:13] */ -static uint8 chr_mode = 0; /* [2:0] */ -static uint16 chr_bank_a = 0; /* [8:0] */ -static uint16 chr_bank_b = 1; /* [8:0] */ -static uint16 chr_bank_c = 2; /* [8:0] */ -static uint16 chr_bank_d = 3; /* [8:0] */ -static uint16 chr_bank_e = 4; /* [8:0] */ -static uint16 chr_bank_f = 5; /* [8:0] */ -static uint16 chr_bank_g = 6; /* [8:0] */ -static uint16 chr_bank_h = 7; /* [8:0] */ - -static uint8 TKSMIR[8]; - -static uint32 prg_bank_6000_mapped = 0; -static uint32 prg_bank_a_mapped = 0; -static uint32 prg_bank_b_mapped = 0; -static uint32 prg_bank_c_mapped = 0; -static uint32 prg_bank_d_mapped = 0; - -/* for MMC2/MMC4 */ -static uint8 ppu_latch0 = 0; -static uint8 ppu_latch1 = 0; -/* for MMC1 */ -static uint64 lreset = 0; -static uint8 mmc1_load_register = 0; /* [5:0] */ -/* for MMC3 */ -static uint8 mmc3_internal = 0; /* [2:0] */ -/* for mapper #69 */ -static uint8 mapper69_internal = 0; /* [3:0] */ -/* for mapper #112 */ -static uint8 mapper112_internal = 0; /* [2:0] */ -/* for mapper #163 */ -static uint8 mapper163_latch = 0; -static uint8 mapper163_r0 = 0; /* [7:0] */ -static uint8 mapper163_r1 = 0; /* [7:0] */ -static uint8 mapper163_r2 = 0; /* [7:0] */ -static uint8 mapper163_r3 = 0; /* [7:0] */ -static uint8 mapper163_r4 = 0; /* [7:0] */ -static uint8 mapper163_r5 = 0; /* [7:0] */ - -/* For mapper #90 */ -static uint8 mul1 = 0; -static uint8 mul2 = 0; - -/* for MMC3 scanline-based interrupts, counts A12 rises after long A12 falls */ -static uint8 mmc3_irq_enabled = 0; /* register to enable/disable counter */ -static uint8 mmc3_irq_latch = 0; /* [7:0], stores counter reload latch value */ -static uint8 mmc3_irq_counter = 0; /* [7:0], counter itself (downcounting) */ -static uint8 mmc3_irq_reload = 0; /* flag to reload counter from latch */ -/* for MMC5 scanline-based interrupts, counts dummy PPU reads */ -static uint8 mmc5_irq_enabled = 0; /* register to enable/disable counter */ -static uint8 mmc5_irq_line = 0; /* [7:0], scanline on which IRQ will be triggered */ -static uint8 mmc5_irq_out = 0; /* stores 1 when IRQ is triggered */ -/* for mapper #18 */ -static uint16 mapper18_irq_value = 0; /* [15:0], counter itself (downcounting) */ -static uint8 mapper18_irq_control = 0; /* [3:0], IRQ settings */ -static uint16 mapper18_irq_latch = 0; /* [15:0], stores counter reload latch value */ -/* for mapper #65 */ -static uint8 mapper65_irq_enabled = 0; /* register to enable/disable IRQ */ -static uint16 mapper65_irq_value = 0; /* [15:0], counter itself (downcounting) */ -static uint16 mapper65_irq_latch = 0; /* [15:0], stores counter reload latch value */ -/* reg mapper65_irq_out = 0; */ -/* for Sunsoft FME-7 */ -static uint8 mapper69_irq_enabled = 0; /* register to enable/disable IRQ */ -static uint8 mapper69_counter_enabled = 0; /* register to enable/disable counter */ -static uint16 mapper69_irq_value = 0; /* counter itself (downcounting) */ -/* for VRC4 CPU-based interrupts */ -static uint8 vrc4_irq_value = 0; /* [7:0], counter itself (upcounting) */ -static uint8 vrc4_irq_control = 0; /* [2:0]� IRQ settings */ -static uint8 vrc4_irq_latch = 0; /* [7:0], stores counter reload latch value */ -static uint8 vrc4_irq_prescaler = 0; /* [6:0], prescaler counter for VRC4 */ -static uint8 vrc4_irq_prescaler_counter = 0; /* prescaler cicles counter for VRC4 */ -/* for VRC3 CPU-based interrupts */ -static uint16 vrc3_irq_value = 0; /* [15:0], counter itself (upcounting) */ -static uint8 vrc3_irq_control = 0; /* [3:0], IRQ settings */ -static uint16 vrc3_irq_latch = 0; /* [15:0], stores counter reload latch value */ -/* for mapper #42 (only Baby Mario) */ -static uint8 mapper42_irq_enabled = 0; /* register to enable/disable counter */ -static uint16 mapper42_irq_value = 0; /* [14:0], counter itself (upcounting) */ -/* for mapper #83 */ -static uint8 mapper83_irq_enabled_latch = 0; -static uint8 mapper83_irq_enabled = 0; -static uint16 mapper83_irq_counter = 0; -/* for mapper #90 */ -static uint8 mapper90_xor = 0; -/* for mapper #67 */ -static uint8 mapper67_irq_enabled = 0; -static uint8 mapper67_irq_latch = 0; -static uint16 mapper67_irq_counter = 0; - -static uint8 flash_state = 0; -static uint16 flash_buffer_a[10]; -static uint8 flash_buffer_v[10]; -static uint8 cfi_mode = 0; - -static uint8 show_error_log = 0; -static uint8 vrc24_compatibility = 0; - -static uint8 ntaramExtra[0x800]; /* for 4-screen mirroring */ - -/* Micron 4-gbit memory CFI data */ -static const uint8 cfi_data[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0x52, 0x59, 0x02, 0x00, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x27, 0x36, 0x00, 0x00, 0x06, - 0x06, 0x09, 0x13, 0x03, 0x05, 0x03, 0x02, 0x1E, - 0x02, 0x00, 0x06, 0x00, 0x01, 0xFF, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, - 0x50, 0x52, 0x49, 0x31, 0x33, 0x14, 0x02, 0x01, - 0x00, 0x08, 0x00, 0x00, 0x02, 0xB5, 0xC5, 0x05, - 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -static void SyncPRG(void) { - uint8 REG_A_CHIP, REG_B_CHIP, REG_C_CHIP, REG_D_CHIP; - - prg_bank_6000_mapped = (prg_base << 1) | (prg_bank_6000 & ((~(prg_mask << 1) & 0xFE) | 1)); - prg_bank_a_mapped = (prg_base << 1) | (prg_bank_a & ((~(prg_mask << 1) & 0xFE) | 1)); - prg_bank_b_mapped = (prg_base << 1) | (prg_bank_b & ((~(prg_mask << 1) & 0xFE) | 1)); - prg_bank_c_mapped = (prg_base << 1) | (prg_bank_c & ((~(prg_mask << 1) & 0xFE) | 1)); - prg_bank_d_mapped = (prg_base << 1) | (prg_bank_d & ((~(prg_mask << 1) & 0xFE) | 1)); - REG_A_CHIP = (SAVE_FLASH != NULL && prg_bank_a_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP; - REG_B_CHIP = (SAVE_FLASH != NULL && prg_bank_b_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP; - REG_C_CHIP = (SAVE_FLASH != NULL && prg_bank_c_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP; - REG_D_CHIP = (SAVE_FLASH != NULL && prg_bank_d_mapped >= 0x20000 - SAVE_FLASH_SIZE / 1024 / 8) ? FLASH_CHIP : ROM_CHIP; - - if (!cfi_mode || !SAVE_FLASH) { - switch (prg_mode & 0x07) { - default: - case 0: - setprg16r(REG_A_CHIP, 0x8000, prg_bank_a_mapped >> 1); - setprg16r(REG_C_CHIP, 0xC000, prg_bank_c_mapped >> 1); - break; - case 1: - setprg16r(REG_C_CHIP, 0x8000, prg_bank_c_mapped >> 1); - setprg16r(REG_A_CHIP, 0xC000, prg_bank_a_mapped >> 1); - break; - case 4: - setprg8r(REG_A_CHIP, 0x8000, prg_bank_a_mapped); - setprg8r(REG_B_CHIP, 0xA000, prg_bank_b_mapped); - setprg8r(REG_C_CHIP, 0xC000, prg_bank_c_mapped); - setprg8r(REG_D_CHIP, 0xE000, prg_bank_d_mapped); - break; - case 5: - setprg8r(REG_C_CHIP, 0x8000, prg_bank_c_mapped); - setprg8r(REG_B_CHIP, 0xA000, prg_bank_b_mapped); - setprg8r(REG_A_CHIP, 0xC000, prg_bank_a_mapped); - setprg8r(REG_D_CHIP, 0xE000, prg_bank_d_mapped); - break; - case 6: - setprg32r(REG_B_CHIP, 0x8000, prg_bank_b_mapped >> 2); - break; - case 7: - setprg32r(REG_A_CHIP, 0x8000, prg_bank_a_mapped >> 2); - break; - } - } else { - setprg32r(CFI_CHIP, 0x8000, 0); - } - - if (!map_rom_on_6000 && WRAM) { - setprg8r(WRAM_CHIP, 0x6000, sram_page); /* Select SRAM page */ - } else if (map_rom_on_6000) { - setprg8(0x6000, prg_bank_6000_mapped); /* Map ROM on $6000-$7FFF */ - } -} - -static void SyncCHR(void) { - /* calculate CHR shift */ - /* wire shift_chr_right = ENABLE_MAPPER_021_022_023_025 && ENABLE_MAPPER_022 && (mapper == 6'b011000) && flags[1]; */ - int chr_shift = ((mapper == 24) && (flags & 2)) ? 1 : 0; - - /* enable or disable writes to CHR RAM, setup CHR mask */ - SetupCartCHRMapping(0, CHR_ROM_PTR, ((((~chr_mask & 0x3F) + 1) * 0x2000 - 1) & (CHR_SIZE - 1)) + 1, can_write_chr); - - switch (chr_mode & 0x07) { - default: - case 0: - setchr8(chr_bank_a >> 3 >> chr_shift); - break; - case 1: - setchr4(0x0000, mapper163_latch >> chr_shift); - setchr4(0x1000, mapper163_latch >> chr_shift); - break; - case 2: - setchr2(0x0000, chr_bank_a >> 1 >> chr_shift); - TKSMIR[0] = TKSMIR[1] = chr_bank_a; - setchr2(0x0800, chr_bank_c >> 1 >> chr_shift); - TKSMIR[2] = TKSMIR[3] = chr_bank_c; - setchr1(0x1000, chr_bank_e >> chr_shift); - TKSMIR[4] = chr_bank_e; - setchr1(0x1400, chr_bank_f >> chr_shift); - TKSMIR[5] = chr_bank_f; - setchr1(0x1800, chr_bank_g >> chr_shift); - TKSMIR[6] = chr_bank_g; - setchr1(0x1C00, chr_bank_h >> chr_shift); - TKSMIR[7] = chr_bank_h; - break; - case 3: - setchr1(0x0000, chr_bank_e >> chr_shift); - TKSMIR[0] = chr_bank_e; - setchr1(0x0400, chr_bank_f >> chr_shift); - TKSMIR[1] = chr_bank_f; - setchr1(0x0800, chr_bank_g >> chr_shift); - TKSMIR[2] = chr_bank_g; - setchr1(0x0C00, chr_bank_h >> chr_shift); - TKSMIR[3] = chr_bank_h; - setchr2(0x1000, chr_bank_a >> 1 >> chr_shift); - TKSMIR[4] = TKSMIR[5] = chr_bank_a; - setchr2(0x1800, chr_bank_c >> 1 >> chr_shift); - TKSMIR[6] = TKSMIR[7] = chr_bank_c; - break; - case 4: - setchr4(0x0000, chr_bank_a >> 2 >> chr_shift); - setchr4(0x1000, chr_bank_e >> 2 >> chr_shift); - break; - case 5: - if (!ppu_latch0) { - setchr4(0x0000, chr_bank_a >> 2 >> chr_shift); - } else { - setchr4(0x0000, chr_bank_b >> 2 >> chr_shift); - } - if (!ppu_latch1) { - setchr4(0x1000, chr_bank_e >> 2 >> chr_shift); - } else { - setchr4(0x1000, chr_bank_f >> 2 >> chr_shift); - } - break; - case 6: - setchr2(0x0000, chr_bank_a >> 1 >> chr_shift); - setchr2(0x0800, chr_bank_c >> 1 >> chr_shift); - setchr2(0x1000, chr_bank_e >> 1 >> chr_shift); - setchr2(0x1800, chr_bank_g >> 1 >> chr_shift); - break; - case 7: - setchr1(0x0000, chr_bank_a >> chr_shift); - setchr1(0x0400, chr_bank_b >> chr_shift); - setchr1(0x0800, chr_bank_c >> chr_shift); - setchr1(0x0C00, chr_bank_d >> chr_shift); - setchr1(0x1000, chr_bank_e >> chr_shift); - setchr1(0x1400, chr_bank_f >> chr_shift); - setchr1(0x1800, chr_bank_g >> chr_shift); - setchr1(0x1C00, chr_bank_h >> chr_shift); - break; - } -} - -static void SyncMIR(void) { - if (four_screen) { - /* setmirror(MI_4); */ - SetupCartMirroring(4, 0, ntaramExtra); - } else { - if (!((mapper == 20) && (flags & 1))) { /* Mapper #189? */ - switch (mirroring) { - case 0: - setmirror(MI_V); - break; - case 1: - setmirror(MI_H); - break; - case 2: - setmirror(MI_0); - break; - case 3: - setmirror(MI_1); - break; - } - } - } -} - -static void Sync(void) { - SyncPRG(); - SyncCHR(); - SyncMIR(); -} - -static DECLFW(COOLGIRL_Flash_Write) { - if (flash_state < sizeof(flash_buffer_a) / sizeof(flash_buffer_a[0])) { - flash_buffer_a[flash_state] = A & 0xFFF; - flash_buffer_v[flash_state] = V; - flash_state++; - - /* enter CFI mode */ - if ((flash_state == 1) && - (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0x98)) { - cfi_mode = 1; - flash_state = 0; - } - - /* sector erase */ - if ((flash_state == 6) && - (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) && - (flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) && - (flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0x80) && - (flash_buffer_a[3] == 0x0AAA) && (flash_buffer_v[3] == 0xAA) && - (flash_buffer_a[4] == 0x0555) && (flash_buffer_v[4] == 0x55) && - (flash_buffer_v[5] == 0x30)) { - int sector = prg_bank_a_mapped * 0x2000 / FLASH_SECTOR_SIZE; - uint32 sector_address = sector * FLASH_SECTOR_SIZE; - uint32 i; - for (i = sector_address; i < sector_address + FLASH_SECTOR_SIZE; i++) - SAVE_FLASH[i % SAVE_FLASH_SIZE] = 0xFF; - FCEU_printf("Flash sector #%d is erased: 0x%08x - 0x%08x.\n", sector, sector_address, sector_address + FLASH_SECTOR_SIZE - 1); - flash_state = 0; - } - - /* write byte */ - if ((flash_state == 4) && - (flash_buffer_a[0] == 0x0AAA) && (flash_buffer_v[0] == 0xAA) && - (flash_buffer_a[1] == 0x0555) && (flash_buffer_v[1] == 0x55) && - (flash_buffer_a[2] == 0x0AAA) && (flash_buffer_v[2] == 0xA0)) { - /*int sector = prg_bank_a_mapped * 0x2000 / FLASH_SECTOR_SIZE; */ - uint32 flash_addr = prg_bank_a_mapped * 0x2000 + (A % 0x8000); - if (SAVE_FLASH[flash_addr % SAVE_FLASH_SIZE] != 0xFF) { - if (!(show_error_log & 2)) { - FCEU_PrintError("Error: can't write to 0x%08x, flash sector is not erased.\n", flash_addr); - show_error_log |= 2; /* show error log only on reset or power-on */ - } - } else { - SAVE_FLASH[flash_addr % SAVE_FLASH_SIZE] = V; - } - flash_state = 0; - } - } - - /* not a command */ - if (((A & 0xFFF) != 0x0AAA) && ((A & 0xFFF) != 0x0555)) { - flash_state = 0; - } - - /* reset */ - if (V == 0xF0) { - flash_state = 0; - cfi_mode = 0; - } - - SyncPRG(); -} - -static DECLFW(M342Write) { - if (sram_enabled && A >= 0x6000 && A < 0x8000 && !map_rom_on_6000) { - CartBW(A, V); /* SRAM is enabled and writable */ - } - - if (SAVE_FLASH && can_write_flash && A >= 0x8000) { - /* writing flash */ - COOLGIRL_Flash_Write(A, V); - } - - /* block two writes in a row */ - if ((timestampbase + timestamp) < (lreset + 2)) { - return; - } - lreset = timestampbase + timestamp; - - if (A >= 0x5000 && A < 0x6000 && !lockout) { - switch (A & 0x07) { - case 0: - /* use bits 29-27 to simulate flash memory */ - prg_base = (prg_base & 0xFF) | (V << 8); - break; - case 1: - prg_base = (prg_base & 0xFF00) | V; - break; - case 2: - chr_mask = (chr_mask & 0x1F) | ((V & 0x80) >> 2); - prg_mask = V & 0x7F; - break; - case 3: - prg_mode = V >> 5; - chr_bank_a = (chr_bank_a & 0x07) | (V << 3); - break; - case 4: - chr_mode = V >> 5; - chr_mask = (chr_mask & 0x20) | (V & 0x1F); - break; - case 5: - chr_bank_a = (chr_bank_a & 0xFF) | ((V & 0x80) << 1); - prg_bank_a = (prg_bank_a & 0xC1) | ((V & 0x7C) >> 1); - sram_page = V & 0x03; - break; - case 6: - flags = V >> 5; - mapper = (mapper & 0x20) | (V & 0x1F); - break; - case 7: - lockout = V >> 7; - mapper = (mapper & 0x1F) | ((V & 0x40) >> 1); - four_screen = (V & 0x20) >> 5; - mirroring = (V & 0x18) >> 3; - can_write_flash = (V & 4) >> 2; - can_write_chr = (V & 2) >> 1; - sram_enabled = V & 1; - switch (mapper) { - case 14: - /* Mapper #65 - Irem's H3001 */ - prg_bank_b = 1; - break; - case 17: - /* MMC2 */ - prg_bank_b = ~2; - break; - case 23: - /* Mapper #42 */ - map_rom_on_6000 = 1; - break; - } - break; - } - if (lockout) { - FCEU_printf("mapper code = %d flags: %02x four-screen = %d\n", mapper, flags, four_screen); - } - } - - /* $0000-$7FFF */ - if (A < 0x8000) { - /* Mapper #163 */ - if (mapper == 6) { - if (A == 0x5101) { - if (mapper163_r4 && !V) { - mapper163_r5 ^= 1; - } - mapper163_r4 = V; - } else if (A == 0x5100 && V == 6) { - prg_mode = prg_mode & 0xFE; - prg_bank_b = 12; - } else { - if ((A & 0x7000) == 0x5000) { - switch ((A & 0x300) >> 8) { - case 2: - prg_mode |= 1; - prg_bank_a = (prg_bank_a & 0x3F) | ((V & 0x03) << 6); - mapper163_r0 = V; - break; - case 0: - prg_mode |= 1; - prg_bank_a = (prg_bank_a & 0xC3) | ((V & 0x0F) << 2); - chr_mode = (chr_mode & 0xFE) | (V >> 7); - mapper163_r1 = V; - break; - case 3: - mapper163_r2 = V; - break; - case 1: - mapper163_r3 = V; - break; - } - } - } - } - - /* Mapper #87 */ - if (mapper == 12) { - /* $6000-$7FFF */ - if ((A & 0x6000) == 0x6000) { - chr_bank_a = (chr_bank_a & 0xE7) | ((V & 0x01) << 4) | ((V & 0x02) << 2); - } - } - - /* Mapper #90 - JY */ - /* - if (mapper == 13) - { - switch (A) - { - case 0x5800: mul1 = V; break; - case 0x5801: mul2 = V; break; - } - } - */ - - /* MMC5 (not really) */ - if (mapper == 15) { - switch (A) { - case 0x5105: - if (V == 0xFF) { - four_screen = 1; - } else { - four_screen = 0; - switch (((V >> 2) & 0x01) | ((V >> 3) & 0x02)) { - case 0: - mirroring = 2; - break; - case 1: - mirroring = 0; - break; - case 2: - mirroring = 1; - break; - case 3: - mirroring = 3; - break; - } - } - break; - case 0x5115: - prg_bank_a = V & 0x1E; - prg_bank_b = (V & 0x1E) | 1; - break; - case 0x5116: - prg_bank_c = V & 0x1F; - break; - case 0x5117: - prg_bank_d = V & 0x1F; - break; - case 0x5120: - chr_bank_a = V; - break; - case 0x5121: - chr_bank_b = V; - break; - case 0x5122: - chr_bank_c = V; - break; - case 0x5123: - chr_bank_d = V; - break; - case 0x5128: - chr_bank_e = V; - break; - case 0x5129: - chr_bank_f = V; - break; - case 0x512A: - chr_bank_g = V; - break; - case 0x512B: - chr_bank_h = V; - break; - case 0x5203: - X6502_IRQEnd(FCEU_IQEXT); - mmc5_irq_out = 0; - mmc5_irq_line = V; - break; - case 0x5204: - X6502_IRQEnd(FCEU_IQEXT); - mmc5_irq_out = 0; - mmc5_irq_enabled = (V & 0x80) >> 7; - break; - } - } - - /* Mapper #189 */ - if (mapper == 20) { - /* $4120-$7FFF */ - if ((flags & 0x02) && (A >= 0x4120)) { - prg_bank_a = (prg_bank_a & 0xC3) | ((V & 0x0F) << 2) | ((V & 0xF0) >> 2); - } - } - - /* Mappers #79 and #146 - NINA-03/06 and Sachen 3015: (flag0 = 1) */ - if (mapper == 27) { - if ((A & 0x6100) == 0x4100) { - chr_bank_a = (chr_bank_a & 0xC7) | ((V & 0x07) << 3); - prg_bank_a = (chr_bank_a & 0xF8) | ((V & 0x08) >> 1); - } - } - - /* Mapper #133 */ - if (mapper == 28) { - if ((A & 0x6100) == 0x4100) { - chr_bank_a = (chr_bank_a & 0xE7) | ((V & 0x03) << 3); - prg_bank_a = (chr_bank_a & 0xF8) | (V & 0x04); - } - } - - /* Mapper #184 */ - if (mapper == 31) { - if ((A & 0x6000) == 0x6000) { - chr_bank_a = (chr_bank_a & 0xE3) | ((V & 0x07) << 2); - chr_bank_e = (chr_bank_e & 0xE3) | ((V & 0x30) >> 2) | 0x10; - } - } - - /* Mapper #38 */ - if (mapper == 32) { - if ((A & 0x7000) == 0x7000) { - prg_bank_a = (prg_bank_a & 0xF7) | ((V & 0x03) << 2); - chr_bank_a = (chr_bank_a & 0xE7) | ((V & 0x0C) << 1); - } - } - } else { /* $8000-$FFFF */ - /* Mapper #2 - UxROM */ - /* flag0 - mapper #71 - for Fire Hawk only. */ - /* other mapper-#71 games are UxROM */ - if (mapper == 1) { - if (!(flags & 0x01) || ((A & 0x7000) != 0x1000)) { - /* UxROM_BITSIZE = 4 */ - prg_bank_a = (prg_bank_a & 0xC1) | ((V & 0x1F) << 1); - if (flags & 0x02) { - /* One screen mirroring select, CHR RAM bank, PRG ROM bank */ - mirroring = 0x02 | (V >> 7); - chr_bank_a = (chr_bank_a & 0xFC) | ((V & 0x60) >> 5); - } - } else { - /* CodeMasters, blah. Mirroring control used only by Fire Hawk */ - mirroring = 0x02 | ((V >> 4) & 0x01); - } - } - - /* Mapper #3 - CNROM */ - if (mapper == 2) { - chr_bank_a = (chr_bank_a & 0x07) | ((V & 0x1F) << 3); - } - - /* Mapper #78 - Holy Diver */ - if (mapper == 3) { - prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x07) << 1); - chr_bank_a = (chr_bank_a & 0x87) | ((V & 0xF0) >> 1); - mirroring = ((V >> 3) & 1) ^ 1; - } - - /* Mapper #97 - Irem's TAM-S1 */ - if (mapper == 4) { - prg_bank_a = (prg_bank_a & 0xC1) | ((V & 0x1F) << 1); - mirroring = (V >> 7) ^ 1; - } - - /* Mapper #93 - Sunsoft-2 */ - if (mapper == 5) { - prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x70) >> 3); - can_write_chr = V & 0x01; - } - - /* Mapper #18 */ - if (mapper == 7) { - switch (((A & 0x7000) >> 10) | (A & 0x03)) { - case 0: /* $8000 */ - prg_bank_a = (prg_bank_a & 0xF0) | (V & 0x0F); - break; - case 1: /* $8001 */ - prg_bank_a = (prg_bank_a & 0x0F) | ((V & 0x0F) << 4); - break; - case 2: /* $8002 */ - prg_bank_b = (prg_bank_b & 0xF0) | (V & 0x0F); - break; - case 3: /* $8003 */ - prg_bank_b = (prg_bank_b & 0x0F) | ((V & 0x0F) << 4); - break; - case 4: /* $9000 */ - prg_bank_c = (prg_bank_c & 0xF0) | (V & 0x0F); - break; - case 5: /* $9001 */ - prg_bank_c = (prg_bank_c & 0x0F) | ((V & 0x0F) << 4); - break; - case 6: - break; - case 7: - break; - case 8: /* $A000 */ - chr_bank_a = (chr_bank_a & 0xF0) | (V & 0x0F); - break; - case 9: /* $A001 */ - chr_bank_a = (chr_bank_a & 0x0F) | ((V & 0x0F) << 4); - break; - case 10: /* $A002 */ - chr_bank_b = (chr_bank_b & 0xF0) | (V & 0x0F); - break; - case 11: /* $A003 */ - chr_bank_b = (chr_bank_b & 0x0F) | ((V & 0x0F) << 4); - break; - case 12: /* $B000 */ - chr_bank_c = (chr_bank_c & 0xF0) | (V & 0x0F); - break; - case 13: /* $B001 */ - chr_bank_c = (chr_bank_c & 0x0F) | ((V & 0x0F) << 4); - break; - case 14: /* $B002 */ - chr_bank_d = (chr_bank_d & 0xF0) | (V & 0x0F); - break; - case 15: /* $B003 */ - chr_bank_d = (chr_bank_d & 0x0F) | ((V & 0x0F) << 4); - break; - case 16: /* $C000 */ - chr_bank_e = (chr_bank_e & 0xF0) | (V & 0x0F); - break; - case 17: /* $C001 */ - chr_bank_e = (chr_bank_e & 0x0F) | ((V & 0x0F) << 4); - break; - case 18: /* $C002 */ - chr_bank_f = (chr_bank_f & 0xF0) | (V & 0x0F); - break; - case 19: /* $C003 */ - chr_bank_f = (chr_bank_f & 0x0F) | ((V & 0x0F) << 4); - break; - case 20: /* $D000 */ - chr_bank_g = (chr_bank_g & 0xF0) | (V & 0x0F); - break; - case 21: /* $D001 */ - chr_bank_g = (chr_bank_g & 0x0F) | ((V & 0x0F) << 4); - break; - case 22: /* $D002 */ - chr_bank_h = (chr_bank_h & 0xF0) | (V & 0x0F); - break; - case 23: /* $D003 */ - chr_bank_h = (chr_bank_h & 0x0F) | ((V & 0x0F) << 4); - break; - case 24: /* $E000 */ - mapper18_irq_latch = (mapper18_irq_latch & 0xFFF0) | (V & 0x0F); - break; - case 25: /* $E001 */ - mapper18_irq_latch = (mapper18_irq_latch & 0xFF0F) | ((V & 0x0F) << 4); - break; - case 26: /* $E002 */ - mapper18_irq_latch = (mapper18_irq_latch & 0xF0FF) | ((V & 0x0F) << 8); - break; - case 27: /* $E003 */ - mapper18_irq_latch = (mapper18_irq_latch & 0x0FFF) | ((V & 0x0F) << 12); - break; - case 28: /* $F000 */ - X6502_IRQEnd(FCEU_IQEXT); - mapper18_irq_value = mapper18_irq_latch; - break; - case 29: /* $F001 */ - X6502_IRQEnd(FCEU_IQEXT); - mapper18_irq_control = V & 0x0F; - break; - case 30: - switch (A & 3) { - case 0: - mirroring = 1; - break; /* Horz */ - case 1: - mirroring = 0; - break; /* Vert */ - case 2: - mirroring = 2; - break; /* 1SsA */ - case 3: - mirroring = 3; - break; /* 1SsB */ - } - break; - case 31: - break; /* sound */ - } - } - - /* Mapper #7 - AxROM, mapper #241 - BNROM */ - if (mapper == 8) { - prg_bank_a = (prg_bank_a & 0xC3) | ((V & 0x0F) << 2); - if (!(flags & 0x01)) { - mirroring = 0x02 | ((V >> 4) & 0x01); - } - } - - /* Mapper #228 - Cheetahmen II */ - if (mapper == 9) { - prg_bank_a = (prg_bank_a & 0xC3) | ((A & 0x0780) >> 5); - chr_bank_a = (chr_bank_a & 0x07) | ((A & 0x0007) << 5) | ((V & 0x03) << 3); - mirroring = (A >> 13) & 0x01; - } - - /* Mapper #11 - ColorDreams */ - if (mapper == 10) { - prg_bank_a = (prg_bank_a & 0xF3) | ((V & 0x03) << 2); - chr_bank_a = (chr_bank_a & 0x87) | ((V & 0xF0) >> 1); - } - - /* Mapper #66 - GxROM */ - if (mapper == 11) { - prg_bank_a = (prg_bank_a & 0xF3) | ((V & 0x30) >> 2); - chr_bank_a = (chr_bank_a & 0xE7) | ((V & 0x03) << 3); - } - - /* Mapper #90 - JY */ - if (mapper == 13) { - switch (A & 0xF000) { - case 0x8000: - switch (A & 0x03) { - case 0: - prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); - break; - case 1: - prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); - break; - case 2: - prg_bank_c = (prg_bank_c & 0xC0) | (V & 0x3F); - break; - case 3: - prg_bank_d = (prg_bank_d & 0xC0) | (V & 0x3F); - break; - } - break; - case 0x9000: - switch (A & 0x07) { - case 0: - chr_bank_a = V; - break; /* $9000 */ - case 1: - chr_bank_b = V; - break; /* $9001 */ - case 2: - chr_bank_c = V; - break; /* $9002 */ - case 3: - chr_bank_d = V; - break; /* $9003 */ - case 4: - chr_bank_e = V; - break; /* $9004 */ - case 5: - chr_bank_f = V; - break; /* $9005 */ - case 6: - chr_bank_g = V; - break; /* $9006 */ - case 7: - chr_bank_h = V; - break; /* $9007 */ - } - break; - case 0xC000: - /* use MMC3's IRQs */ - switch (A & 0x07) { - case 0: - if (V & 0x01) { - mmc3_irq_enabled = 1; - } else { - X6502_IRQEnd(FCEU_IQEXT); - mmc3_irq_enabled = 0; - } - break; - case 1: - break; /* who cares about this shit? */ - case 2: - mmc3_irq_enabled = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: - mmc3_irq_enabled = 1; - break; - case 4: - break; /* prescaler? who cares? */ - case 5: - mmc3_irq_latch = V ^ mapper90_xor; - mmc3_irq_reload = 1; - break; - case 6: - mapper90_xor = V; - break; - case 7: - break; /* meh */ - } - break; - case 0xD000: - if ((A & 0x03) == 1) { - mirroring = V & 0x03; - } - break; - } - } - - /* Mapper #65 - Irem's H3001 */ - if (mapper == 14) { - switch (((A & 0x7000) >> 9) | (A & 0x07)) { - case 0: /* $8000 */ - prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); - break; - case 9: /* $9001, mirroring */ - mirroring = (V >> 7) & 0x01; - break; - case 11: /* $9003, enable IRQ */ - X6502_IRQEnd(FCEU_IQEXT); - mapper65_irq_enabled = V >> 7; - break; - case 12: /* $9004 */ - X6502_IRQEnd(FCEU_IQEXT); /* mapper65_irq_out = 0; */ /* ack */ - mapper65_irq_value = mapper65_irq_latch; /* $9004, IRQ reload */ - break; - case 13: /* $9005, IRQ high V */ - mapper65_irq_latch = (mapper65_irq_latch & 0x00FF) | (V << 8); - break; - case 14: /* $9006, IRQ low V */ - mapper65_irq_latch = (mapper65_irq_latch & 0xFF00) | V; - break; - case 16: /* $A000 */ - prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); - break; - case 24: /* $B000 */ - chr_bank_a = V; - break; - case 25: /* $B001 */ - chr_bank_b = V; - break; - case 26: /* $B002 */ - chr_bank_c = V; - break; - case 27: /* $B003 */ - chr_bank_d = V; - break; - case 28: /* $B004 */ - chr_bank_e = V; - break; - case 29: /* $B005 */ - chr_bank_f = V; - break; - case 30:/* $B006 */ - chr_bank_g = V; - break; - case 31: /* $B007 */ - chr_bank_h = V; - break; - case 32: /* $C000 */ - prg_bank_c = (prg_bank_c & 0xC0) | (V & 0x3F); - break; - } - } - - /* Mapper #1 - MMC1 */ - /* - r0 - load register - flag0 - 16KB of SRAM (SOROM) - */ - if (mapper == 16) { - if (V & 0x80) { - /* reset */ - mmc1_load_register = (mmc1_load_register & 0xC0) | 0x20; - prg_mode = 0; - prg_bank_c = (prg_bank_c & 0xE0) | 0x1E; - } else { - mmc1_load_register = (mmc1_load_register & 0xC0) | ((V & 0x01) << 5) | - ((mmc1_load_register & 0x3E) >> 1); - if (mmc1_load_register & 0x01) { - switch (A & 0xE000) { - case 0x8000: - if ((mmc1_load_register & 0x18) == 0x18) { - prg_mode = 0; - prg_bank_c = (prg_bank_c & 0xE1) | 0x1E; - } else if ((mmc1_load_register & 0x18) == 0x10) { - prg_mode = 1; - prg_bank_c = (prg_bank_c & 0xE1); - } else { - prg_mode = 7; - } - if (mmc1_load_register & 0x20) { - chr_mode = 4; - } else { - chr_mode = 0; - } - mirroring = ((mmc1_load_register >> 1) & 0x03) ^ 2; - break; - case 0xA000: - chr_bank_a = (chr_bank_a & 0x83) | ((mmc1_load_register & 0x3E) << 1); - if (flags & 0x01) { - /* (flags[0]) - 16KB of SRAM */ - /* PRG RAM page #2 is battery backed */ - sram_page = 0x02 | (((mmc1_load_register >> 4) & 0x01) ^ 0x01); - } - prg_bank_a = (prg_bank_a & 0xDF) | (mmc1_load_register & 0x20); /* for SUROM, 512k PRG support */ - prg_bank_c = (prg_bank_c & 0xDF) | (mmc1_load_register & 0x20); /* for SUROM, 512k PRG support */ - break; - case 0xC000: - chr_bank_e = (chr_bank_e & 0x83) | ((mmc1_load_register & 0x3E) << 1); - break; - case 0xE000: - prg_bank_a = (prg_bank_a & 0xE1) | (mmc1_load_register & 0x1E); - sram_enabled = ((mmc1_load_register >> 5) & 0x01) ^ 0x01; - break; - } - mmc1_load_register = 0x20; - } - } - } - - /* Mapper #9 and #10 - MMC2 and MMC4 */ - /* flag0 - 0=MMC2, 1=MMC4 */ - if (mapper == 17) { - switch ((A >> 12) & 0x07) { - case 2: /* $A000-$AFFF */ - if (!(flags & 0x01)) { - /* MMC2 */ - prg_bank_a = (prg_bank_a & 0xF0) | (V & 0x0F); - } else { - /* MMC4 */ - prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0x0F) << 1); - } - break; - case 3: /* $B000-$BFFF */ - chr_bank_a = (chr_bank_a & 0x83) | ((V & 0x1F) << 2); - break; - case 4: /* $C000-$CFFF */ - chr_bank_b = (chr_bank_b & 0x83) | ((V & 0x1F) << 2); - break; - case 5: /* $D000-$DFFF */ - chr_bank_e = (chr_bank_e & 0x83) | ((V & 0x1F) << 2); - break; - case 6: /* $E000-$EFFF */ - chr_bank_f = (chr_bank_f & 0x83) | ((V & 0x1F) << 2); - break; - case 7: /* $F000-$FFFF */ - mirroring = V & 0x01; - break; - } - } - - /* Mapper #152 */ - if (mapper == 18) { - chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x0F) << 3); - prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x70) >> 3); - mirroring = 0x02 | (V >> 7); - } - - /* Mapper #73 - VRC3 */ - if (mapper == 19) { - switch (A & 0xF000) { - case 0x8000: - vrc3_irq_latch = (vrc3_irq_latch & 0xFFF0) | (V & 0x0F); - break; - case 0x9000: - vrc3_irq_latch = (vrc3_irq_latch & 0xFF0F) | ((V & 0x0F) << 4); - break; - case 0xA000: - vrc3_irq_latch = (vrc3_irq_latch & 0xF0FF) | ((V & 0x0F) << 8); - break; - case 0xB000: - vrc3_irq_latch = (vrc3_irq_latch & 0x0FFF) | ((V & 0x0F) << 12); - break; - case 0xC000: - X6502_IRQEnd(FCEU_IQEXT); /* ack */ - vrc3_irq_control = (vrc3_irq_control & 0xF8) | (V & 0x07); - if (vrc3_irq_control & 0x02) { - vrc3_irq_value = vrc3_irq_latch; - } - break; - case 0xD000: - X6502_IRQEnd(FCEU_IQEXT); /* ack */ - vrc3_irq_control = (vrc3_irq_control & 0xFD) | (vrc3_irq_control & 0x01) << 1; - break; - case 0xE000: - break; - case 0xF000: - prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x07) << 1); - break; - } - } - - /* Mapper #4 - MMC3/MMC6 */ - /* - flag0 - TxSROM - flag1 - mapper #189 - */ - if (mapper == 20) { - switch (((A & 0x6000) >> 12) | (A & 0x01)) { - case 0: /* $8000-$9FFE, even */ - mmc3_internal = (mmc3_internal & 0xF8) | (V & 0x07); - if (!(flags & 0x02) && !(flags & 0x04)) { - if (V & 0x40) { - prg_mode = 5; - } else { - prg_mode = 4; - } - } - if (!(flags & 0x04)) { - if (V & 0x80) { - chr_mode = 3; - } else { - chr_mode = 2; - } - } - break; - case 1: /* $8001-$9FFF, odd */ - switch (mmc3_internal & 0x07) { - case 0: - chr_bank_a = V; - break; - case 1: - chr_bank_c = V; - break; - case 2: - chr_bank_e = V; - break; - case 3: - chr_bank_f = V; - break; - case 4: - chr_bank_g = V; - break; - case 5: - chr_bank_h = V; - break; - case 6: - if (!(flags & 0x02)) { - prg_bank_a = V; - } - break; - case 7: - if (!(flags & 0x02)) { - prg_bank_b = V; - } - break; - } - break; - case 2: /* $A000-$BFFE, even (mirroring) */ - if (!(flags & 0x04)) { - mirroring = V & 0x01; - } - break; - case 3: /* RAM protect... no */ - break; - case 4: /* $C000-$DFFE, even (IRQ latch) */ - mmc3_irq_latch = V; - break; - case 5: /* $C001-$DFFF, odd */ - mmc3_irq_reload = 1; - break; - case 6: /* $E000-$FFFE, even */ - X6502_IRQEnd(FCEU_IQEXT); - mmc3_irq_enabled = 0; - break; - case 7: /* $E001-$FFFF, odd */ - if (!(flags & 0x04)) { - mmc3_irq_enabled = 1; - } - break; - } - } - - /* Mapper #112 */ - if (mapper == 21) { - switch (A & 0xE000) { - case 0x8000: - mapper112_internal = (mapper112_internal & 0xF8) | (V & 0x07); - break; - case 0xA000: - switch (mapper112_internal & 0x07) { - case 0: - prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); - break; - case 1: - prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); - break; - case 2: - chr_bank_a = V; - break; - case 3: - chr_bank_c = V; - break; - case 4: - chr_bank_e = V; - break; - case 5: - chr_bank_f = V; - break; - case 6: - chr_bank_g = V; - break; - case 7: - chr_bank_h = V; - break; - } - break; - case 0xC000: - break; - case 0xE000: - mirroring = V & 0x01; - break; - } - } - - /* Mappers #33 + #48 - Taito */ - /* flag0=0 - #33, flag0=1 - #48 */ - if (mapper == 22) { - switch (((A & 0x6000) >> 11) | (A & 0x03)) { - case 0: /* $8000, PRG Reg 0 (8k @ $8000) */ - prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); - if (!(flags & 0x01)) { /* 33 */ - mirroring = (V >> 6) & 0x01; - } - break; - case 1: /* $8001, PRG Reg 1 (8k @ $A000) */ - prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); - break; - case 2: /* $8002, CHR Reg 0 (2k @ $0000) */ - chr_bank_a = V << 1; - break; - case 3: /* $8003, CHR Reg 1 (2k @ $0800) */ - chr_bank_c = V << 1; - break; - case 4: /* $A000, CHR Reg 2 (1k @ $1000) */ - chr_bank_e = V; - break; - case 5: /* $A001, CHR Reg 2 (1k @ $1400) */ - chr_bank_f = V; - break; - case 6: /* $A002, CHR Reg 2 (1k @ $1800) */ - chr_bank_g = V; - break; - case 7: /* $A003, CHR Reg 2 (1k @ $1C00) */ - chr_bank_h = V; - break; - case 12: /* $E000, mirroring, for mapper #48 */ - if (flags & 0x01) { /* 48 */ - mirroring = (V >> 6) & 0x01; - } - break; - case 8: /* $C000, IRQ latch */ - mmc3_irq_latch = V ^ 0xFF; - break; - case 9: /* $C001, IRQ reload */ - mmc3_irq_reload = 1; - break; - case 10: /* $C002, IRQ enable */ - mmc3_irq_enabled = 1; - break; - case 11: /* $C003, IRQ disable & ack */ - mmc3_irq_enabled = 0; - X6502_IRQEnd(FCEU_IQEXT); /* ack */ - break; - } - } - - /* Mapper #42 */ - if (mapper == 23) { - switch (((A & 0x4000) >> 12) | (A & 3)) { - case 0: /* $8000, CHR Reg (8k @ $8000) */ - chr_bank_a = (chr_bank_a & 0xE0) | ((V & 0x1F) << 3); - break; - case 4: /* $E000, PRG Reg (8k @ $6000) */ - prg_bank_6000 = (prg_bank_6000 & 0xF0) | (V & 0x0F); - break; - case 5: /* Mirroring */ - mirroring = (V >> 3) & 0x01; - break; - case 6: /* IRQ */ - mapper42_irq_enabled = (V & 0x02) >> 1; - if (!mapper42_irq_enabled) { - X6502_IRQEnd(FCEU_IQEXT); - mapper42_irq_value = 0; - } - break; - } - } - - /* Mapper #23 - VRC2/4 */ - /* - flag0 - switches A0 and A1 lines. 0=A0,A1 like VRC2b (mapper #23), 1=A1,A0 like VRC2a(#22), VRC2c(#25) - flag1 - divides CHR bank select by two (mapper #22, VRC2a) - */ - if (mapper == 24) { - uint8 vrc_2b_hi = 0; - uint8 vrc_2b_low = 0; - uint8 vrc_2b_addr = 0; - - if (vrc24_compatibility) { - /* Compatibility code - for rom variants using the older firmware */ - vrc_2b_hi = ((A >> 1) & 0x01) | ((A >> 3) & 0x01) | ((A >> 5) & 0x01) | ((A >> 7) & 0x01); - vrc_2b_low = (A & 0x01) | ((A >> 2) & 0x01) | ((A >> 4) & 0x01) | ((A >> 6) & 0x01); - vrc_2b_addr = - (((flags & 0x01) ? vrc_2b_low : vrc_2b_hi) << 1) | - ((flags & 0x01) ? vrc_2b_hi : vrc_2b_low); - } else { - /* Updated code, not compatible with earlier VRC24 cart variants */ - switch (flags & 0x05) { - case 0: - vrc_2b_hi = (((A >> 7) & 0x01) | ((A >> 2) & 0x01)); /* mapper #21 */ - vrc_2b_low = (((A >> 6) & 0x01) | ((A >> 1) & 0x01)); /* mapper #21 */ - break; - case 1: - vrc_2b_hi = (A & 0x01); /* mapper #22 */ - vrc_2b_low = ((A >> 1) & 0x01); /* mapper #22 */ - break; - case 4: - vrc_2b_hi = (((A >> 5) & 0x01) | ((A >> 3) & 0x01) | ((A >> 1) & 0x01)); /* mapper #23 */ - vrc_2b_low = (((A >> 4) & 0x01) | ((A >> 2) & 0x01) | (A & 0x01)); /* mapper #23 */ - break; - default: - vrc_2b_hi = (((A >> 2) & 0x01) | (A & 0x01)); /* mapper #25 */ - vrc_2b_low = (((A >> 3) & 0x01) | ((A >> 1) & 0x01)); /* mapper #25 */ - break; - } - vrc_2b_addr = (vrc_2b_hi << 1) | vrc_2b_low; - } - - switch (((A >> 10) & 0x1C) | vrc_2b_addr) { - case 0: /* $8000-$8003, PRG0 */ - case 1: - case 2: - case 3: - prg_bank_a = (prg_bank_a & 0xE0) | (V & 0x1F); - break; - case 4: /* $9000-$9001, mirroring */ - case 5: - /* VRC2 - using games are usually well - behaved and only write 0 or 1 to this register, */ - /* but Wai Wai World in one instance writes $FF instead */ - if (V != 0xFF) { - mirroring = V & 0x03; - } - break; - case 6: /* $9002-$9004, PRG swap */ - case 7: - prg_mode = (prg_mode & 0xFE) | ((V >> 1) & 0x01); - break; - case 8: /* $A000-$A003, PRG1 */ - case 9: - case 10: - case 11: - prg_bank_b = (prg_bank_b & 0xE0) | (V & 0x1F); - break; - case 12: /* $B000, CHR0 low */ - chr_bank_a = (chr_bank_a & 0xF0) | (V & 0x0F); - break; - case 13: /* $B001, CHR0 hi */ - chr_bank_a = (chr_bank_a & 0x0F) | ((V & 0x0F) << 4); - break; - case 14: /* $B002, CHR1 low */ - chr_bank_b = (chr_bank_b & 0xF0) | (V & 0x0F); - break; - case 15: /* $B003, CHR1 hi */ - chr_bank_b = (chr_bank_b & 0x0F) | ((V & 0x0F) << 4); - break; - case 16: /* $C000, CHR2 low */ - chr_bank_c = (chr_bank_c & 0xF0) | (V & 0x0F); - break; - case 17: /* $C001, CHR2 hi */ - chr_bank_c = (chr_bank_c & 0x0F) | ((V & 0x0F) << 4); - break; - case 18: /* $C002, CHR3 low */ - chr_bank_d = (chr_bank_d & 0xF0) | (V & 0x0F); - break; - case 19: /* $C003, CHR3 hi */ - chr_bank_d = (chr_bank_d & 0x0F) | ((V & 0x0F) << 4); - break; - case 20: /* $D000, CHR4 low */ - chr_bank_e = (chr_bank_e & 0xF0) | (V & 0x0F); - break; - case 21: /* $D001, CHR4 hi */ - chr_bank_e = (chr_bank_e & 0x0F) | ((V & 0x0F) << 4); - break; - case 22: /* $D002, CHR5 low */ - chr_bank_f = (chr_bank_f & 0xF0) | (V & 0x0F); - break; - case 23: /* $D003, CHR5 hi */ - chr_bank_f = (chr_bank_f & 0x0F) | ((V & 0x0F) << 4); - break; - case 24: /* $E000, CHR6 low */ - chr_bank_g = (chr_bank_g & 0xF0) | (V & 0x0F); - break; - case 25: /* $E001, CHR6 hi */ - chr_bank_g = (chr_bank_g & 0x0F) | ((V & 0x0F) << 4); - break; - case 26: /* $E002, CHR7 low */ - chr_bank_h = (chr_bank_h & 0xF0) | (V & 0x0F); - break; - case 27: /* $E003, CHR7 hi */ - chr_bank_h = (chr_bank_h & 0x0F) | ((V & 0x0F) << 4); - break; - } - if ((A & 0x7000) == 0x7000) { - switch (vrc_2b_addr) { - case 0: /* IRQ latch low */ - vrc4_irq_latch = (vrc4_irq_latch & 0xF0) | (V & 0x0F); - break; - case 1: /* IRQ latch hi */ - vrc4_irq_latch = (vrc4_irq_latch & 0x0F) | ((V & 0x0F) << 4); - break; - case 2: /* IRQ control */ - X6502_IRQEnd(FCEU_IQEXT); /* ack */ - vrc4_irq_control = (vrc4_irq_control & 0xF8) | (V & 0x07); /* mode, enabled, enabled after ack */ - if (vrc4_irq_control & 0x02) { /* if E is set */ - vrc4_irq_prescaler_counter = 0; /* reset prescaler */ - vrc4_irq_prescaler = 0; - vrc4_irq_value = vrc4_irq_latch; /* reload with latch */ - } - break; - case 3: /* IRQ ack */ - X6502_IRQEnd(FCEU_IQEXT); - vrc4_irq_control = (vrc4_irq_control & 0xFD) | (vrc4_irq_control & 0x01) << 1; - break; - } - } - } - - /* Mapper #69 - Sunsoft FME-7 */ - if (mapper == 25) { - uint8 reg = (A & 0x6000) >> 13; - if (reg == 0) { - mapper69_internal = (mapper69_internal & 0xF0) | (V & 0x0F); - } - if (reg == 1) { - switch (mapper69_internal & 0x0F) { - case 0: /* CHR0 */ - chr_bank_a = V; - break; - case 1: /* CHR1 */ - chr_bank_b = V; - break; - case 2: /* CHR2 */ - chr_bank_c = V; - break; - case 3: /* CHR3 */ - chr_bank_d = V; - break; - case 4: /* CHR4 */ - chr_bank_e = V; - break; - case 5: /* CHR5 */ - chr_bank_f = V; - break; - case 6: /* CHR6 */ - chr_bank_g = V; - break; - case 7: /* CHR7 */ - chr_bank_h = V; - break; - case 8: /* PRG0 */ - sram_enabled = (V >> 7) & 0x01; - map_rom_on_6000 = ((V >> 6) & 0x01) ^ 0x01; - prg_bank_6000 = V & 0x3F; - break; - case 9: /* PRG1 */ - prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); - break; - case 10: /* PRG2 */ - prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); - break; - case 11: /* PRG3 */ - prg_bank_c = (prg_bank_c & 0xC0) | (V & 0x3F); - break; - case 12: /* mirroring */ - mirroring = V & 0x03; - break; - case 13: - X6502_IRQEnd(FCEU_IQEXT); /* ack */ - mapper69_counter_enabled = V >> 7; - mapper69_irq_enabled = V & 0x01; - break; - case 14: /* IRQ low */ - mapper69_irq_value = (mapper69_irq_value & 0xFF00) | V; - break; - case 15: /* IRQ high */ - mapper69_irq_value = (mapper69_irq_value & 0x00FF) | (V << 8); - break; - } - } - } - - /* Mapper #32 - Irem's G-101 */ - if (mapper == 26) { - switch (A & 0xF000) { - case 0x8000: - prg_bank_a = (prg_bank_a & 0xC0) | (V & 0x3F); - break; - case 0x9000: - prg_mode = (prg_mode & 0x06) | ((V >> 1) & 0x01); - mirroring = V & 0x01; - break; - case 0xA000: - prg_bank_b = (prg_bank_b & 0xC0) | (V & 0x3F); - break; - case 0xB000: - switch (A & 0x07) { - case 0: - chr_bank_a = V; - break; - case 1: - chr_bank_b = V; - break; - case 2: - chr_bank_c = V; - break; - case 3: - chr_bank_d = V; - break; - case 4: - chr_bank_e = V; - break; - case 5: - chr_bank_f = V; - break; - case 6: - chr_bank_g = V; - break; - case 7: - chr_bank_h = V; - break; - } - break; - } - } - - /* Mapper #36 is assigned to TXC's PCB 01-22000-400 */ - if (mapper == 29) { - if ((A & 0x7FFE) == 0x7FFE) { - prg_bank_a = (prg_bank_a & 0xC3) | ((V & 0xF0) >> 2); - chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x0F) << 3); - } - } - - /* Mapper #70 */ - if (mapper == 30) { - prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0xF0) >> 3); - chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x0F) << 3); - } - - /* Mapper #75 - VRC1 */ - if (mapper == 34) { - switch (A & 0xF000) { - case 0x8000: - prg_bank_a = (prg_bank_a & 0xF0) | (V & 0x0F); - break; - case 0x9000: - mirroring = V & 1; - chr_bank_a = (chr_bank_a & 0xBF) | ((V & 0x02) << 5); - chr_bank_e = (chr_bank_a & 0xBF) | ((V & 0x04) << 4); - break; - case 0xA000: /* $A000-$AFFF */ - prg_bank_b = (prg_bank_b & 0xF0) | (V & 0x0F); - break; - case 0xC000: - prg_bank_c = (prg_bank_c & 0xF0) | (V & 0x0F); - break; - case 0xE000: - chr_bank_a = (chr_bank_a & 0xC3) | ((V & 0x0F) << 2); - break; - case 0xF000: - chr_bank_e = (chr_bank_e & 0xC3) | ((V & 0x0F) << 2); - break; - } - } - - /* Mapper #83 - Cony/Yoko */ - /* TODO: Check for flags 4 needed? */ - if (mapper == 35) { - switch (A & 0x8300) { - case 0x8000: - prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0x0F) << 1); - break; - case 0x8100: /* $81xx */ - mirroring = V & 0x03; - prg_mode = (prg_mode & 0x03) | ((V >> 2) & 0x04); - map_rom_on_6000 = (V & 0x20) >> 5; - mapper83_irq_enabled_latch = (V & 0x80) >> 7; - break; - case 0x8200: - if (!(A & 0x01)) { - X6502_IRQEnd(FCEU_IQEXT); - mapper83_irq_counter = (mapper83_irq_counter & 0xFF00) | V; - } else { - mapper83_irq_enabled = mapper83_irq_enabled_latch; - mapper83_irq_counter = (mapper83_irq_counter & 0x00FF) | (V << 8); - } - break; - case 0x8300: - if (!(A & 0x10)) { - switch (A & 0x03) { - case 0: - prg_bank_a = V; - break; - case 1: - prg_bank_b = V; - break; - case 2: - prg_bank_b = V; - break; - case 3: - /* TODO: Verify this */ - prg_bank_6000 = V; - break; - } - } else { - if (!(flags & 0x04)) { - switch (A & 0x07) { - case 0: - chr_bank_a = V; - break; - case 1: - chr_bank_b = V; - break; - case 2: - chr_bank_c = V; - break; - case 3: - chr_bank_d = V; - break; - case 4: - chr_bank_e = V; - break; - case 5: - chr_bank_f = V; - break; - case 6: - chr_bank_g = V; - break; - case 7: - chr_bank_h = V; - break; - } - } else { - switch (A & 0x07) { - /* TODO: verify CHR mask */ - case 0: - chr_bank_a = (chr_bank_a & 0x01) | (V << 1); - break; - case 1: - chr_bank_c = (chr_bank_c & 0x01) | (V << 1); - break; - case 6: - chr_bank_e = (chr_bank_e & 0x01) | (V << 1); - break; - case 7: - chr_bank_g = (chr_bank_g & 0x01) | (V << 1); - break; - } - } - } - break; - } - } - - /* Mapper #67 - Sunsoft-3 */ - if (mapper == 36) { - if (A & 0x800) { - switch (A & 0xF800) { - case 0x8800: - chr_bank_a = (chr_bank_a & 0x81) | ((V & 0x3F) << 1); - break; - case 0x9800: - chr_bank_c = (chr_bank_c & 0x81) | ((V & 0x3F) << 1); - break; - case 0xA800: - chr_bank_e = (chr_bank_e & 0x81) | ((V & 0x3F) << 1); - break; - case 0xB800: - chr_bank_g = (chr_bank_g & 0x81) | ((V & 0x3F) << 1); - break; - case 0xC800: - mapper67_irq_latch = ~mapper67_irq_latch; - if (mapper67_irq_latch) { - mapper67_irq_counter = (mapper67_irq_counter & 0x00FF) | (V << 8); - } else { - mapper67_irq_counter = (mapper67_irq_counter & 0xFF00) | V; - } - break; - case 0xD800: - mapper67_irq_latch = 0; - mapper67_irq_enabled = (V & 0x10) >> 4; - break; - case 0xE800: - mirroring = V & 0x03; - break; - case 0xF800: - prg_bank_a = (prg_bank_a & 0xE1) | ((V & 0x0F) << 1); - break; - } - } else { - /* Interrupt Acknowledge ($8000) */ - X6502_IRQEnd(FCEU_IQEXT); - } - } - - /* Mapper #89 - Sunsoft-2 chip on the Sunsoft-3 board */ - if (mapper == 37) { - prg_bank_a = (prg_bank_a & 0xF1) | ((V & 0x70) >> 3); - chr_bank_a = (chr_bank_a & 0x87) | ((V & 0x80) >> 1) | ((V & 0x07) << 3); - mirroring = 2 | ((V & 0x08) >> 3); - } - } - - Sync(); -} - -static DECLFR(M342Read) { - if ((mapper == 0) && (A >= 0x5000) && (A < 0x6000)) - return 0; - - /* Mapper #163 */ - if (mapper == 6) { - if ((A & 0x7700) == 0x5100) { - return mapper163_r2 | mapper163_r0 | mapper163_r1 | ~mapper163_r3; - } - if ((A & 0x7700) == 0x5500) { - return (mapper163_r5 & 1) ? mapper163_r2 : mapper163_r1; - } - } - - /* Mapper #90 - JY */ - if (mapper == 13) { - if ((A == 0x5800)) { - return (mul1 * mul2) & 0xFF; - } - if ((A == 0x5801)) { - return ((mul1 * mul2) >> 8) & 0xFF; - } - } - - /* MMC5 */ - if (mapper == 15) { - if (A == 0x5204) { - uint8 ppuon = (PPU[1] & 0x18); - uint8 ret = (mmc5_irq_out << 7) | (!ppuon || ((scanline + 1) >= 241) ? 0 : 0x40); - X6502_IRQEnd(FCEU_IQEXT); - mmc5_irq_out = 0; - return ret; - } - } - - /* Mapper #36 is assigned to TXC's PCB 01-22000-400 */ - if ((mapper == 29) && ((A & 0xE100) == 0x4100)) { - return (prg_bank_a & 0x0C) << 2; - } - - /* Mapper #83 - Cony/Yoko */ - if ((mapper == 35) && ((A & 0x7000) == 0x5000)) { - return (flags & 3); - } - - if (sram_enabled && !map_rom_on_6000 && (A >= 0x6000) && (A < 0x8000)) { - return CartBR(A); /* SRAM */ - } - - if (map_rom_on_6000 && (A >= 0x6000) && (A < 0x8000)) { - return CartBR(A); /* PRG */ - } - - return CPU_OPENBUS; /* Open bus */ -} - -static void M342HBHook(void) { - /* for MMC3 and MMC3-based */ - if (mmc3_irq_reload || !mmc3_irq_counter) { - mmc3_irq_counter = mmc3_irq_latch; - mmc3_irq_reload = 0; - } else { - mmc3_irq_counter--; - } - if (!mmc3_irq_counter && mmc3_irq_enabled) { - X6502_IRQBegin(FCEU_IQEXT); - } - - /* for MMC5 */ - if (mmc5_irq_line == scanline + 1) { - if (mmc5_irq_enabled) { - X6502_IRQBegin(FCEU_IQEXT); - mmc5_irq_out = 1; - } - } - - /* for mapper #163 */ - if (scanline == 239) { - mapper163_latch = 0; - SyncCHR(); - } else if (scanline == 127) { - mapper163_latch = 1; - SyncCHR(); - } -} - -static void M342CPUHook(int a) { - while (a--) { - /* Mapper #23 - VRC4 */ - if (vrc4_irq_control & 0x02) { - vrc4_irq_prescaler++; /* count prescaler */ - if ((!(vrc4_irq_prescaler_counter & 0x02) && vrc4_irq_prescaler == 114) || - ((vrc4_irq_prescaler_counter & 0x02) && vrc4_irq_prescaler == 113)) { - vrc4_irq_prescaler = 0; - vrc4_irq_prescaler_counter++; - if (vrc4_irq_prescaler_counter == 3) { - vrc4_irq_prescaler_counter = 0; - } - vrc4_irq_value++; - if (vrc4_irq_value == 0) { /* if (carry) */ - X6502_IRQBegin(FCEU_IQEXT); - vrc4_irq_value = vrc4_irq_latch; - } - } - } - - /* Mapper #73 - VRC3 */ - if (vrc3_irq_control & 0x02) { - if (vrc3_irq_control & 0x04) { /* 8-bit mode */ - vrc3_irq_value = (vrc3_irq_value & 0xFF00) | ((vrc3_irq_value + 1) & 0xFF); - if ((vrc3_irq_value & 0xFF) == 0) { - X6502_IRQBegin(FCEU_IQEXT); - vrc3_irq_value = (vrc3_irq_value & 0xFF00) | (vrc3_irq_latch & 0xFF); - } - } else { /* 16-bit */ - vrc3_irq_value += 1; - if (vrc3_irq_value == 0) { - X6502_IRQBegin(FCEU_IQEXT); - vrc3_irq_value = vrc3_irq_latch; - } - } - } - - /* Mapper #69 - Sunsoft FME-7 */ - if (mapper69_counter_enabled) { - mapper69_irq_value--; - if (mapper69_irq_value == 0xFFFF) { - X6502_IRQBegin(FCEU_IQEXT); - } - } - - /* Mapper #18 */ - if (mapper18_irq_control & 0x01) { - uint8 carry; - carry = (mapper18_irq_value & 0x0F) - 1; - mapper18_irq_value = (mapper18_irq_value & 0xFFF0) | (carry & 0x0F); - carry = (carry >> 4) & 0x01; - if (!(mapper18_irq_control & 0x08)) { - carry = ((mapper18_irq_value >> 4) & 0x0F) - carry; - mapper18_irq_value = (mapper18_irq_value & 0xFF0F) | ((carry & 0x0F) << 4); - carry = (carry >> 4) & 0x01; - } - if (!(mapper18_irq_control & 0x0C)) { - carry = ((mapper18_irq_value >> 8) & 0x0F) - carry; - mapper18_irq_value = (mapper18_irq_value & 0xF0FF) | ((carry & 0x0F) << 8); - carry = (carry >> 4) & 0x01; - } - if (!(mapper18_irq_control & 0x0E)) { - carry = ((mapper18_irq_value >> 12) & 0x0F) - carry; - mapper18_irq_value = (mapper18_irq_value & 0x0FFF) | ((carry & 0x0F) << 12); - carry = (carry >> 4) & 0x01; - } - if (carry) { - X6502_IRQBegin(FCEU_IQEXT); - } - } - - /* Mapper #65 - Irem's H3001 */ - if (mapper65_irq_enabled) { - if (mapper65_irq_value != 0) { - mapper65_irq_value--; - if (!mapper65_irq_value) { - X6502_IRQBegin(FCEU_IQEXT); - } - } - } - - /* Mapper #42 */ - if (mapper42_irq_enabled) { - mapper42_irq_value++; - if (mapper42_irq_value >> 15) { - mapper42_irq_value = 0; - } - if (((mapper42_irq_value >> 13) & 0x03) == 3) { - X6502_IRQBegin(FCEU_IQEXT); - } else { - X6502_IRQEnd(FCEU_IQEXT); - } - } - - /* Mapper #83 - Cony/Yoko */ - if (mapper83_irq_enabled) { - if (mapper83_irq_counter == 0) { - X6502_IRQBegin(FCEU_IQEXT); - } - mapper83_irq_counter--; - } - - /* Mapper #67 - Sunsoft-3 */ - if (mapper67_irq_enabled) { - mapper67_irq_counter--; - if (mapper67_irq_counter == 0xFFFF) { - X6502_IRQBegin(FCEU_IQEXT); /* fire IRQ */ - mapper67_irq_enabled = 0; /* disable IRQ */ - } - } - } -} - -static void M342PPUHook(uint32 A) { - /* For TxROM */ - if ((mapper == 20) && (flags & 0x01)) { - setmirror(MI_0 + (TKSMIR[(A & 0x1FFF) >> 10] >> 7)); - } - - /* Mapper #9 and #10 - MMC2 and MMC4 */ - if (mapper == 17) { - if ((A >> 4) == 0xFD) { - ppu_latch0 = 0; - SyncCHR(); - } - if ((A >> 4) == 0xFE) { - ppu_latch0 = 1; - SyncCHR(); - } - if ((A >> 4) == 0x1FD) { - ppu_latch1 = 0; - SyncCHR(); - } - if ((A >> 4) == 0x1FE) { - ppu_latch1 = 1; - SyncCHR(); - } - } -} - -static void M342Reset(void) { - sram_enabled = 0; - sram_page = 0; - can_write_chr = 0; - map_rom_on_6000 = 0; - flags = 0; - mapper = 0; - can_write_flash = 0; - mirroring = 0; - four_screen = 0; - lockout = 0; - prg_base = 0; - prg_mask = 0xF8; - prg_mode = 0; - prg_bank_6000 = 0; - prg_bank_a = 0; - prg_bank_b = 1; - prg_bank_c = ~1; - prg_bank_d = ~0; - chr_mask = 0; - chr_mode = 0; - chr_bank_a = 0; - chr_bank_b = 1; - chr_bank_c = 2; - chr_bank_d = 3; - chr_bank_e = 4; - chr_bank_f = 5; - chr_bank_g = 6; - chr_bank_h = 7; - ppu_latch0 = 0; - ppu_latch1 = 0; - lreset = 0; - mmc1_load_register = 0; - mmc3_internal = 0; - mapper69_internal = 0; - mapper112_internal = 0; - mapper163_latch = 0; - mapper163_r0 = 0; - mapper163_r1 = 0; - mapper163_r2 = 0; - mapper163_r3 = 0; - mapper163_r4 = 0; - mapper163_r5 = 0; - mul1 = 0; - mul2 = 0; - mmc3_irq_enabled = 0; - mmc3_irq_latch = 0; - mmc3_irq_counter = 0; - mmc3_irq_reload = 0; - mmc5_irq_enabled = 0; - mmc5_irq_line = 0; - mmc5_irq_out = 0; - mapper18_irq_value = 0; - mapper18_irq_control = 0; - mapper18_irq_latch = 0; - mapper65_irq_enabled = 0; - mapper65_irq_value = 0; - mapper65_irq_latch = 0; - mapper69_irq_enabled = 0; - mapper69_counter_enabled = 0; - mapper69_irq_value = 0; - vrc4_irq_value = 0; - vrc4_irq_control = 0; - vrc4_irq_latch = 0; - vrc4_irq_prescaler = 0; - vrc4_irq_prescaler_counter = 0; - vrc3_irq_value = 0; - vrc3_irq_control = 0; - vrc3_irq_latch = 0; - mapper42_irq_enabled = 0; - mapper42_irq_value = 0; - mapper90_xor = 0; - flash_state = 0; - cfi_mode = 0; - show_error_log = 0; - Sync(); -} - -static void M342Power(void) { - FCEU_CheatAddRAM(32, 0x6000, WRAM); - SetReadHandler(0x4020, 0x7FFF, M342Read); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4020, 0xFFFF, M342Write); - M342Reset(); -} - -static void M342Close(void) { - if (SAVE_FLASH) { - FCEU_gfree(SAVE_FLASH); - } - - if (CFI) { - FCEU_gfree(CFI); - } - - SAVE_FLASH = CFI = NULL; -} - -static void StateRestore(int version) { - Sync(); - lreset = 0; -} - -#define ExState(var, varname) AddExState(&var, sizeof(var), 0, varname) - -void Mapper342_Init(CartInfo *info) { - int i; - - info->Power = M342Power; - info->Reset = M342Reset; - info->Close = M342Close; - GameStateRestore = StateRestore; - GameHBIRQHook = M342HBHook; - MapIRQHook = M342CPUHook; - PPU_hook = M342PPUHook; - - CHR_SIZE = info->CHRRamSize ? info->CHRRamSize : (512 * 1024) /* non-iNES2 or UNIF */; - - WRAMSIZE = (info->PRGRamSize + info->PRGRamSaveSize) ? (info->PRGRamSize + info->PRGRamSaveSize) : (32 * 1024); - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - memset(WRAM, 0, WRAMSIZE); - SetupCartPRGMapping(WRAM_CHIP, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } - - if (info->battery) { - SAVE_FLASH = (uint8 *)FCEU_gmalloc(SAVE_FLASH_SIZE); - SetupCartPRGMapping(FLASH_CHIP, SAVE_FLASH, SAVE_FLASH_SIZE, 1); - info->SaveGame[1] = SAVE_FLASH; - info->SaveGameLen[1] = SAVE_FLASH_SIZE; - } - - CFI = (uint8 *)FCEU_gmalloc(sizeof(cfi_data) * 2); - for (i = 0; i < (int)sizeof(cfi_data); i++) { - CFI[i * 2] = CFI[i * 2 + 1] = cfi_data[i]; - } - SetupCartPRGMapping(CFI_CHIP, CFI, sizeof(cfi_data) * 2, 0); - - switch (info->PRGCRC32) { - /* Earlier version of roms using VRC24 were using incorrect flags - * which are now incompatible with later updates of Coolgirl firmware causing - * graphics to be broken. This enables compatibily code to handle early roms while - * keeping the latest and updated VRC24 handling intact for newer roms when they become available. - */ - case 0xCF0FE3F3: /* 0b89251f6d63d49586ee3bbe41914ab7.unif */ - case 0x62BEFE75: /* 320 ¿úÓ äÑ¡ñ¿.unf */ - case 0xBF617289: /* d61e011f86b13bed9a22d3c56326e689.unif */ - case 0x3A70CB07: /* (MMK-02A-01) Gradius 10-in-1.nes */ - case 0x5352A128: /* (MMK-02D-00) Coolgirl 11-in-1.nes */ - case 0x861F89A0: /* (MMK-02E-00) Coolgirl 7-in-1.nes */ - case 0xA25CD951: /* (MMK-02F-00) Shooting Game 16-in-1.nes */ - case 0xE368F1F6: /* (MMK-033-00) Game 150-in-1.nes */ - case 0x49EE3B04: /* (YG-6014) Super Captain Tsubasa 2 Hack 6-in-1.nes (not using mapper code 24 but whatever) */ - case 0x7B85868B: /* (Yhc-4006-00) Super Konami 80-in-1.nes */ - case 0x2F0D22CD: /* (Yhc-BS-8165-01) Super Plane Game 11-in-1.nes */ - case 0x242B9218: /* (Yhc-CK-124-07) Super Konami 3-in-1.nes */ - vrc24_compatibility = 1; - break; - default: - vrc24_compatibility = 0; - break; - } - - ExState(sram_enabled, "SREN"); - ExState(sram_page, "SRPG"); - ExState(can_write_chr, "SRWR"); - ExState(map_rom_on_6000, "MR6K"); - ExState(flags, "FLGS"); - ExState(mapper, "MPPR"); - ExState(can_write_flash, "FLWR"); - ExState(mirroring, "MIRR"); - ExState(four_screen, "4SCR"); - ExState(lockout, "LOCK"); - - ExState(prg_base, "PBAS"); - ExState(prg_mask, "PMSK"); - ExState(prg_mode, "PMOD"); - ExState(prg_bank_6000, "P6BN"); - ExState(prg_bank_a, "PABN"); - ExState(prg_bank_b, "PBBN"); - ExState(prg_bank_c, "PCBN"); - ExState(prg_bank_d, "PDBN"); - ExState(prg_bank_6000_mapped, "P6BM"); - ExState(prg_bank_a_mapped, "PABM"); - ExState(prg_bank_b_mapped, "PBBM"); - ExState(prg_bank_c_mapped, "PCBM"); - ExState(prg_bank_d_mapped, "PDBM"); - - ExState(chr_mask, "CMSK"); - ExState(chr_mode, "CMOD"); - ExState(chr_bank_a, "CABN"); - ExState(chr_bank_b, "CBBN"); - ExState(chr_bank_c, "CCBN"); - ExState(chr_bank_d, "CDBN"); - ExState(chr_bank_e, "CEBN"); - ExState(chr_bank_f, "CFBN"); - ExState(chr_bank_g, "CGBN"); - ExState(chr_bank_h, "CHBN"); - - ExState(ppu_latch0, "PPU0"); - ExState(ppu_latch1, "PPU1"); - - ExState(lreset, "LRST"); - ExState(mmc1_load_register, "M01R"); - - ExState(mmc3_internal, "M01I"); - - ExState(mapper69_internal, "M69I"); - ExState(mapper112_internal, "112I"); - ExState(mapper163_latch, "163L"); - ExState(mapper163_r0, "1630"); - ExState(mapper163_r1, "1631"); - ExState(mapper163_r2, "1632"); - ExState(mapper163_r3, "1633"); - ExState(mapper163_r4, "1634"); - ExState(mapper163_r5, "1635"); - - ExState(mul1, "MUL1"); - ExState(mul2, "MUL2"); - - ExState(mmc3_irq_enabled, "M4IE"); - ExState(mmc3_irq_latch, "M4IL"); - ExState(mmc3_irq_counter, "M4IC"); - ExState(mmc3_irq_reload, "M4IR"); - - ExState(mmc5_irq_enabled, "M5IE"); - ExState(mmc5_irq_line, "M5IL"); - ExState(mmc5_irq_out, "M5IO"); - - ExState(mapper18_irq_value, "18IV"); - ExState(mapper18_irq_control, "18IC"); - ExState(mapper18_irq_latch, "18IL"); - - ExState(mapper65_irq_enabled, "65IE"); - ExState(mapper65_irq_value, "65IV"); - ExState(mapper65_irq_latch, "65IL"); - - ExState(mapper69_irq_enabled, "69IE"); - ExState(mapper69_counter_enabled, "69CE"); - ExState(mapper69_irq_value, "69IV"); - - ExState(vrc4_irq_value, "V4IV"); - ExState(vrc4_irq_control, "V4IC"); - ExState(vrc4_irq_latch, "V4IL"); - ExState(vrc4_irq_prescaler, "V4PP"); - ExState(vrc4_irq_prescaler_counter, "V4PC"); - - ExState(vrc3_irq_value, "V3IV"); - ExState(vrc3_irq_control, "V3IC"); - ExState(vrc3_irq_latch, "V3IL"); - - ExState(mapper42_irq_enabled, "42IE"); - ExState(mapper42_irq_value, "42IV"); - - ExState(mapper83_irq_enabled_latch, "M83L"); - ExState(mapper83_irq_enabled, "M83I"); - ExState(mapper83_irq_counter, "M83C"); - - ExState(mapper90_xor, "90XR"); - - ExState(mapper67_irq_enabled, "67IE"); - ExState(mapper67_irq_latch, "67IL"); - ExState(mapper67_irq_counter, "67IC"); - - ExState(flash_state, "FLST"); - ExState(flash_buffer_a, "FLBA"); - ExState(flash_buffer_v, "FLBV"); - - ExState(cfi_mode, "CFIM"); - - AddExState(ntaramExtra, 2048, 0, "ExRM"); -} diff --git a/src/mappers/mapper343.c b/src/mappers/mapper343.c deleted file mode 100644 index 54f56fc9d..000000000 --- a/src/mappers/mapper343.c +++ /dev/null @@ -1,54 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 343 - * BMC-RESETNROM-XIN1 - * - Sheng Tian 2-in-1(Unl,ResetBase)[p1] - Kung Fu (Spartan X), Super Mario Bros (alt) - * - Sheng Tian 2-in-1(Unl,ResetBase)[p2] - B-Wings, Twin-bee - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (iNESCart.submapper == 1) { - setprg32(0x8000, latch.data); - } else { - setprg16(0x8000, latch.data); - setprg16(0xC000, latch.data); - } - setchr8(latch.data); - setmirror((latch.data >> 7) & 0x01); -} - -static DECLFW(M343Write) { - Latch_Write(A, V ^ 0xFF); -} - -static void M343Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M343Write); -} - -void Mapper343_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M343Power; -} diff --git a/src/mappers/mapper344.c b/src/mappers/mapper344.c deleted file mode 100644 index 385afd70e..000000000 --- a/src/mappers/mapper344.c +++ /dev/null @@ -1,78 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 344 - * BMC-GN-26 - * Kuai Da Jin Ka Zhong Ji Tiao Zhan 3-in-1 (3-in-1,6-in-1,Unl) - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static uint8 prg_bank_order[2][4] = { - { 0, 1, 2, 3 }, /* normal bank order */ - { 0, 3, 1, 2 } /* wrong bank order, added for compatibility */ -}; - -static void M344CW(uint16 A, uint16 V) { - uint16 mask = (reg & 0x02) ? 0x7F : 0xFF; - uint16 base = (reg & 0x03) << 7; - - setchr1(A, base | (V & mask)); -} - -static void M344PW(uint16 A, uint16 V) { - uint8 base = prg_bank_order[(iNESCart.PRGCRC32 == 0xAB2ACA46)][reg & 0x03]; - - if (reg & 0x04) { - setprg32(0x8000, (base << 2) | ((mmc3.reg[6] & 0x0F) >> 2)); - } else { - setprg8(A, (base << 4) | (V & 0x0F)); - } -} - -static DECLFW(M344Write) { - if (MMC3_WramIsWritable()) { - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M344Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M344Power(void) { - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M344Write); -} - -void Mapper344_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M344PW; - MMC3_cwrap = M344CW; - info->Power = M344Power; - info->Reset = M344Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper345.c b/src/mappers/mapper345.c deleted file mode 100644 index 6807b82a0..000000000 --- a/src/mappers/mapper345.c +++ /dev/null @@ -1,76 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 345 - * BMC-L6IN1 - * New Star 6-in-1 Game Cartridge - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_345 - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M345PW(uint16 A, uint16 V) { - uint8 base = reg >> 6; - - if (reg & 0x0C) { - setprg8(A, (base << 4) | (V & 0x0F)); - } else { - setprg32(0x8000, (base << 2) | (reg & 0x03)); - } -} - -static void M345MIR(void) { - if (reg & 0x20) { - setmirror(MI_0 + ((reg & 0x10) >> 1)); - } else { - setmirror((mmc3.mirr & 0x01) ^ 0x01); - } -} - -static DECLFW(M345Write) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } -} - -static void M345Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M345Power(void) { - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M345Write); -} - -void Mapper345_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M345PW; - MMC3_FixMIR = M345MIR; - info->Power = M345Power; - info->Reset = M345Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper346.c b/src/mappers/mapper346.c deleted file mode 100644 index 22bbfcf8d..000000000 --- a/src/mappers/mapper346.c +++ /dev/null @@ -1,84 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 346 - Kaiser 7012 - * UNL-KS7012 - * FDS Conversion - * - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, reg); - setchr8(0); -} - -static DECLFW(M346Write) { -/* FCEU_printf("bs %04x %02x\n",A,V); */ - switch (A) { - case 0xE0A0: reg = 0; Sync(); break; - case 0xEE36: reg = 1; Sync(); break; - } -} - -static void M346Power(void) { - reg = 1; - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0xE000, 0xEFFF, M346Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M346Reset(void) { - reg = 1; - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -static void M346Close(void) { -} - -void Mapper346_Init(CartInfo *info) { - info->Power = M346Power; - info->Reset = M346Reset; - info->Close = M346Close; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper347.c b/src/mappers/mapper347.c deleted file mode 100644 index 7b7cfdc61..000000000 --- a/src/mappers/mapper347.c +++ /dev/null @@ -1,193 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 347 - Kaiser 7030 - * UNIF UNL-KS7030 - * FDS Conversion - Yume Koujou: Doki Doki Panic - * - * Logical bank layot 32 K BANK 0, 64K BANK 1, 32K ~0 hardwired, 8K is missing - * need redump from MASKROM! - * probably need refix mapper after hard dump - * - */ - -/* 2020-3-6 - update mirroring - * PRG-ROM Bank Select #1/Mirroring Select ($8000-$8FFF, write) - * A~FEDC BA98 7654 3210 - * ------------------- - * 1000 .... .... MBBB - * |+++- Select 4 KiB PRG-ROM bank at CPU $7000-$7FFF - * +---- Select nametable mirroring type - * 0: Vertical - * 1: Horizontal - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg[2]; -static void (*WSync)(void); - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -/* Legacy bank order */ - -/* 6000 - 6BFF - RAM - * 6C00 - 6FFF - BANK 1K REG1 - * 7000 - 7FFF - BANK 4K REG0 - * 8000 - B7FF - PRG - * B800 - BFFF - RAM - * C000 - CBFF - BANK 3K - * CC00 - D7FF - RAM - * D800 - FFFF - PRG - */ - -static void M347Sync2(void) { - setchr8(0); - setprg32(0x8000, ~0); - setprg4(0xb800, reg[0] & 0x07); - setprg4(0xc800, reg[1] + 8); - setmirror(((reg[0] >> 3) & 0x01) ^ 0x01); -} - -static DECLFR(M347Read2) { - if ((A >= 0x6000) && (A <= 0x6BFF)) { - return WRAM[A - 0x6000]; - } else if ((A >= 0x6C00) && (A <= 0x6FFF)) { - return CartBR(0xC800 + (A - 0x6C00)); - } else if ((A >= 0x7000) && (A <= 0x7FFF)) { - return CartBR(0xB800 + (A - 0x7000)); - } else if ((A >= 0xB800) && (A <= 0xBFFF)) { - return WRAM[0x0C00 + (A - 0xB800)]; - } else if ((A >= 0xC000) && (A <= 0xCBFF)) { - return CartBR(0xCC00 + (A - 0xC000)); - } else if ((A >= 0xCC00) && (A <= 0xD7FF)) { - return WRAM[0x1400 + (A - 0xCC00)]; - } else if ((A >= 0x8000) && (A <= 0xB7FF)) { - return CartBR(A); - } else if (A >= 0xD800) { - return CartBR(A); - } - return CPU_OPENBUS; -} - -static DECLFW(M347Write2) { - if ((A >= 0x6000) && (A <= 0x6BFF)) { - WRAM[A - 0x6000] = V; - } else if ((A >= 0x6C00) && (A <= 0x6FFF)) { - CartBW(0xC800 + (A - 0x6C00), V); - } else if ((A >= 0x7000) && (A <= 0x7FFF)) { - CartBW(0xB800 + (A - 0x7000), V); - } else if ((A >= 0xB800) && (A <= 0xBFFF)) { - WRAM[0x0C00 + (A - 0xB800)] = V; - } else if ((A >= 0xC000) && (A <= 0xCBFF)) { - CartBW(0xCC00 + (A - 0xC000), V); - } else if ((A >= 0xCC00) && (A <= 0xD7FF)) { - WRAM[0x1400 + (A - 0xCC00)] = V; - } else if ((A >= 0x8000) && (A <= 0x8FFF)) { - reg[0] = A & 0x0F; - WSync(); - } else if ((A >= 0x9000) && (A <= 0x9FFF)) { - reg[1] = A & 0x0F; - WSync(); - } -} -/* end of legacy bank order handling */ - -static void Sync(void) { - setchr8(0); - setprg32(0x8000, ~0); - if (reg[0] & 8) - setmirror(MI_H); - else - setmirror(MI_V); -} - -static DECLFR(M347Read) { - if (A >= 0x6000 && A <= 0x6BFF) { - return WRAM[A - 0x6000 + 0x00000]; - } else if (A >= 0x6C00 && A <= 0x6FFF) { - return PRGptr[0][A - 0x6000 + 0x01000 * reg[1] + 0x00000]; - } else if (A >= 0x7000 && A <= 0x7FFF) { - return PRGptr[0][A - 0x7000 + 0x01000 * (reg[0] & 0x07) + 0x10000]; - } else if (A >= 0xB800 && A <= 0xBFFF) { - return WRAM[A - 0xB800 + 0x00C00]; - } else if (A >= 0xC000 && A <= 0xCBFF) { - return PRGptr[0][A - 0xC000 + 0x01000 * reg[1] + 0x00000]; - } else if (A >= 0xCC00 && A <= 0xD7FF) { - return WRAM[A - 0xCC00 + 0x01400]; - } else if (A >= 0x8000) { - return PRGptr[0][A - 0x8000 + 0x18000]; - } - return CPU_OPENBUS; -} - -static DECLFW(M347Write) { - if (A >= 0x6000 && A <= 0x6BFF) { - WRAM[A - 0x6000 + 0x0000] = V; - } else if (A >= 0xB800 && A <= 0xBFFF) { - WRAM[A - 0xB800 + 0x0C00] = V; - } else if (A >= 0xCC00 && A <= 0xD7FF) { - WRAM[A - 0xCC00 + 0x1400] = V; - } else if (A >= 0x8000 && A <= 0x8FFF) { - reg[0] = A & 15; - WSync(); - } else if (A >= 0x9000 && A <= 0x9FFF) { - reg[1] = A & 15; - WSync(); - } -} - -static void M347Power(void) { - FDSSound_Power(); - reg[0] = reg[1] = ~0; - - if (iNESCart.PRGCRC32 == 0xFA4DAC91) { - SetReadHandler(0x6000, 0xFFFF, M347Read2); - SetWriteHandler(0x6000, 0xFFFF, M347Write2); - WSync = M347Sync2; - } else { - SetReadHandler(0x6000, 0xFFFF, M347Read); - SetWriteHandler(0x6000, 0xFFFF, M347Write); - WSync = Sync; - } - WSync(); -} - -static void M347Close(void) { -} - -static void StateRestore(int version) { - WSync(); -} - -void Mapper347_Init(CartInfo *info) { - info->Power = M347Power; - info->Close = M347Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper348.c b/src/mappers/mapper348.c deleted file mode 100644 index 10b6883af..000000000 --- a/src/mappers/mapper348.c +++ /dev/null @@ -1,77 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2008 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 348 - * M-022 MMC3 based 830118C T-106 4M + 4M */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M348CW(uint16 A, uint16 V) { - uint16 mask = 0x7F; - uint16 base = (reg << 5) & 0x180; - - setchr1(A, base | (V & mask)); -} - -static void M348PW(uint16 A, uint16 V) { - uint8 mask = 0x0F; - uint8 base = (reg << 2) & 0x30; - - if ((reg & 0x0C) == 0x0C) { - setprg8(0x8000, base | ((mmc3.reg[6] & ~0x02) & mask)); - setprg8(0xA000, base | ((mmc3.reg[7] & ~0x02) & mask)); - setprg8(0xC000, base | ((mmc3.reg[6] | 0x02) & mask)); - setprg8(0xE000, base | ((mmc3.reg[7] | 0x02) & mask)); - } else { - setprg8(A, base | (V & mask)); - } -} - -static DECLFW(M348Write) { - if (MMC3_WramIsWritable()) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M348Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M348Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6800, 0x68FF, M348Write); -} - -void Mapper348_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M348PW; - MMC3_cwrap = M348CW; - info->Power = M348Power; - info->Reset = M348Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper349.c b/src/mappers/mapper349.c deleted file mode 100644 index b3d07e6c1..000000000 --- a/src/mappers/mapper349.c +++ /dev/null @@ -1,45 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 349 - BMC-G-146 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x800) { /* UNROM mode */ - setprg16(0x8000, (latch.addr & 0x1F) | (latch.addr & ((latch.addr & 0x40) >> 6))); - setprg16(0xC000, (latch.addr & 0x1F) | 0x07); - } else { - if (latch.addr & 0x40) { /* 16K mode */ - setprg16(0x8000, latch.addr & 0x1F); - setprg16(0xC000, latch.addr & 0x1F); - } else { /* 32K mode */ - setprg32(0x8000, (latch.addr >> 1) & 0x0F); - } - } - setchr8(0); - setmirror(((latch.addr & 0x80) >> 7) ^ 0x01); -} - -void Mapper349_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper350.c b/src/mappers/mapper350.c deleted file mode 100644 index f349d0755..000000000 --- a/src/mappers/mapper350.c +++ /dev/null @@ -1,88 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 350 - BMC-891227 - * Super 15-in-1 Game Card - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_350 - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint8 bank = (reg[0] & 0x18) | (reg[1] & 0x07); - - setprg8(0x6000, 1); - if (reg[0] & 0x40) { /* UNROM */ - if (reg[0] & 0x20) { - /* 2nd chip only has 128K PRG */ - bank &= 0x07; - } - setprg16(0x8000, (reg[0] & 0x20) | bank); - setprg16(0xC000, (reg[0] & 0x20) | bank | 0x07); - } else { - if (reg[0] & 0x20) { /* NROM-256 */ - setprg32(0x8000, bank >> 1); - } else { - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } - /* CHR-RAM Protect... kinda */ - SetupCartCHRMapping(0, CHRptr[0], 0x2000, (reg[0] & 0x40) != 0); - setchr8(0); - setmirror(((reg[0] >> 7) & 0x01) ^ 0x01); -} - -static DECLFW(M350Write) { - reg[(A >> 14) & 0x01] = V; - Sync(); -} - -static void M350Reset(void) { - reg[0] = reg[1] = 0; - Sync(); -} - -static void M350Power(void) { - reg[0] = reg[1] = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M350Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper350_Init(CartInfo *info) { - info->Power = M350Power; - info->Reset = M350Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper351.c b/src/mappers/mapper351.c deleted file mode 100644 index 5cc411f1a..000000000 --- a/src/mappers/mapper351.c +++ /dev/null @@ -1,274 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc1.h" -#include "mmc3.h" -#include "vrc24.h" - -static uint8 reg[4], dipsw; - -static SFORMAT stateRegs[] = { - { reg, 4, "REGS" }, - { &dipsw, 1, "DIPS" }, - { 0 }, -}; - -static uint32 GetPRGMask(void) { - return ((reg[2] & 0x04) ? 0x0F : 0x1F); -} - -static uint32 GetPRGBase(void) { - return (reg[1] >> 1); -} - -static uint32 GetCHRMask(void) { - if ((reg[2] & 0x10) && !(reg[2] & 0x20)) { - return 0x1F; - } - return ((reg[2] & 0x20) ? 0x7F : 0xFF); -} - -static uint32 GetCHRBase(void) { - return (reg[0] << 1); -} - -static void M351MMC1PW(uint16 A, uint16 V) { - uint8 mask = GetPRGMask() >> 1; - uint8 bank = GetPRGBase() >> 1; - - setprg16(A, (bank & ~mask) | (V & mask)); -} - -static void M351MMC1CW(uint16 A, uint16 V) { - uint16 mask = GetCHRMask() >> 2; - uint16 bank = GetCHRBase() >> 2; - - setchr4(A, (bank & ~mask) | (V & mask)); -} - -static void M351MMC3PW(uint16 A, uint16 V) { - uint8 mask = GetPRGMask(); - uint8 bank = GetPRGBase(); - - setprg8(A, (bank & ~mask) | (V & mask)); -} - -static void M351MMC3CW(uint16 A, uint16 V) { - uint16 mask = GetCHRMask(); - uint16 bank = GetCHRBase(); - - setchr1(A, (bank & ~mask) | (V & mask)); -} - -static void M351VRC24PW(uint16 A, uint16 V) { - uint8 mask = GetPRGMask(); - uint8 bank = GetPRGBase(); - - setprg8(A, (bank & ~mask) | (V & mask)); -} - -static void M351VRC24CW(uint16 A, uint16 V) { - uint16 mask = GetCHRMask(); - uint16 bank = GetCHRBase(); - - setchr1(A, (bank & ~mask) | (V & mask)); -} - -static void SyncPRG(void) { - if (reg[2] & 0x10) { /* NROM mode */ - uint32 bank = GetPRGBase(); - - if (reg[2] & 0x08) { /* NROM-64 */ - setprg8(0x8000, bank); - setprg8(0xA000, bank); - setprg8(0xC000, bank); - setprg8(0xE000, bank); - } else { - if (reg[2] & 0x04) { /* NROM-128 */ - setprg16(0x8000, bank >> 1); - setprg16(0xC000, bank >> 1); - } else { /* NROM-256 */ - setprg32(0x8000, bank >> 2); - } - } - } else { - switch (reg[0] & 0x03) { - default: - case 1: MMC3_FixPRG(); break; - case 2: MMC1_FixPRG(); break; - case 3: VRC24_FixPRG(); break; - } - } -} - -static void SyncCHR(void) { - if (reg[2] & 0x01) { /* CHR RAM mode */ - setchr8r(0x10, 0); - } else if (reg[2] & 0x40) { /* CNROM mode */ - setchr8(GetCHRBase() >> 3); - } else { - switch (reg[0] & 0x03) { - default: - case 1: MMC3_FixCHR(); break; - case 2: MMC1_FixCHR(); break; - case 3: VRC24_FixCHR(); break; - } - } -} - -static void SyncMIR(void) { - switch (reg[0] & 0x03) { - default: - case 1: MMC3_FixMIR(); break; - case 2: MMC1_FixMIR(); break; - case 3: VRC24_FixMIR(); break; - } -} - -static void Sync(void) { - SyncPRG(); - SyncCHR(); - SyncMIR(); -} - -static void M351CPUHook(int a) { - if ((reg[0] & 0x03) == 0x03) { - VRC24_IRQCPUHook(a); - } -} - -static void M351HBHook(void) { - if (!(reg[0] & 0x02)) { /* MMC3 mode */ - MMC3_IRQHBHook(); - } -} - -static DECLFR(M351ReadDIP) { - return dipsw; -} - -static DECLFW(M351WriteMirr) { - /* FDS mirroring */ - mmc3.mirr = (V >> 3) & 0x01; - SyncMIR(); -} - -static DECLFW(M351WriteReg) { - reg[A & 0x03] = V; - Sync(); -} - -static DECLFW(M351Write) { - switch (reg[0] & 0x03) { - default: - case 1: - MMC3_Write(A, V); - Sync(); - break; - case 2: - MMC1_Write(A, V); - break; - case 3: - if (!(reg[2] & 0x04)) { - A = (A & 0xF800) | ((A >> 1) & 0x3FF); - } - if (A & 0x800) { - A = (A & 0xFFF3) | ((A << 1) & 0x08) | ((A >> 1) & 0x04); - } - VRC24_Write(A, V); - break; - } -} - -static void M351Power(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - dipsw = 0; - - VRC24_Reset(); - MMC1_Reset(); - MMC3_Reset(); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetReadHandler(0x5000, 0x5FFF, M351ReadDIP); - SetWriteHandler(0x4025, 0x4025, M351WriteMirr); - SetWriteHandler(0x5000, 0x5FFF, M351WriteReg); - SetWriteHandler(0x8000, 0xFFFF, M351Write); -} - -static void M531Reset(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - dipsw++; - - VRC24_Reset(); - MMC1_Reset(); - MMC3_Reset(); - - FCEU_printf(" Mapper Reset! dpsw:%d\n", dipsw); -} - -static void M351Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper351_Init(CartInfo *info) { - int CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; - - VRC24_Init(info, VRC2, 0x04, 0x08, FALSE, TRUE); - VRC24_pwrap = M351VRC24PW; - VRC24_cwrap = M351VRC24CW; - - MMC1_Init(info, FALSE, FALSE); - MMC1_pwrap = M351MMC1PW; - MMC1_cwrap = M351MMC1CW; - - MMC3_Init(info, FALSE, FALSE); - MMC3_pwrap = M351MMC3PW; - MMC3_cwrap = M351MMC3CW; - - info->Reset = M531Reset; - info->Power = M351Power; - info->Close = M351Close; - - MapIRQHook = M351CPUHook; - GameHBIRQHook = M351HBHook; - - GameStateRestore = StateRestore; - AddExState(stateRegs, ~0, 0, 0); - - if (CHR_ROM_SIZE) { - uint32 new_prg_size = PRG_ROM_SIZE; - /* This crazy thing can map CHR-ROM into CPU address space. Allocate a - * combined PRG+CHR address space and treat it a second "chip". */ - new_prg_size += CHR_ROM_SIZE; - PRG_ROM_PTR = (uint8 *)realloc(PRG_ROM_PTR, new_prg_size); - memcpy(PRG_ROM_PTR + new_prg_size, CHR_ROM_PTR, CHR_ROM_SIZE); - SetupCartPRGMapping(0, PRG_ROM_PTR, new_prg_size, 0); - } - - if (CHRRAMSIZE) { - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); - } -} diff --git a/src/mappers/mapper352.c b/src/mappers/mapper352.c deleted file mode 100644 index 5282a6449..000000000 --- a/src/mappers/mapper352.c +++ /dev/null @@ -1,62 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * NES 2.0 Mapper 352 - * BMC-KS106C - * - Kaiser 4-in-1(Unl,M352)[p1] - B-Wings, Kung Fu, 1942, SMB1 - */ - -#include "mapinc.h" - -static uint8 gameblock; - -static SFORMAT StateRegs[] = { - { &gameblock, 1, "GAME" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, gameblock); - setchr8(gameblock); - setmirror(gameblock & 0x01); -} - -static void M352Power(void) { - gameblock = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void M352Reset(void) { - gameblock++; - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper352_Init(CartInfo *info) { - info->Power = M352Power; - info->Reset = M352Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper353.c b/src/mappers/mapper353.c deleted file mode 100644 index 2f1489f99..000000000 --- a/src/mappers/mapper353.c +++ /dev/null @@ -1,163 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 353 is used for the 92 Super Mario Family multicart, - * consisting of an MMC3 clone ASIC together with a PAL. - * The PCB code is 81-03-05-C. - */ - -#include "mapinc.h" -#include "mmc3.h" -#include "fdssound.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M353PW(uint16 A, uint16 V) { - uint16 base = reg << 5; - uint16 mask = 0x1F; - - if (reg == 2) { - base |= (mmc3.reg[0] & 0x80) ? 0x10 : 0x00; - mask >>= 1; - } else if ((reg == 3) && !(mmc3.reg[0] & 0x80) && (A >= 0xC000)) { - base = 0x70; - mask = 0x0F; - V = mmc3.reg[6 + ((A >> 13) & 0x01)]; - } - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M353CW(uint16 A, uint16 V) { - uint16 mask = 0x7F; - uint16 base = reg << 7; - - if ((reg == 2) && (mmc3.reg[0] & 0x80)) { - setchr8r(0x10, 0); - } else { - setchr1(A, (base & ~mask) | (V & mask)); - } -} - -static void M353MIR(void) { - if (reg == 0) { - if (mmc3.cmd & 0x80) { - setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); - } else { - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); - } - } else { - setmirror((mmc3.mirr & 0x01) ^ 0x01); - } -} - -static DECLFW(M353Write) { - if (A & 0x80) { - reg = (A >> 13) & 0x03; - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } else { - uint8 oldcmd = mmc3.cmd; - - switch (A & 0xE001) { - case 0x8000: - mmc3.cmd = V; - if ((oldcmd & 0x40) != (mmc3.cmd & 0x40)) { - MMC3_FixPRG(); - } - if ((oldcmd & 0x80) != (mmc3.cmd & 80)) { - MMC3_FixCHR(); - MMC3_FixMIR(); - } - break; - case 0x8001: - mmc3.reg[mmc3.cmd & 0x07] = V; - switch (mmc3.cmd & 0x07) { - case 0: - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - case 1: - case 2: - case 3: - case 4: - case 5: - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - case 6: - case 7: - MMC3_FixPRG(); - break; - } - break; - default: - MMC3_Write(A, V); - break; - } - } -} - -static void M353Power(void) { - FDSSound_Power(); - reg = 0; - MMC3_Power(); - SetWriteHandler(0x8000, 0xFFFF, M353Write); -} - -static void M353Reset(void) { - reg = 0; - MMC3_Reset(); - FDSSoundRegReset(); - FDSSound_SC(); -} - -static void M353Close(void) { - MMC3_Close(); -} - -void Mapper353_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - MMC3_cwrap = M353CW; - MMC3_pwrap = M353PW; - MMC3_FixMIR = M353MIR; - info->Power = M353Power; - info->Close = M353Close; - info->Reset = M353Reset; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper354.c b/src/mappers/mapper354.c deleted file mode 100644 index 0e6147db6..000000000 --- a/src/mappers/mapper354.c +++ /dev/null @@ -1,87 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 354 denotes three different PCBs: - * - FAM250 for the 1992 巨作 250-in-1 劃面選關 鑽石巨王 multicart (iNESCart.submapper 0), - * - 810139C for the 1992 劃面選關 400-in-1 創新版 as well as an undumped 650-in-1 multicart (also iNESCart.submapper 0), - * - 810331C/SCHI-24 for the 1992 劃面選關 1050-in-1 multicart (iNESCart.submapper 1). - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint16 prg = ((latch.addr >> 5) & 0x80) | ((latch.addr << 2) & 0x40) | (latch.data & 0x3F); - - switch (latch.addr & 0x07) { - case 0: - case 4: - setprg32(0x8000, prg >> 1); - break; - case 1: - setprg16(0x8000, prg); - setprg16(0xC000, prg | 0x07); - break; - case 2: - case 6: - setprg8(0x8000, (prg << 1) | (latch.data >> 7)); - setprg8(0xA000, (prg << 1) | (latch.data >> 7)); - setprg8(0xC000, (prg << 1) | (latch.data >> 7)); - setprg8(0xE000, (prg << 1) | (latch.data >> 7)); - break; - case 3: - case 7: - setprg16(0x8000, prg); - setprg16(0xC000, prg); - break; - case 5: - setprg8(0x6000, (prg << 1) | (latch.data >> 7)); - setprg32(0x8000, (prg >> 1) | 0x03); - break; - } - /* CHR-RAM write protect */ - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], ((latch.addr >> 3) & 0x01) ^ 0x01); - setchr8(0); - setmirror(((latch.data >> 6) & 0x01) ^ 0x01); -} - -static DECLFW(M354Write) { - uint32 addr = 0xE000 | (iNESCart.submapper == 0) ? 0x1000 : 0; - - if (A < addr) { - return; - } - - latch.addr = A; - latch.data = V; - Sync(); -} - -static void M354_Power(void) { - Latch_Power(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M354Write); -} - -void Mapper354_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M354_Power; - info->Reset = Latch_RegReset; -} \ No newline at end of file diff --git a/src/mappers/mapper355.c b/src/mappers/mapper355.c deleted file mode 100644 index 4750768d0..000000000 --- a/src/mappers/mapper355.c +++ /dev/null @@ -1,135 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NOTE: This only emulates the UNIF variant of 3D-Blocks */ - -#include "mapinc.h" - -#include "mapper355.h" -#include "hw/pic16c5x.h" - -static uint32 address; -static uint8 *eprom = NULL; - -static uint8_t pci16c5x_read(int port) { - if (port == 0) { - return (1 | - (address & 0x0040 ? 0x02 : 0) | /* A6 -> RA1 */ - (address & 0x0020 ? 0x04 : 0) | /* A5 -> RA2 */ - (address & 0x0010 ? 0x08 : 0)); /* A4 -> RA3 */ - } else if (port == 1) { - return ( - (address & 0x1000 ? 0x01 : 0) | /* A12 -> RB0 */ - (address & 0x0080 ? 0x02 : 0) | /* A7 -> RB1 */ - (address & 0x0400 ? 0x04 : 0) | /* A10 -> RB2 */ - (address & 0x0800 ? 0x08 : 0) | /* A11 -> RB3 */ - (address & 0x0200 ? 0x10 : 0) | /* A9 -> RB4 */ - (address & 0x0100 ? 0x20 : 0) | /* A8 -> RB5 */ - (address & 0x2000 ? 0x40 : 0) | /* A13 -> RB6 */ - (address & 0x4000 ? 0x80 : 0)); /* A14 -> RB7 */ - } - return (0xFF); -} - -static void pci16c5x_write(int port, int val) { - if (port == 0) { - if (val & 0x1001) { - X6502_IRQEnd(FCEU_IQEXT); - } else { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void M355CPUIRQHook(int a) { - while (a--) { - pic16c5x_run(); - } -} - -static readfunc cpuRead[0x10000]; -static writefunc cpuWrite[0x10000]; - -static DECLFR(M555Read) { - address = A; - if (A >= 0x8000) { - return CartBR(A); - } - return cpuRead[A](A); -} - -static DECLFW(M555Write) { - address = A; - if (cpuWrite[A]) { - cpuWrite[A](A, V); - } -} - -static void M555Power(void) { - int x; - - address = 0; - - pic16c5x_reset(1); - - setprg32(0x8000, 0); - setchr8(0); - - for (x = 0; x < 0x10000; x++) { - cpuRead[x] = GetReadHandler(x); - cpuWrite[x] = GetWriteHandler(x); - } - - SetReadHandler(0, 0xFFFF, M555Read); - SetWriteHandler(0, 0xFFFF, M555Write); -} - -static void M555Reset(void) { - address = 0; - pic16c5x_reset(0); -} - -static void M555Close(void) { - eprom = NULL; -} - -void Mapper355_Init(CartInfo *info) { - if (MISC_ROM_SIZE && (MISC_ROM_SIZE == 1024)) { - eprom = MISC_ROM_PTR; - } else { - if (info->CRC32 == 0x86DBA660) { /* 3D Block (Hwang Shinwei) [!].nes */ - eprom = &eprom_3d_block[0]; - } else if ((info->CRC32 == 0x3C43939D) || /* Block Force.nes */ - (info->CRC32 == 0xB655C53A)) { /* Block Force (Hwang Shinwei).nes */ - eprom = &eprom_block_force[0]; - } - } - - if (eprom) { - pic16c54_init(eprom, pci16c5x_read, pci16c5x_write); - pic16c5x_add_statesinfo(); - } - - info->Power = M555Power; - info->Reset = M555Reset; - info->Close = M555Close; - MapIRQHook = M355CPUIRQHook; - AddExState(&address, sizeof(address), 0, "ADDR"); -} diff --git a/src/mappers/mapper355.h b/src/mappers/mapper355.h deleted file mode 100644 index 2b4c1d063..000000000 --- a/src/mappers/mapper355.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef _MAPPER_355_H -#define _MAPPER_355_H - -/* microcontroller ROM */ - -static uint8 eprom_3d_block[] = { - 0xFE, 0x0C, 0x05, 0x00, 0x00, 0x0C, 0x25, 0x00, 0x00, 0x00, 0xFF, 0x0C, 0x05, 0x00, 0x00, 0x08, - 0x28, 0x00, 0xE8, 0x02, 0x09, 0x0A, 0x00, 0x08, 0x28, 0x00, 0xE8, 0x02, 0x0D, 0x0A, 0xE9, 0x02, - 0x0D, 0x0A, 0x00, 0x08, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x06, 0x12, 0x0A, 0x00, 0x08, 0xE2, 0x01, - 0x00, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x00, 0x08, 0xFF, 0x08, 0xFF, 0x08, 0xFF, 0x08, - 0xE2, 0x01, 0xFF, 0x08, 0xFF, 0x08, 0x00, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x00, 0x08, - 0xFF, 0x08, 0xFF, 0x0C, 0x05, 0x00, 0xFF, 0x0C, 0x06, 0x00, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x07, - 0x2D, 0x0A, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x07, 0x2D, 0x0A, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x07, - 0x2D, 0x0A, 0x0E, 0x0C, 0x45, 0x01, 0x2A, 0x00, 0x43, 0x07, 0x44, 0x0A, 0x05, 0x0C, 0x29, 0x00, - 0x03, 0x0C, 0x0C, 0x09, 0x00, 0x09, 0x2D, 0x0A, 0x02, 0x0C, 0x8A, 0x01, 0x43, 0x07, 0x55, 0x0A, - 0x02, 0x0C, 0x29, 0x00, 0x05, 0x0C, 0x0C, 0x09, 0x00, 0x09, 0x0B, 0x0C, 0x29, 0x00, 0x90, 0x0C, - 0x08, 0x09, 0x00, 0x09, 0xE9, 0x02, 0x4F, 0x0A, 0x2D, 0x0A, 0x0E, 0x0C, 0x8A, 0x01, 0x43, 0x07, - 0x5C, 0x0A, 0xA0, 0x0C, 0x2B, 0x00, 0x2D, 0x0A, 0x04, 0x0C, 0x8A, 0x01, 0x43, 0x07, 0x98, 0x0A, - 0x02, 0x0C, 0x8B, 0x01, 0x43, 0x06, 0x2D, 0x0A, 0xEB, 0x00, 0xEB, 0x00, 0x03, 0x0C, 0x29, 0x00, - 0x2C, 0x0C, 0x0C, 0x09, 0x00, 0x09, 0x30, 0x0C, 0x2C, 0x00, 0x00, 0x0C, 0x2D, 0x00, 0x0B, 0x02, - 0x28, 0x00, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x07, 0x79, 0x0A, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x06, - 0x2D, 0x0A, 0xE8, 0x02, 0x71, 0x0A, 0x00, 0x09, 0x3B, 0x0C, 0x28, 0x00, 0xE2, 0x0C, 0x86, 0x01, - 0x43, 0x07, 0x86, 0x0A, 0xE2, 0x0C, 0x86, 0x01, 0x43, 0x06, 0x2D, 0x0A, 0xE8, 0x02, 0x7E, 0x0A, - 0x00, 0x09, 0x0B, 0x02, 0xEC, 0x01, 0x03, 0x07, 0x8E, 0x0A, 0xAD, 0x02, 0x3B, 0x0C, 0xEC, 0x01, - 0x03, 0x07, 0x93, 0x0A, 0xAD, 0x02, 0x02, 0x0C, 0x8D, 0x00, 0x03, 0x07, 0x6F, 0x0A, 0x2D, 0x0A, - 0x08, 0x0C, 0x8A, 0x01, 0x43, 0x07, 0xA1, 0x0A, 0x08, 0x0C, 0x2E, 0x00, 0xF0, 0x0C, 0x24, 0x00, - 0x5A, 0x0B, 0x0A, 0x0C, 0x8A, 0x01, 0x43, 0x07, 0xA7, 0x0A, 0x03, 0x04, 0xAC, 0x0A, 0x0C, 0x0C, - 0x8A, 0x01, 0x43, 0x07, 0x5D, 0x0B, 0x03, 0x05, 0x60, 0x03, 0xEE, 0x00, 0x43, 0x07, 0x5A, 0x0B, - 0x08, 0x0C, 0x2E, 0x00, 0xA4, 0x02, 0xF4, 0x0C, 0x84, 0x01, 0x43, 0x07, 0x5A, 0x0B, 0x1F, 0x0C, - 0x53, 0x01, 0x37, 0x00, 0x33, 0x03, 0x33, 0x03, 0x33, 0x03, 0x33, 0x03, 0x33, 0x03, 0x07, 0x0C, - 0x53, 0x01, 0x3A, 0x00, 0x0F, 0x0C, 0x52, 0x01, 0x39, 0x00, 0x28, 0x00, 0x32, 0x03, 0x32, 0x03, - 0x32, 0x03, 0x32, 0x03, 0x0F, 0x0C, 0x52, 0x01, 0x38, 0x00, 0x07, 0x0C, 0x51, 0x01, 0x35, 0x00, - 0x31, 0x03, 0x31, 0x03, 0x31, 0x03, 0x07, 0x0C, 0x51, 0x01, 0x34, 0x00, 0x31, 0x03, 0x31, 0x03, - 0x31, 0x03, 0x03, 0x0C, 0x51, 0x01, 0x33, 0x00, 0x07, 0x0C, 0x50, 0x01, 0x32, 0x00, 0x30, 0x03, - 0x30, 0x03, 0x30, 0x03, 0x07, 0x0C, 0x50, 0x01, 0x31, 0x00, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, - 0x03, 0x0C, 0x50, 0x01, 0x30, 0x00, 0x07, 0x0C, 0x79, 0x01, 0x28, 0x03, 0x04, 0x0C, 0x48, 0x01, - 0x33, 0x01, 0x08, 0x0C, 0x57, 0x01, 0x43, 0x06, 0xF6, 0x0A, 0xB8, 0x02, 0x10, 0x0C, 0x57, 0x01, - 0x43, 0x06, 0x06, 0x0B, 0x07, 0x0C, 0x77, 0x01, 0x17, 0x02, 0x17, 0x09, 0xF9, 0x01, 0xF9, 0x06, - 0xB9, 0x00, 0x17, 0x02, 0x20, 0x09, 0xFA, 0x01, 0xFA, 0x06, 0xBA, 0x00, 0x7B, 0x00, 0x02, 0x0C, - 0xB1, 0x00, 0x71, 0x02, 0xB1, 0x02, 0xF1, 0x06, 0x13, 0x0B, 0x19, 0x02, 0x91, 0x00, 0x03, 0x07, - 0x13, 0x0B, 0x11, 0x02, 0x39, 0x00, 0x02, 0x0C, 0xB2, 0x00, 0x72, 0x02, 0xB2, 0x02, 0xF2, 0x06, - 0x1F, 0x0B, 0x1A, 0x02, 0x92, 0x00, 0x03, 0x07, 0x1F, 0x0B, 0x12, 0x02, 0x3A, 0x00, 0x02, 0x0C, - 0xB0, 0x00, 0x70, 0x02, 0xB0, 0x02, 0xF0, 0x06, 0x2B, 0x0B, 0x18, 0x02, 0x90, 0x00, 0x03, 0x07, - 0x2B, 0x0B, 0x10, 0x02, 0x38, 0x00, 0x02, 0x0C, 0xB4, 0x00, 0x05, 0x0C, 0xB4, 0x00, 0x74, 0x02, - 0xB4, 0x02, 0xF4, 0x06, 0x39, 0x0B, 0x19, 0x02, 0x94, 0x00, 0x03, 0x06, 0x39, 0x0B, 0x14, 0x02, - 0x39, 0x00, 0x02, 0x0C, 0xB5, 0x00, 0x05, 0x0C, 0xB5, 0x00, 0x75, 0x02, 0xB5, 0x02, 0xF5, 0x06, - 0x47, 0x0B, 0x1A, 0x02, 0x95, 0x00, 0x03, 0x06, 0x47, 0x0B, 0x15, 0x02, 0x3A, 0x00, 0x02, 0x0C, - 0xB3, 0x00, 0x0A, 0x0C, 0xB3, 0x00, 0x73, 0x02, 0xB3, 0x02, 0xF3, 0x06, 0x58, 0x0B, 0x18, 0x02, - 0x93, 0x00, 0x43, 0x06, 0x57, 0x0B, 0x03, 0x06, 0x58, 0x0B, 0x13, 0x02, 0x38, 0x00, 0xBB, 0x02, - 0xF8, 0x0C, 0x24, 0x00, 0x12, 0x09, 0x00, 0x09, 0x2D, 0x0A, 0x12, 0x09, 0x00, 0x02, 0x43, 0x06, - 0x67, 0x0B, 0x03, 0x0C, 0x08, 0x09, 0x00, 0x09, 0xE0, 0x00, 0x43, 0x07, 0x61, 0x0B, 0xA4, 0x02, - 0x2D, 0x0A, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x29, 0x0A -}; - -static uint8 eprom_block_force[] = { - 0xFE, 0x0C, 0x05, 0x00, 0x05, 0x05, 0xFF, 0x0C, 0x06, 0x00, 0x02, 0x0C, 0x3A, 0x00, 0x00, 0x0C, - 0x3B, 0x00, 0x05, 0x0C, 0x3C, 0x00, 0x06, 0x0C, 0x3D, 0x00, 0x00, 0x0C, 0x3E, 0x00, 0x00, 0x0C, - 0x3F, 0x00, 0xDD, 0x0C, 0x86, 0x01, 0x43, 0x07, 0x11, 0x0A, 0xDD, 0x0C, 0x86, 0x01, 0x43, 0x06, - 0x15, 0x0A, 0xDF, 0x0C, 0x86, 0x01, 0x43, 0x07, 0x11, 0x0A, 0x0F, 0x0C, 0x45, 0x01, 0xE2, 0x01, - 0x30, 0x0A, 0x30, 0x0A, 0x38, 0x0A, 0x38, 0x0A, 0x34, 0x0A, 0x34, 0x0A, 0x48, 0x0A, 0x48, 0x0A, - 0x32, 0x0A, 0x32, 0x0A, 0x44, 0x0A, 0x44, 0x0A, 0x36, 0x0A, 0x36, 0x0A, 0x4B, 0x0A, 0x4B, 0x0A, - 0x64, 0x00, 0x11, 0x0A, 0xA4, 0x02, 0x11, 0x0A, 0x60, 0x00, 0x11, 0x0A, 0xA0, 0x02, 0x11, 0x0A, - 0x10, 0x02, 0x32, 0x00, 0x11, 0x02, 0x33, 0x00, 0xF2, 0x02, 0x3C, 0x0A, 0xF3, 0x02, 0x3C, 0x0A, - 0x05, 0x04, 0x05, 0x04, 0x05, 0x05, 0x11, 0x0A, 0x08, 0x02, 0xE2, 0x01, 0x50, 0x0A, 0x88, 0x0A, - 0x00, 0x02, 0x27, 0x00, 0x11, 0x0A, 0xE7, 0x02, 0x11, 0x0A, 0x05, 0x04, 0x05, 0x05, 0x11, 0x0A, - 0x19, 0x02, 0x9F, 0x00, 0x43, 0x06, 0x57, 0x0A, 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x18, 0x02, - 0x9E, 0x00, 0x43, 0x06, 0x5E, 0x0A, 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x17, 0x02, 0x9D, 0x00, - 0x43, 0x06, 0x65, 0x0A, 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x16, 0x02, 0x9C, 0x00, 0x43, 0x06, - 0x6C, 0x0A, 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x15, 0x02, 0x9B, 0x00, 0x43, 0x06, 0x73, 0x0A, - 0x03, 0x07, 0x7B, 0x0A, 0x11, 0x0A, 0x14, 0x02, 0x9A, 0x00, 0x43, 0x06, 0x7A, 0x0A, 0x03, 0x07, - 0x7B, 0x0A, 0x11, 0x0A, 0x11, 0x0A, 0x14, 0x02, 0x3A, 0x00, 0x15, 0x02, 0x3B, 0x00, 0x16, 0x02, - 0x3C, 0x00, 0x17, 0x02, 0x3D, 0x00, 0x18, 0x02, 0x3E, 0x00, 0x19, 0x02, 0x3F, 0x00, 0x11, 0x0A, - 0x8B, 0x09, 0x29, 0x00, 0x11, 0x0A, 0x09, 0x02, 0xE2, 0x01, 0x00, 0x08, 0x19, 0x08, 0x33, 0x08, - 0x4C, 0x08, 0x66, 0x08, 0x80, 0x08, 0x99, 0x08, 0xB3, 0x08, 0xCC, 0x08, 0xE6, 0x08, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, - 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x0F, 0x00, 0x0A -}; - -#endif /* _MAPPER_355_H */ \ No newline at end of file diff --git a/src/mappers/mapper356.c b/src/mappers/mapper356.c deleted file mode 100644 index ab6c9f497..000000000 --- a/src/mappers/mapper356.c +++ /dev/null @@ -1,107 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 356 - J.Y. Company's 7-in-1 Rockman (JY-208) - * All registers work as INES Mapper 045, except $6000 sequential register 2 (third write): - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; -static uint8 cmd; -static uint8 ntaramExtra[2048]; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &cmd, 1, "CMD0" }, - { 0 } -}; - -static void M356CW(uint16 A, uint16 V) { - if (reg[2] & 0x20) { - uint16 mask = 0xFF >> (~reg[2] & 0xF); - uint16 base = ((reg[2] << 4) & 0xF00) | reg[0]; - - setchr1(A, (base & ~mask) | (V & mask)); - } else { - setchr8r(0x10, 0); - } -} - -static void M356PW(uint16 A, uint16 V) { - uint16 mask = ~reg[3] & 0x3F; - uint16 base = ((reg[2] << 2) & 0x300) | reg[1]; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M356MIR(void) { - if (reg[2] & 0x40) { - /* setmirror(MI_4); */ - SetupCartMirroring(4, 0, ntaramExtra); - } else { - setmirror((mmc3.mirr & 0x01) ^ 0x01); - } -} - -static DECLFW(M356Write) { - if (!(reg[3] & 0x40)) { - reg[cmd] = V; - cmd = (cmd + 1) & 3; - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } -} - -static void M356Close(void) { - MMC3_Close(); -} - -static void M356Reset(void) { - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - MMC3_Reset(); -} - -static void M356Power(void) { - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M356Write); -} - -void Mapper356_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M356CW; - MMC3_pwrap = M356PW; - MMC3_FixMIR = M356MIR; - info->Reset = M356Reset; - info->Power = M356Power; - info->Close = M356Close; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); - AddExState(ntaramExtra, 2048, 0, "ExRM"); -} diff --git a/src/mappers/mapper357.c b/src/mappers/mapper357.c deleted file mode 100644 index fe1948ed7..000000000 --- a/src/mappers/mapper357.c +++ /dev/null @@ -1,125 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 357 is used for a 4-in-1 multicart (cartridge ID 4602) from Bit Corp. - * The first game is Bit Corp's hack of the YUNG-08 conversion of Super Mario Brothers 2 (J) named Mr. Mary 2, - * the other three games are UNROM games. - * - * Implementation is modified so reset actually sets the correct dipswitch (or outer banks) for each of the 4 games - */ - -#include "mapinc.h" - -static uint8 reg[4]; -static uint8 dipsw; -static uint8 IRQa; -static uint16 IRQCount; - -static SFORMAT StateRegs[] = { - { reg, 4, "REG" }, - { &dipsw, 1, "DPSW" }, - { &IRQCount, 2, "IRQC" }, - { &IRQa, 1, "IRQA" }, - { 0 } -}; - -static void Sync(void) { - if (dipsw == 0) { - static const uint8 banks[2][8] = { - { 4, 3, 5, 3, 6, 3, 7, 3 }, - { 1, 1, 5, 1, 4, 1, 5, 1 } - }; - /* SMB2J Mode */ - setprg8(0x6000, reg[1] ? 0 : 2); - setprg8(0x8000, reg[1] ? 0 : 1); - setprg8(0xA000, 0); - setprg8(0xC000, banks[reg[1]][reg[0]]); - setprg8(0xE000, reg[1] ? 8 : 10); - } else { - /* UNROM Mode */ - setprg16(0x8000, (dipsw << 3) | reg[2]); - setprg16(0xc000, (dipsw << 3) | 0x07); - } -} - -static DECLFW(M357Write) { - if (A & 0x8000) { - reg[2] = V & 0x07; - Sync(); - } - if ((A & 0x71FF) == 0x4022) { - reg[0] = V & 0x07; - Sync(); - } - if ((A & 0x71FF) == 0x4120) { - reg[1] = V & 0x01; - Sync(); - } - if ((A & 0xF1FF) == 0x4122) { - IRQa = V & 0x01; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - } -} - -static void M357Power(void) { - reg[0] = 0; - reg[1] = 0; - reg[2] = 0; - IRQa = IRQCount = 0; - setchr8(0); - setmirror(MI_V); - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x4020, 0xFFFF, M357Write); -} - -static void M357Reset(void) { - reg[0] = 0; - reg[1] = 0; - reg[2] = 0; - IRQa = IRQCount = 0; - dipsw++; - dipsw &= 3; - setmirror((dipsw == 3) ? MI_H : MI_V); - Sync(); -} - -static void M357IRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount & 0x1000) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper357_Init(CartInfo *info) { - info->Reset = M357Reset; - info->Power = M357Power; - MapIRQHook = M357IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper358.c b/src/mappers/mapper358.c deleted file mode 100644 index 4249ebbbe..000000000 --- a/src/mappers/mapper358.c +++ /dev/null @@ -1,41 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -static uint32 GetPRGBank(uint32 V) { - return (((jyasic.mode[3] << 4) & ~0x1F) | (V & 0x1F)); -} - -static uint32 GetCHRBank(uint32 V) { - if (jyasic.mode[3] & 0x20) { - return (((jyasic.mode[3] << 7) & 0x600) | (V & 0x1FF)); - } else { - return (((jyasic.mode[3] << 7) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); - } -} - -void Mapper358_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} diff --git a/src/mappers/mapper359.c b/src/mappers/mapper359.c deleted file mode 100644 index a582fc7f9..000000000 --- a/src/mappers/mapper359.c +++ /dev/null @@ -1,226 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 359 - BMC-SB-5013 - * NES 2.0 Mapper 540 - UNL-82112C - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 prg[4]; -static uint8 chr[8]; -static uint8 reg[4]; - -static uint8 IRQReload; -static uint8 IRQa; -static uint8 irqPA12; -static uint8 IRQAutoEnable; -static uint8 IRQLatch; -static uint8 IRQCount; -static int16 IRQCount16; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { reg, 4, "EXPR" }, - { &IRQReload, 1, "IRQL" }, - { &IRQa, 1, "IRQa" }, - { &irqPA12, 1, "IRQp" }, - { &IRQAutoEnable, 1, "IRQe" }, - { &IRQLatch, 1, "IRQl" }, - { &IRQCount, 1, "IRQ8" }, - { &IRQCount16, 2, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - uint16 prgMask = 0x3F; - uint16 prgBase = (reg[0] & 0x38) << 1; - - switch (reg[1] & 0x03) { - case 0: prgMask = 0x3F; break; - case 1: prgMask = 0x1F; break; - case 2: prgMask = 0x2F; break; - case 3: prgMask = 0x0F; break; - } - - setprg8(0x6000, prgBase | (prg[3] & prgMask)); - setprg8(0x8000, prgBase | (prg[0] & prgMask)); - setprg8(0xA000, prgBase | (prg[1] & prgMask)); - setprg8(0xC000, prgBase | (prg[2] & prgMask)); - setprg8(0xE000, prgBase | ( ~0 & prgMask)); - - if (!CHR_ROM_SIZE) { - setchr8(0); - } else { - if (iNESCart.mapper == 540) { - setchr2(0x0000, chr[0]); - setchr2(0x0800, chr[1]); - setchr2(0x1000, chr[6]); - setchr2(0x1800, chr[7]); - } else { - uint16 chrMask = (reg[1] & 0x40) ? 0xFF : 0x7F; - uint16 chrBase = (reg[3] << 7); - - setchr1(0x0000, chrBase | (chr[0] & chrMask)); - setchr1(0x0400, chrBase | (chr[1] & chrMask)); - setchr1(0x0800, chrBase | (chr[2] & chrMask)); - setchr1(0x0C00, chrBase | (chr[3] & chrMask)); - setchr1(0x1000, chrBase | (chr[4] & chrMask)); - setchr1(0x1400, chrBase | (chr[5] & chrMask)); - setchr1(0x1800, chrBase | (chr[6] & chrMask)); - setchr1(0x1C00, chrBase | (chr[7] & chrMask)); - } - } - - switch (reg[2] & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } -} - -static DECLFW(M359Write) { - switch (A & 0xF000) { - case 0x8000: - prg[A & 0x03] = V; - Sync(); - break; - case 0x9000: - reg[A & 0x03] = V; - Sync(); - break; - case 0xA000: - case 0xB000: - chr[((A >> 10) & 0x04) | (A & 0x03)] = V; - Sync(); - break; - case 0xC000: - switch (A & 0x03) { - case 0: - if (IRQAutoEnable) { - IRQa = FALSE; - } - IRQCount16 &= 0xFF00; - IRQCount16 |= V; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 1: - if (IRQAutoEnable) { - IRQa = TRUE; - } - IRQCount16 &= 0x00FF; - IRQCount16 |= (V << 8); - IRQReload = TRUE; - IRQLatch = V; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 2: - IRQa = (V & 0x01); - irqPA12 = (V & 0x02) >> 1; - IRQAutoEnable = (V & 0x04) >> 2; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 3: - IRQa = (V & 0x01); - X6502_IRQEnd(FCEU_IQEXT); - break; - } - } -} - -static void M359Power(void) { - prg[0] = ~3; - prg[1] = ~2; - prg[2] = ~1; - prg[3] = ~0; - chr[0] = 0; - chr[1] = 1; - chr[2] = 2; - chr[3] = 3; - chr[4] = 4; - chr[5] = 5; - chr[6] = 6; - chr[7] = 7; - reg[0] = 0; - reg[1] = 0x40; - reg[2] = 0; - reg[3] = 0; - IRQReload = IRQa = irqPA12 = IRQAutoEnable = 0; - IRQLatch = IRQCount = IRQCount16 = 0; - Sync(); - FDSSound_Power(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xCFFF, M359Write); -} - -static void M359Reset(void) { - Sync(); - FDSSoundRegReset(); - FDSSound_SC(); -} - -static void M359CPUHook(int a) { - if (!irqPA12) { - if (IRQa && IRQCount16) { - IRQCount16 -= a; - if (IRQCount16 <= 0) - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void M359IRQHook(void) { - if (irqPA12) { - if (!IRQCount || IRQReload) { - IRQCount = IRQLatch; - } else { - IRQCount--; - } - if (!IRQCount && IRQa) { - X6502_IRQBegin(FCEU_IQEXT); - } - IRQReload = FALSE; - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper359_Init(CartInfo *info) { - info->Power = M359Power; - info->Reset = M359Reset; - MapIRQHook = M359CPUHook; - GameHBIRQHook = M359IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} - -void Mapper540_Init(CartInfo *info) { - info->Power = M359Power; - MapIRQHook = M359CPUHook; - GameHBIRQHook = M359IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper360.c b/src/mappers/mapper360.c deleted file mode 100644 index 59b9453e2..000000000 --- a/src/mappers/mapper360.c +++ /dev/null @@ -1,67 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 360 - Bit Corp's 31-in-1 multicart (3150) */ - -#include "mapinc.h" - -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - /* dip 0 and 1 is the same game SMB) */ - if (dipsw < 2) { - setprg32(0x8000, dipsw >> 1); - } else { - setprg16(0x8000, dipsw); - setprg16(0xC000, dipsw); - } - setchr8(dipsw); - setmirror(((dipsw & 0x10) >> 4) ^ 1); -} - -static void M360Power(void) { - dipsw = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0XFFFF, CartBW); -} - -static void M360Reset(void) { - dipsw = (dipsw + 1) & 31; - Sync(); - FCEU_printf("dipsw = %d\n", dipsw); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper360_Init(CartInfo *info) { - info->Reset = M360Reset; - info->Power = M360Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper361.c b/src/mappers/mapper361.c deleted file mode 100644 index bde1dc07e..000000000 --- a/src/mappers/mapper361.c +++ /dev/null @@ -1,70 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 361 (YY841101C): - * JY-009 - * JY-018 - * JY-019 - * OK-411 -*/ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M361PW(uint16 A, uint16 V) { - setprg8(A, (reg & 0xF0) | (V & 0x0F)); -} - -static void M361CW(uint16 A, uint16 V) { - setchr1(A, ((reg & 0xF0) << 3) | (V & 0x7F)); -} - -static void M361Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static DECLFW(M361Write) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M361Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M361Write); -} - -void Mapper361_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M361PW; - MMC3_cwrap = M361CW; - info->Power = M361Power; - info->Reset = M361Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper362.c b/src/mappers/mapper362.c deleted file mode 100644 index f141b51ee..000000000 --- a/src/mappers/mapper362.c +++ /dev/null @@ -1,92 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 362 - PCB 830506C - * 1995 Super HiK 4-in-1 (JY-005) - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 game; -static uint8 PPUCHRBus; - -static SFORMAT StateRegs[] = { - { &game, 1, "GAME" }, - { &PPUCHRBus, 1, "PPUC" }, - { 0 }, -}; - -static void M362PW(uint16 A, uint16 V) { - uint16 prgBase = (game == 0) ? ((vrc24.chr[PPUCHRBus] & 0x180) >> 3) : 0x40; - - setprg8(A, prgBase | (V & 0x0F)); -} - -static void M362CW(uint16 A, uint16 V) { - uint16 chrBase = (game == 0) ? (vrc24.chr[PPUCHRBus] & 0x180) : 0x200; - uint16 chrMask = (game == 0) ? 0x7F : 0x1FF; - - setchr1(A, chrBase | (V & chrMask)); -} - -static DECLFW(M362CHRWrite) { - VRC24_Write(A, V); - if (A & 0x01) { - /* NOTE: Because the lst higher 2 CHR-ROM bits are repurposed as PRG/CHR outer bank, - an extra PRG sync after a CHR write. */ - VRC24_FixPRG(); - } -} - -static void M362PPUHook(uint32 A) { - uint8 bank = (A & 0x1FFF) >> 10; - if ((game == 0) && (PPUCHRBus != bank) && ((A & 0x3000) != 0x2000)) { - PPUCHRBus = bank; - VRC24_FixCHR(); - VRC24_FixPRG(); - } -} - -static void M362Reset(void) { - if (PRGsize[0] <= (512 * 1024)) { - game = 0; - } else { - game = (game + 1) & 0x01; - } - VRC24_FixCHR(); - VRC24_FixPRG(); -} - -static void M362Power(void) { - PPUCHRBus = game = 0; - VRC24_Power(); - SetWriteHandler(0xB000, 0xEFFF, M362CHRWrite); -} - -void Mapper362_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x01, 0x02, 0, 0); - info->Reset = M362Reset; - info->Power = M362Power; - PPU_hook = M362PPUHook; - VRC24_pwrap = M362PW; - VRC24_cwrap = M362CW; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper364.c b/src/mappers/mapper364.c deleted file mode 100644 index dca449c0c..000000000 --- a/src/mappers/mapper364.c +++ /dev/null @@ -1,62 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M364CW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x20) ? 0x7F : 0xFF; - - setchr1(A, ((reg << 4) & 0x100) | (V & mask)); -} - -static void M364PW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x20) ? 0x0F : 0x1F; - - setprg8(A, ((reg >> 1) & 0x20) | (V & mask)); -} - -static DECLFW(M364Write) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M364Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M364Write); -} - -void Mapper364_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = M364PW; - MMC3_cwrap = M364CW; - info->Power = M364Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper366.c b/src/mappers/mapper366.c deleted file mode 100644 index 991f64cd4..000000000 --- a/src/mappers/mapper366.c +++ /dev/null @@ -1,67 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* - * Mapper 366 (GN-45): - * K-3131GS - * K-3131SS -*/ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M366PW(uint16 A, uint16 V) { - setprg8(A, reg | (V & 0x0F)); -} - -static void M366CW(uint16 A, uint16 V) { - setchr1(A, (reg << 3) | (V & 0x7F)); -} - -static void M366Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static DECLFW(M366Write) { - CartBW(A, V); - if (!(reg & 0x80)) { - reg = A & 0xF0; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M366Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M366Write); -} - -void Mapper366_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = M366PW; - MMC3_cwrap = M366CW; - info->Power = M366Power; - info->Reset = M366Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper368.c b/src/mappers/mapper368.c deleted file mode 100644 index 9c7177e9d..000000000 --- a/src/mappers/mapper368.c +++ /dev/null @@ -1,123 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 357 is used for a 4-in-1 multicart (cartridge ID 4602) from Bit Corp. - * The first game is Bit Corp's hack of the YUNG-08 conversion of Super Mario Brothers 2 (J) named Mr. Mary 2, - * the other three games are UNROM games. - */ - - -#include "mapinc.h" - -static uint8 reg[2]; -static uint8 IRQa; -static uint16 IRQCount; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &IRQCount, 2, "IRQC" }, - { &IRQa, 1, "IRQA" }, - { 0 } -}; - -static void Sync(void) { - /* - The actual bank number is: - Value Bank# - ------------ - 0 4 - 1 3 - 2 5 - 3 3 - 4 6 - 5 3 - 6 7 - 7 3 */ - uint8 prg = (reg[0] & 0x01) ? 0x03 : (0x04 | ((reg[0] >> 1) & 0x03)); - - setprg8(0x6000, 0x02); - setprg8(0x8000, 0x01); - setprg8(0xA000, 0x00); - setprg8(0xC000, prg); - setprg8(0xE000, 0x08); - setchr8(0); -} - -static DECLFR(M368Read) { - if ((A & 0xF1FF) == 0x4122) { - return (0x8A | (reg[1] & 0x35)); - } - return CartBR(A); -} - -static DECLFW(M368Write) { - switch (A & 0xF1FF) { - case 0x4022: - reg[0] = V; - Sync(); - break; - case 0x4122: - reg[1] = V; - IRQa = V & 0x01; - if (!IRQa) { - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - } - break; - } -} - -static void M368Power(void) { - reg[0] = reg[1] = 0; - IRQa = IRQCount = 0; - Sync(); - SetReadHandler(0x4020, 0x4FFF, M368Read); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x4020, 0x4FFF, M368Write); -} - -static void M368Reset(void) { - reg[0] = reg[1] = 0; - IRQa = IRQCount = 0; - Sync(); -} - -static void M368IRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount >= 4096) { - IRQCount -= 4096; - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper368_Init(CartInfo *info) { - info->Reset = M368Reset; - info->Power = M368Power; - MapIRQHook = M368IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper369.c b/src/mappers/mapper369.c deleted file mode 100644 index ff72ff4c6..000000000 --- a/src/mappers/mapper369.c +++ /dev/null @@ -1,165 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 369 (BMC-N49C-300) - Super Mario Bros. Party multicart */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 smb2j; -static uint8 IRQa; -static uint16 IRQCount; - -static SFORMAT StateRegs[] = { - { ®, 1, "MODE" }, - { &smb2j, 1, "SMB2" }, - { &IRQa, 1, "MIQA" }, - { &IRQCount, 2, "MIQC" }, - { 0 } -}; - -static void M369PW(uint16 A, uint16 V) { - uint8 mask = (reg == 0xFF) ? 0x1F : 0x0F; - uint8 base = (reg == 0xFF) ? 0x20 : 0x10; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M369CW(uint16 A, uint16 V) { - uint16 mask = (reg == 0xFF) ? 0xFF : 0x7F; - uint16 base = (reg == 0xFF) ? 0x100 : 0x80; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M369Sync(void) { - switch (reg) { - case 0x00: - case 0x01: /* NROM */ - setprg32(0x8000, reg); - setchr8(reg & 0x03); - break; - case 0x13: /* SMB2J */ - setprg8r(0, 0x6000, 0x0E); - setprg8(0x8000, 0x0C); - setprg8(0xA000, 0x0D); - setprg8(0xC000, 0x08 | (smb2j & 0x03)); - setprg8(0xE000, 0x0F); - setchr8(reg & 0x03); - break; - case 0x37: /* MMC3: 128 KiB CHR */ - case 0xFF: /* MMC3: 256 KiB CHR */ - setprg8r(0x10, 0x6000, 0); - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static DECLFW(M369WriteLo) { - if (A & 0x100) { - reg = V; - M369Sync(); - } -} - -static DECLFW(M369Write) { - switch (A & 0xE000) { - case 0x8000: - if (reg == 0x13) { - IRQa = 0; - X6502_IRQEnd(FCEU_IQEXT); - } - if (A & 0x01) { - mmc3.reg[mmc3.cmd & 0x07] = V; - M369Sync(); - } else { - mmc3.cmd = V; - M369Sync(); - } - break; - case 0xA000: - if (reg == 0x13) { - IRQa = (V & 0x02) != 0; - } - MMC3_CMDWrite(A, V); - break; - case 0xC000: - MMC3_IRQWrite(A, V); - break; - case 0xE000: - if (reg == 0x13) { - smb2j = V; - M369Sync(); - } - MMC3_IRQWrite(A, V); - break; - } -} - -static void SMB2JIRQHook(int a) { - if (reg == 0x13) { - if (IRQa) { - IRQCount += a; - if (IRQCount >= 4096) { - IRQCount -= 4096; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void MMC3IRQHook(void) { - if (reg != 0x13) { - MMC3_IRQHBHook(); - } -} - -static void M369Reset(void) { - reg = smb2j = 0; - IRQa = IRQCount = 0; - MMC3_Reset(); - M369Sync(); -} - -static void StateRestore(int version) { - M369Sync(); -} - -static void M369Power(void) { - reg = smb2j = 0; - IRQa = IRQCount = 0; - MMC3_Power(); - SetWriteHandler(0x4100, 0x4FFF, M369WriteLo); - SetWriteHandler(0x8000, 0xFFFF, M369Write); - M369Sync(); -} - -void Mapper369_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = M369PW; - MMC3_cwrap = M369CW; - info->Power = M369Power; - info->Reset = M369Reset; - MapIRQHook = SMB2JIRQHook; - GameHBIRQHook = MMC3IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper370.c b/src/mappers/mapper370.c deleted file mode 100644 index 4dec16211..000000000 --- a/src/mappers/mapper370.c +++ /dev/null @@ -1,136 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 370 - F600 - * Golden Mario Party II - Around the World (6-in-1 multicart) - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static void M370CW(uint16 A, uint16 V) { - uint16 mask = (reg & 0x04) ? 0xFF : 0x7F; - uint16 base = reg << 7; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M370PW(uint16 A, uint16 V) { - uint16 mask = reg & 0x20 ? 0x0F : 0x1F; - uint16 base = reg << 1; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M370MIR(void) { - if ((reg & 0x07) == 1) { - if (mmc3.cmd & 0x80) { - setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); - } else { - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); - } - } else { - setmirror((mmc3.mirr & 0x01) ^ 0x01); - } -} - -static DECLFR(M370Read) { - return (((dipsw << 7) & 0x80) | (CPU_OPENBUS & 0x7F)); -} - -static DECLFW(M370Write) { - reg = (A & 0xFF); - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); -} - -static DECLFW(M370WriteCMD) { - uint8 oldcmd = mmc3.cmd; - - switch (A & 0xE001) { - case 0x8000: - mmc3.cmd = V; - if ((oldcmd & 0x40) != (mmc3.cmd & 0x40)) { - MMC3_FixPRG(); - } - if ((oldcmd & 0x80) != (mmc3.cmd & 0x80)) { - MMC3_FixCHR(); - MMC3_FixMIR(); - } - break; - case 0x8001: - switch (mmc3.cmd & 0x07) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - mmc3.reg[mmc3.cmd & 0x07] = V; - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - default: - MMC3_CMDWrite(A, V); - break; - } - break; - default: - MMC3_CMDWrite(A, V); - break; - } -} - -static void M370Reset(void) { - reg = 0; - dipsw ^= 1; - FCEU_printf("solderpad=%02x\n", dipsw); - MMC3_Reset(); -} - -static void M370Power(void) { - reg = 0; - dipsw = 1; /* start off with the 6-in-1 menu */ - MMC3_Power(); - SetReadHandler(0x5000, 0x5FFF, M370Read); - SetWriteHandler(0x5000, 0x5FFF, M370Write); - SetWriteHandler(0x8000, 0x9FFF, M370WriteCMD); -} - -void Mapper370_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_FixMIR = M370MIR; - MMC3_cwrap = M370CW; - MMC3_pwrap = M370PW; - info->Power = M370Power; - info->Reset = M370Reset; - AddExState(®, 1, 0, "EXPR"); - AddExState(&dipsw, 1, 0, "DPSW"); -} diff --git a/src/mappers/mapper372.c b/src/mappers/mapper372.c deleted file mode 100644 index 8b912e270..000000000 --- a/src/mappers/mapper372.c +++ /dev/null @@ -1,95 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* added 2020-1-28 - */ -/* NES 2.0 Mapper 372 is used for a revision of the Rockman I-VI multicart (PCB ID SFC-12). - * It is INES Mapper 045 but with one bit of outer bank register #2 working as a CHR-ROM/RAM switch. - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; -static uint8 cmd; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &cmd, 1, "CMD0" }, - { 0 } -}; - -static void M372CW(uint16 A, uint16 V) { - if (reg[2] & 0x20) { - setchr8r(0x10, 0); - } else { - uint32 mask = 0xFF >> (~reg[2] & 0x0F); - uint32 base = ((reg[2] << 4) & 0xF00) | reg[0]; - - setchr1(A, (base & ~mask) | (V & mask)); - } -} - -static void M372PW(uint16 A, uint16 V) { - uint32 mask = ~reg[3] & 0x3F; - uint32 base = ((reg[2] << 2) & 0x300) | reg[1]; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M372Write) { - if (!(reg[3] & 0x40)) { - reg[cmd] = V; - cmd = (cmd + 1) & 0x03; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M372Reset(void) { - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - MMC3_Reset(); -} - -static void M372Power(void) { - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M372Write); -} - -static void M372Close(void) { - MMC3_Close(); -} - -void Mapper372_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M372CW; - MMC3_pwrap = M372PW; - info->Reset = M372Reset; - info->Power = M372Power; - info->Close = M372Close; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper374.c b/src/mappers/mapper374.c deleted file mode 100644 index c994570a4..000000000 --- a/src/mappers/mapper374.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 374 - * 1995 Super HiK 4-in-1 - 新系列機器戰警组合卡 (JY-022) - * 1996 Super HiK 4-in-1 - 新系列超級飛狼組合卡 (JY-051) - */ - -#include "mapinc.h" -#include "mmc1.h" - -static uint8 game = 0; - -static SFORMAT StateRegs[] = { - { &game, 1, "GAME" }, - { 0 } -}; - -static void M374PRG(uint16 A, uint16 V) { - setprg16(A, (game << 3) | (V & 0x07)); -} - -static void M374CHR(uint16 A, uint16 V) { - setchr4(A, (game << 5) | (V & 0x1F)); -} - -static void M374Reset(void) { - game = (game + 1) & 0x03; - MMC1_Reset(); -} - -void Mapper374_Init(CartInfo *info) { - MMC1_Init(info, 0, 0); - MMC1_cwrap = M374CHR; - MMC1_pwrap = M374PRG; - info->Reset = M374Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper375.c b/src/mappers/mapper375.c deleted file mode 100644 index 727b6e0b5..000000000 --- a/src/mappers/mapper375.c +++ /dev/null @@ -1,65 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint32 prg = ((latch.addr >> 4) & 0x40) | ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); - uint32 cpuA14 = latch.addr & 0x01; - uint32 nrom = (latch.addr >> 7) & 0x01; - uint32 unrom = (latch.addr >> 9) & 0x01; - uint32 unrom_like = (latch.addr >> 11) & 0x01; - - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, ((prg & ~cpuA14) & ~(0x07 * unrom_like)) | (unrom_like * latch.data)); - setprg16(0xC000, ((prg | cpuA14) & ~(0x07 * !nrom * !unrom)) | (0x07 * !nrom * unrom)); - - setchr8(0); - setmirror(((latch.addr >> 1) & 1) ^ 1); - if ((latch.addr & 0x80) == 0x80) { - /* CHR-RAM write protect hack, needed for some multicarts */ - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); - } else { - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); - } -} - -static DECLFW(M375Write) { - if (latch.addr & 0x800) { - latch.data = V; - } else { - latch.addr = A; - latch.data = V; - } - Sync(); -} - -static void M375Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M375Write); -} - -void Mapper375_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, FALSE); - info->Power = M375Power; - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper376.c b/src/mappers/mapper376.c deleted file mode 100644 index d123c46a8..000000000 --- a/src/mappers/mapper376.c +++ /dev/null @@ -1,71 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void M376CW(uint16 A, uint16 V) { - uint16 base = ((reg[1] << 8) & 0x100) | ((reg[0] << 1) & 0x80); - - setchr1(A, base | (V & 0x7F)); -} - -static void M376PW(uint16 A, uint16 V) { - uint16 base = ((reg[1] << 4) & 0x10) | ((reg[0] >> 3) & 0x08) | (reg[0] & 0x07); - - if (reg[0] & 0x80) { - if (reg[0] & 0x20) { - setprg32(0x8000, base >> 1); - } else { - setprg16(0x8000, base); - setprg16(0xC000, base); - } - } else { - setprg8(A, ((base << 1) & ~0x0F) | (V & 0x0F)); - } -} - -static DECLFW(M376Write) { - reg[A & 0x01] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M376Power(void) { - reg[0] = 0; - reg[1] = 0; - MMC3_Power(); - SetWriteHandler(0x7000, 0x7FFF, M376Write); -} - -void Mapper376_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M376PW; - MMC3_cwrap = M376CW; - info->Power = M376Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper377.c b/src/mappers/mapper377.c deleted file mode 100644 index f0bcd06a8..000000000 --- a/src/mappers/mapper377.c +++ /dev/null @@ -1,74 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 377 - NES 2.0 Mapper 377 is used for the - * 1998 Super Game 8-in-1 (JY-111) pirate multicart. It works similarly to Mapper 267 except it has an outer 256KiB - * PRG-ROM bank. - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M377CW(uint16 A, uint16 V) { - uint16 base = ((reg & 0x20) >> 2) | (reg & 0x06); - - setchr1(A, (base << 6) | (V & 0x7F)); -} - -static void M377PW(uint16 A, uint16 V) { - uint16 base = ((reg & 0x20) >> 2) | (reg & 0x06); - - setprg8(A, (base << 3) | (V & 0x0F)); -} - -static DECLFW(M377Write) { - if (!(reg & 0x80)) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M377Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M377Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M377Write); -} - -void Mapper377_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M377CW; - MMC3_pwrap = M377PW; - info->Reset = M377Reset; - info->Power = M377Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper380.c b/src/mappers/mapper380.c deleted file mode 100644 index 9b663b38e..000000000 --- a/src/mappers/mapper380.c +++ /dev/null @@ -1,64 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 380 denotes the 970630C circuit board, - * used on a 512 KiB multicart having 42 to 80,000 listed NROM and UNROM games. */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - uint32 prg = (latch.addr >> 2) & 0x1F; - uint32 cpuA14 = (latch.addr & 0x01) != 0x01; - uint32 ourom = (latch.addr >> 8) & 0x01; - uint32 nrom = (latch.addr >> 9) & 0x01; - - setprg16(0x8000, prg & ~(cpuA14 * nrom)); - setprg16(0xC000, (prg | (cpuA14 * nrom)) | (0x07 * !nrom) | (0x08 * (iNESCart.submapper == 1) * !nrom * ourom)); - - setchr8(0); - setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); - SetupCartCHRMapping(0, CHRptr[0], 0x2000, !(latch.addr & 0x80)); -} - -static DECLFR(M380Read) { - if ((iNESCart.submapper == 0) && (latch.addr & 0x100)) { - A |= dipsw; - } - return CartBR(A); -} - -static void M380Reset(void) { - dipsw = (dipsw + 1) & 0xF; - Latch_RegReset(); -} - -void Mapper380_Init(CartInfo *info) { - Latch_Init(info, Sync, M380Read, FALSE, FALSE); - info->Reset = M380Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper381.c b/src/mappers/mapper381.c deleted file mode 100644 index 00bbf6b9a..000000000 --- a/src/mappers/mapper381.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Map 381 - 2-in-1 High Standard Game (BC-019), reset-based */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reset = 0; - -static void Sync(void) { - setprg16(0x8000, (reset << 4) | ((latch.data & 0x07) << 1) | ((latch.data >> 4) & 0x0F)); - setprg16(0xC000, (reset << 4) | 0x0F); - setchr8(0); -} - -static void M381Reset(void) { - reset++; - Sync(); -} - -void Mapper381_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = M381Reset; - AddExState(&reset, 1, 0, "RST0"); -} diff --git a/src/mappers/mapper382.c b/src/mappers/mapper382.c deleted file mode 100644 index cdabe4688..000000000 --- a/src/mappers/mapper382.c +++ /dev/null @@ -1,65 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 382 - denotes the 830928C circuit board, - * used on a 512 KiB 5-in-1 and a 1 MiB 9-in-1 multicart containing - * the BNROM game Journey to the West and Capcom/Konami UNROM games. - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 base; - -static SFORMAT StateRegs[] = { - { &base, 1, "BASE"}, - { 0 } -}; - -static void Sync(void) { - if (!(base & 0x20)) { - base = latch.addr & 0x3F; - } - switch (base & 0x08) { - case 8: - /* bnrom */ - setprg32(0x8000, (base << 2) | (latch.data & 0x03)); - break; - default: - /* unrom */ - setprg16(0x8000, (base << 3) | (latch.data & 0x07)); - setprg16(0xC000, (base << 3) | 0x07); - break; - } - setchr8(0); - setmirror(((base >> 4) & 0x01) ^ 0x01); - /* FCEU_printf("inB[0]:%02x outB[1]:%02x mode:%02x mirr:%02x lock:%02x\n", latch.data, latch.addr, mode, mirr, lock); */ -} - -static void M382Reset(void) { - base = 0; - Latch_RegReset(); -} - -void Mapper382_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Reset = M382Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper383.c b/src/mappers/mapper383.c deleted file mode 100644 index b1ca33193..000000000 --- a/src/mappers/mapper383.c +++ /dev/null @@ -1,121 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* 晶太 YY840708C PCB - Solely used for the "1995 Soccer 6-in-1 足球小将專輯 (JY-014)" multicart. - MMC3+PAL16L8 combination, resulting in a bizarre mapper that switches banks in part upon *reads*. -*/ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 pal_A15, pal_A16, pal_A1718; - -static SFORMAT StateRegs[] = { - { &pal_A15, 1, "A15_"}, - { &pal_A16, 1, "A16_"}, - { &pal_A1718, 1, "A178"}, - { 0 } -}; - -static void M383PW(uint16 A, uint16 V) { - uint16 base; - uint16 mask; - - switch (pal_A1718) { - case 0x00: - /* "Setting 0 provides a round-about means of dividing the first 128 KiB bank into two 32 KiB and one 64 KiB bank." */ - base = pal_A1718 | pal_A16 | (pal_A16 ? 0x00 : pal_A15); - mask = pal_A16 ? 0x07 : 0x03; - break; - case 0x30: - /* "Setting 3 provides 128 KiB MMC3 banking with the CPU A14 line fed to the MMC3 clone reversed. - This is used for the game Tecmo Cup: Soccer Game (renamed "Tecmo Cup Soccer"), - originally an MMC1 game with the fixed bank at $8000-$BFFF and the switchable bank at $C000-$FFFF, - a configuration that could not be reproduced with an MMC3 alone." */ - base = pal_A1718; - mask = 0x0F; - A ^= 0x4000; - - /* "It is also used for the menu, - which in part executes from PRG-ROM mapped to the CPU $6000-$7FFF address range on the MMC3 clone's fixed - banks alone, as no MMC3 PRG bank register is written to before JMPing to this address range." */ - if (A == 0xA000) { - setprg8(0x6000, base | (V & 0x0B)); - } - break; - default: - /* "Settings 1 and 2 provide normal 128 KiB MMC3 banking." */ - base = pal_A1718; - mask = 0x0F; - break; - } - - setprg8(A, base | (V & mask)); -} - -static void M383CW(uint16 A, uint16 V) { - setchr1(A, (pal_A1718 << 3) | (V & 0x7F)); -} - -static DECLFR(M383Read) { - if (pal_A1718 == 0x00) { /* "PAL PRG pal_A16 is updated with the content of the corresponding MMC3 PRG bank bit by reading from the - respective address range, which in turn will then be applied across the entire ROM address range." */ - pal_A16 = mmc3.reg[0x06 | ((A >> 13) & 0x01)] & 0x08; - MMC3_FixPRG(); - } - return CartBR(A); -} - -static DECLFW(M383Write) { - if (A & 0x0100) { - pal_A15 = (A >> 11) & 0x04; - pal_A1718 = A & 0x30; - MMC3_FixPRG(); - MMC3_FixCHR(); - } - MMC3_Write(A, V); -} - -static void M383Reset(void) { - pal_A15 = 0; - pal_A16 = 0; - pal_A1718 = 0; - MMC3_Reset(); -} - -static void M383Power(void) { - pal_A15 = 0; - pal_A16 = 0; - pal_A1718 = 0; - MMC3_Power(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetReadHandler(0x8000, 0xBFFF, M383Read); - SetWriteHandler(0x8000, 0xFFFF, M383Write); -} - -void Mapper383_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M383PW; - MMC3_cwrap = M383CW; - info->Power = M383Power; - info->Reset = M383Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper385.c b/src/mappers/mapper385.c deleted file mode 100644 index 75265b8e9..000000000 --- a/src/mappers/mapper385.c +++ /dev/null @@ -1,34 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.addr >> 1); - setprg16(0xc000, latch.addr >> 1); - setmirror((latch.addr & 0x01) ^ 0x01); - setchr8(0); -} - -void Mapper385_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); -} diff --git a/src/mappers/mapper386.c b/src/mappers/mapper386.c deleted file mode 100644 index ab79ee997..000000000 --- a/src/mappers/mapper386.c +++ /dev/null @@ -1,41 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -static uint32 GetPRGBank(uint32 V) { - return (((jyasic.mode[3] << 3) & 0x40) | ((jyasic.mode[3] << 4) & 0x20) | (V & 0x1F)); -} - -static uint32 GetCHRBank(uint32 V) { - if (jyasic.mode[3] & 0x20) { - return (((jyasic.mode[3] << 7) & 0x600) | (V & 0x1FF)); - } else { - return (((jyasic.mode[3] << 7) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); - } -} - -void Mapper386_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} diff --git a/src/mappers/mapper387.c b/src/mappers/mapper387.c deleted file mode 100644 index c90dede4d..000000000 --- a/src/mappers/mapper387.c +++ /dev/null @@ -1,41 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -static uint32 GetPRGBank(uint32 V) { - return (((jyasic.mode[3] << 2) & 0x20) | ((jyasic.mode[3] << 3) & 0x10) | (V & 0x0F)); -} - -static uint32 GetCHRBank(uint32 V) { - if (jyasic.mode[3] & 0x20) { - return (((jyasic.mode[3] << 7) & 0x600) | (V & 0x1FF)); - } else { - return (((jyasic.mode[3] << 7) & 0x600) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); - } -} - -void Mapper387_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} diff --git a/src/mappers/mapper388.c b/src/mappers/mapper388.c deleted file mode 100644 index 62c83e0c0..000000000 --- a/src/mappers/mapper388.c +++ /dev/null @@ -1,41 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -static uint32 GetPRGBank(uint32 V) { - return (((jyasic.mode[3] << 3) & 0x60) | (V & 0x1F)); -} - -static uint32 GetCHRBank(uint32 V) { - if (jyasic.mode[3] & 0x20) { - return (((jyasic.mode[3] << 8) & 0x200) | (V & 0x1FF)); - } else { - return (((jyasic.mode[3] << 8) & 0x200) | ((jyasic.mode[3] << 8) & 0x100) | (V & 0x0FF)); - } -} - -void Mapper388_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, FALSE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} diff --git a/src/mappers/mapper389.c b/src/mappers/mapper389.c deleted file mode 100644 index 4ef1ae603..000000000 --- a/src/mappers/mapper389.c +++ /dev/null @@ -1,84 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* Mapper 389 - Caltron 9-in-1 multicart */ - -#include "mapinc.h" - -static uint8 regs[3]; - -static SFORMAT StateRegs[] = { - { ®s, 3, "REGS" }, - { 0 } -}; - -static void Sync(void) { - if (regs[1] & 0x02) { - /* UNROM-064 */ - setprg16(0x8000, (regs[0] >> 2) | ((regs[2] >> 2) & 0x03)); - setprg16(0xC000, (regs[0] >> 2) | 0x03); - } else { - /* NROM-256 */ - setprg32(0x8000, regs[0] >> 3); - } - setchr8(((regs[1] >> 1) & 0x1C) | (regs[2] & 0x03)); - setmirror((regs[0] & 0x01) ^ 1); -} - -static DECLFW(M389Write) { - switch (A & 0xF000) { - case 0x8000: - regs[0] = (A & 0xFF); - Sync(); - break; - case 0x9000: - regs[1] = (A & 0xFF); - Sync(); - break; - default: - regs[2] = (A & 0x0F); - Sync(); - break; - } -} - -static void M389Reset(void) { - regs[0] = regs[1] = regs[2] = 0; - Sync(); -} - -static void M389Power(void) { - regs[0] = regs[1] = regs[2] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M389Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper389_Init(CartInfo *info) { - info->Power = M389Power; - info->Reset = M389Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper390.c b/src/mappers/mapper390.c deleted file mode 100644 index 2d146bbe1..000000000 --- a/src/mappers/mapper390.c +++ /dev/null @@ -1,90 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 390 - Realtec 8031 */ -/* NOTE: Duplicate of Mapper 236 (CHR-ROM variant */ - -#include "mapinc.h" - -static uint8 reg[2]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - switch (reg[1] & 0x30) { - case 0x00: - case 0x10: /* UNROM */ - setprg16(0x8000, reg[1]); - setprg16(0xC000, reg[1] | 0x07); - break; - case 0x20: /* Maybe unused, NROM-256? */ - setprg32(0x8000, reg[1] >> 1); - break; - case 0x30: /* NROM-128 */ - setprg16(0x8000, reg[1]); - setprg16(0xC000, reg[1]); - break; - } - setchr8(reg[0]); - setmirror(((reg[0] & 0x20) >> 5) ^ 1); -} - -static DECLFR(M390Read) { - uint8 ret = CartBR(A); - if ((reg[1] & 0x30) == 0x10) - ret |= dipsw; - return ret; -} - -static DECLFW(M390Write) { - reg[(A >> 14) & 0x01] = A & 0x3F; - Sync(); -} - -static void M390Power(void) { - reg[0] = 0; - reg[1] = 0; - dipsw = 11; /* hard-coded 150-in-1 menu */ - Sync(); - SetReadHandler(0x8000, 0xFFFF, M390Read); - SetWriteHandler(0x8000, 0xFFFF, M390Write); -} - -static void M390Reset(void) { - dipsw = 11; /* hard-coded 150-in-1 menu */ - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper390_Init(CartInfo *info) { - info->Reset = M390Reset; - info->Power = M390Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper391.c b/src/mappers/mapper391.c deleted file mode 100644 index 85daa4d1d..000000000 --- a/src/mappers/mapper391.c +++ /dev/null @@ -1,90 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* BS-110 PCB, previously called NC7000M due to a mix-up. */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void M391PW(uint16 A, uint16 V) { - uint8 mask = (reg[0] & 0x08) ? 0x0F : 0x1F; - uint8 base = (reg[0] << 4) & 0x30; - - if (reg[0] & 0x20) { - if (reg[0] & 0x04) { /* NROM-256 */ - setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~0x03) | 0); - setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & mask) & ~0x03) | 1); - setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~0x03) | 2); - setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] & mask) & ~0x03) | 3); - } else { /* NROM-128 */ - setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~0x01) | 0); - setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & mask) & ~0x01) | 1); - setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] & mask) & ~0x01) | 0); - setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] & mask) & ~0x01) | 1); - } - } else { - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static void M391CW(uint16 A, uint16 V) { - uint16 mask = (reg[0] & 0x40) ? 0x7F : 0xFF; - uint16 base = ((reg[0] << 3) & 0x80) | ((reg[1] << 8) & 0x100); - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M391Write) { - if (MMC3_WramIsWritable()) { - if (!(reg[0] & 0x80)) { - reg[0] = V; - reg[1] = ((A >> 8) & 0xFF); - MMC3_FixPRG(); - MMC3_FixCHR(); - } - } -} - -static void M391Reset(void) { - reg[0] = reg[1] = 0; - MMC3_Reset(); -} - -static void M391Power(void) { - reg[0] = reg[1] = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M391Write); -} - -void Mapper391_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M391CW; - MMC3_pwrap = M391PW; - info->Power = M391Power; - info->Reset = M391Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper393.c b/src/mappers/mapper393.c deleted file mode 100644 index 305f14200..000000000 --- a/src/mappers/mapper393.c +++ /dev/null @@ -1,106 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void M393CW(uint16 A, uint16 V) { - if (reg[0] & 0x08) { - setchr8r(0x10, 0); - } else { - setchr1(A, (reg[0] << 8) | (V & 0xFF)); - } -} - -static void M393PW(uint16 A, uint16 V) { - if (reg[0] & 0x20) { - if (reg[0] & 0x10) { - setprg16(0x8000, (reg[0] << 3) | (reg[1] & 0x07)); - setprg16(0xC000, (reg[0] << 3) | 0x07); - } else { - setprg32(0x8000, (reg[0] << 2) | ((mmc3.reg[6] >> 2) & 0x03)); - } - } else { - setprg8(A, (reg[0] << 4) | (V & 0x0F)); - } -} - -static DECLFW(M393Write) { - reg[1] = V; - switch (A & 0xE001) { - case 0x8001: - mmc3.reg[mmc3.cmd & 0x07] = V; - if ((mmc3.cmd & 0x07) < 6) { - MMC3_FixCHR(); - } - MMC3_FixPRG(); - break; - default: - MMC3_Write(A, V); - MMC3_FixPRG(); - break; - } -} - -static DECLFW(M393WriteReg) { - if (MMC3_WramIsWritable()) { - reg[0] = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M393Power(void) { - reg[0] = reg[1] = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M393WriteReg); - SetWriteHandler(0x8000, 0xFFFF, M393Write); -} - -static void M393Reset(void) { - reg[0] = reg[1] = 0; - MMC3_Reset(); -} - -static void M393lose(void) { - MMC3_Close(); -} - -void Mapper393_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = M393PW; - MMC3_cwrap = M393CW; - info->Power = M393Power; - info->Reset = M393Reset; - info->Close = M393lose; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper394.c b/src/mappers/mapper394.c deleted file mode 100644 index 7abf9ae40..000000000 --- a/src/mappers/mapper394.c +++ /dev/null @@ -1,140 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 394: HSK007 circuit board that can simulate J.Y. ASIC, MMC3, and NROM. */ - -#include "mapinc.h" -#include "jyasic.h" -#include "mmc3.h" - -static uint8 reg[4]; - -static uint32 M394_PRGBank_JY(uint32 V) { - uint8 base = ((reg[1] << 5) & 0x020) | ((reg[3] << 1) & 0x010); - - return (base | (V & 0x1F)); -} - -static uint32 M394_CHRBank_JY(uint32 V) { - uint32 base = ((reg[1] << 8) & 0x100) | ((reg[3] << 1) & 0x080); - - return (base | (V & 0x0FF)); -} - -static void M394MMC3PW(uint16 A, uint16 V) { - uint8 mask = (reg[3] & 0x10) ? 0x1F : 0x0F; - uint8 base = ((reg[1] << 5) & 0x020) | ((reg[3] << 1) & 0x010); - - if (reg[1] & 0x08) { - setprg8(A, base | (V & mask)); - } else { - setprg32(0x8000, (base | ((reg[3] << 1) & 0x0F)) >> 2); - } -} - -static void M394MMC3CW(uint16 A, uint16 V) { - uint16 mask = (reg[3] & 0x80) ? 0xFF : 0x7F; - uint16 base = ((reg[3] << 1) & 0x080) | ((reg[1] << 8) & 0x100); - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M394WriteReg) { - uint8 oldMode = reg[1]; - - A &= 3; - reg[A] = V; - if (A == 1) { - if (!(oldMode & 0x10) && (V & 0x10)) { - JYASIC_Power(); - } else if ((oldMode & 0x10) && !(V & 0x10)) { - JYASIC_restoreWriteHandlers(); - MMC3_Power(); - } - } else { - if (reg[1] & 0x10) { - JYASIC_FixPRG(); - JYASIC_FixCHR(); - JYASIC_FixMIR(); - } else { - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } - } -} - -static void M394StateRestore(int version) { - int i; - - JYASIC_restoreWriteHandlers(); - if (reg[1] & 0x10) { - SetWriteHandler(0x5000, 0x5FFF, JYASIC_WriteALU); - SetWriteHandler(0x6000, 0x7fff, CartBW); - SetWriteHandler(0x8000, 0x87FF, JYASIC_WritePRG); /* 8800-8FFF ignored */ - SetWriteHandler(0x9000, 0x97FF, JYASIC_WriteCHRLow); /* 9800-9FFF ignored */ - SetWriteHandler(0xA000, 0xA7FF, JYASIC_WriteCHRHigh); /* A800-AFFF ignored */ - SetWriteHandler(0xB000, 0xB7FF, JYASIC_WriteNT); /* B800-BFFF ignored */ - SetWriteHandler(0xC000, 0xCFFF, JYASIC_WriteIRQ); - SetWriteHandler(0xD000, 0xD7FF, JYASIC_WriteMode); /* D800-DFFF ignored */ - for (i = 0; i < 0x10000; i++) { - JYASIC_cpuWrite[i] = GetWriteHandler(i); - } - SetWriteHandler(0x0000, 0xFFFF, JYASIC_trapCPUWrite); /* Trap all CPU writes for IRQ clocking purposes */ - JYASIC_CPUWriteHandlersSet = 1; - SetReadHandler(0x5000, 0x5FFF, JYASIC_ReadALU_DIP); - SetReadHandler(0x6000, 0xFFFF, CartBR); - JYASIC_FixPRG(); - JYASIC_FixCHR(); - JYASIC_FixMIR(); - } else { - SetWriteHandler(0x8000, 0xBFFF, MMC3_CMDWrite); - SetWriteHandler(0xC000, 0xFFFF, MMC3_IRQWrite); - SetReadHandler(0x8000, 0xFFFF, CartBR); - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M394Power(void) { - reg[0] = 0x00; - reg[1] = 0x0F; /* start in MMC3 mode */ - reg[2] = 0x00; - reg[3] = 0x10; - MMC3_Power(); - SetWriteHandler(0x5000, 0x5FFF, M394WriteReg); -} - -void Mapper394_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = M394_PRGBank_JY; - JYASIC_GetCHRBank = M394_CHRBank_JY; - - MMC3_Init(info, 0, 0); - MMC3_pwrap = M394MMC3PW; - MMC3_cwrap = M394MMC3CW; - - info->Reset = M394Power; - info->Power = M394Power; - - AddExState(reg, 4, 0, "HSK"); - GameStateRestore = M394StateRestore; -} diff --git a/src/mappers/mapper395.c b/src/mappers/mapper395.c deleted file mode 100644 index dadc03204..000000000 --- a/src/mappers/mapper395.c +++ /dev/null @@ -1,78 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 395 - Realtec 8210 - * Super Card 12-in-1 (SPC002) - * Super Card 13-in-1 (SPC003) - * Super Card 14-in-1 (King006) - * Super Card 14-in-1 (King007) - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void M395CW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x40) ? 0x7F : 0xFF; - uint16 base = ((reg[0] << 4) & 0x300) | ((reg[1] << 5) & 0x400) | ((reg[1] << 3) & 0x80); - - setchr1(A, base | (V & mask)); -} - -static void M395PW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x08) ? 0x0F : 0x1F; - uint16 base = ((reg[0] << 4) & 0x80) | ((reg[0] << 1) & 0x60) | ((reg[1] << 4) & 0x10); - - setprg8(A, base | (V & mask)); -} - -static DECLFW(M395Write) { - if (!(reg[1] & 0x80)) { - reg[(A >> 4) & 0x01] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M395Reset(void) { - reg[0] = reg[1] = 0; - MMC3_Reset(); -} - -static void M395Power(void) { - reg[0] = reg[1] = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M395Write); -} - -void Mapper395_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M395CW; - MMC3_pwrap = M395PW; - info->Power = M395Power; - info->Reset = M395Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper396.c b/src/mappers/mapper396.c deleted file mode 100644 index 0d6e063a6..000000000 --- a/src/mappers/mapper396.c +++ /dev/null @@ -1,56 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 396 - BMC-830752C - * 1995 Super 8-in-1 (JY-050 rev0) - * Super 8-in-1 Gold Card Series (JY-085) - * Super 8-in-1 Gold Card Series (JY-086) - * 2-in-1 (GN-51) - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - if ((latch.addr & 0x6000) == 0x2000) { - reg = latch.data; - } - setprg16(0x8000, (reg << 3) | (latch.data & 0x07)); - setprg16(0xC000, (reg << 3) | 0x07); - setchr8(0); - setmirror((reg & 0x60) ? MI_H : MI_V); -} - -static void M396Reset(void) { - reg = 0; - Latch_RegReset(); -} - -void Mapper396_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = M396Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper397.c b/src/mappers/mapper397.c deleted file mode 100644 index 60dd580a9..000000000 --- a/src/mappers/mapper397.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" -#include "fdssound.h" - -static uint32 GetPRGBank(uint32 V) { - return (((jyasic.mode[3] << 4) & ~0x1F) | (V & 0x1F)); -} - -static uint32 GetCHRBank(uint32 V) { - return ((jyasic.mode[3] << 7) | (V & 0x07F)); -} - -static void M397Power(void) { - JYASIC_Power(); - FDSSound_Power(); -} - -void Mapper397_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; - info->Power = M397Power; -} diff --git a/src/mappers/mapper398.c b/src/mappers/mapper398.c deleted file mode 100644 index 808325954..000000000 --- a/src/mappers/mapper398.c +++ /dev/null @@ -1,92 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 398 - PCB YY840820C - * 1995 Super HiK 5-in-1 - 新系列米奇老鼠組合卡 (JY-048) - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 reg; -static uint8 PPUCHRBus; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { &PPUCHRBus, 1, "PPUC" }, - { 0 }, -}; - -static void M398PW(uint16 A, uint16 V) { - if (reg & 0x80) { - /* GNROM-like */ - setprg32(0x8000, ((reg >> 5) & 0x06) | ((vrc24.chr[PPUCHRBus] >> 2) & 0x01)); - } else { - setprg8(A, V & 0x0F); - } -} - -static void M398CW(uint16 A, uint16 V) { - if (reg & 0x80) { - /* GNROM-like */ - setchr8(0x40 | ((reg >> 3) & 0x08) | (vrc24.chr[PPUCHRBus] & 0x07)); - } else { - setchr1(A, V & 0x1FF); - } -} - -static DECLFW(M398WriteLatch) { - reg = A & 0xFF; - VRC24_FixPRG(); - VRC24_FixCHR(); - VRC24_Write(A, V); -} - -static void M398PPUHook(uint32 A) { - uint8 bank = (A & 0x1FFF) >> 10; - if ((PPUCHRBus != bank) && ((A & 0x3000) != 0x2000)) { - PPUCHRBus = bank; - VRC24_FixPRG(); - VRC24_FixCHR(); - } -} - -static void M398Reset(void) { - reg = 0xC0; - VRC24_FixPRG(); - VRC24_FixCHR(); -} - -static void M398Power(void) { - PPUCHRBus = 0; - reg = 0xC0; - VRC24_Power(); - SetWriteHandler(0x8000, 0xFFFF, M398WriteLatch); -} - -void Mapper398_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x01, 0x02, 0, 1); - info->Reset = M398Reset; - info->Power = M398Power; - PPU_hook = M398PPUHook; - VRC24_pwrap = M398PW; - VRC24_cwrap = M398CW; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper399.c b/src/mappers/mapper399.c deleted file mode 100644 index 84ad92a23..000000000 --- a/src/mappers/mapper399.c +++ /dev/null @@ -1,86 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 prg[2]; -static uint8 chr[2]; - -static SFORMAT StateRegs[] = { - { prg, 2, "PREG" }, - { chr, 2, "CREG" }, - { 0 } -}; - -static void M399PRG(void) { - if (iNESCart.submapper == 1) { - setprg8(0x6000, 0xFE); - setprg8(0x8000, prg[0] << 1 | 0); - setprg8(0xA000, prg[0] << 1 | 1); - setprg8(0xC000, prg[1]); - setprg8(0xE000, 0xFF); - } else { - setprg8(0x8000, 0x00); - setprg8(0xA000, prg[0]); - setprg8(0xC000, prg[1]); - setprg8(0xE000, 0xFF); - } -} - -static void M399CHR(void) { - setchr4(0x0000, chr[0]); - setchr4(0x1000, chr[1]); -} - -static DECLFW(M399WriteReg) { - if (A & 0x01) { - prg[V >> 7] = V; - MMC3_FixPRG(); - } else { - chr[V >> 7] = V; - MMC3_FixCHR(); - } -} - -static DECLFW(M399Write1) { - MMC3_Write(0x2000 + A, V); -} - -static void M399Power(void) { - prg[0] = chr[0] = 0; - prg[1] = chr[1] = 1; - MMC3_Power(); - if (iNESCart.submapper == 1) { - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x8000, 0xDFFF, M399Write1); - SetWriteHandler(0xE000, 0xFFFF, M399WriteReg); - } else { - SetWriteHandler(0x8000, 0x9FFF, M399WriteReg); - } -} - -void Mapper399_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_FixPRG = M399PRG; - MMC3_FixCHR = M399CHR; - info->Power = M399Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper400.c b/src/mappers/mapper400.c deleted file mode 100644 index 5d091aa4b..000000000 --- a/src/mappers/mapper400.c +++ /dev/null @@ -1,70 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 400 is used for retroUSB's 8-BIT XMAS 2017 homebrew cartridge. - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg; -static uint8 led; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, (reg & ~0x07) | (latch.data & 0x07)); - setprg16(0xC000, (reg & ~0x07) | 0x07); - setchr8(0); - if (reg != 0x80) { - setmirror(((reg >> 5) & 0x01) ^ 0x01); - } -} - -static DECLFW(M400WriteReg) { - reg = V; - Sync(); -} - -static DECLFW(M400WriteLED) { - led = V; -} - -static void M400Reset(void) { - reg = 0x80; - Latch_RegReset(); -} - -static void M400Power(void) { - reg = 0x80; - Latch_Power(); - SetWriteHandler(0x7800, 0x7FFF, M400WriteReg); - SetWriteHandler(0x8000, 0xBFFF, M400WriteLED); -} - -void Mapper400_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Power = M400Power; - info->Reset = M400Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper401.c b/src/mappers/mapper401.c deleted file mode 100644 index ef9898ba2..000000000 --- a/src/mappers/mapper401.c +++ /dev/null @@ -1,97 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 - Mapper 401 (reference from NewRisingSun) - * Super 19-in-1 (VIP19) (crc 0x2F497313) - * - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; -static uint8 cmd; -static uint8 dipsw = 0; - -static void M401CW(uint16 A, uint16 V) { - uint32 mask = (0xFF >> (~reg[2] & 0xF)); - uint32 bank = (reg[0] | ((reg[2] << 4) & 0xF00)); - - setchr1(A, bank | (V & mask)); -} - -static void M401PW(uint16 A, uint16 V) { - uint32 mask = (~reg[3] & 0x1F); - uint32 bank = (reg[1] & 0x1F) | (reg[2] & 0x80) | - ((dipsw & 2) ? (reg[2] & 0x20) : ((reg[1] >> 1) & 0x20)) | - ((dipsw & 4) ? (reg[2] & 0x40) : ((reg[1] << 1) & 0x40)); - setprg8(A, bank | (V & mask)); -} - -static DECLFR(M401Read) { - if ((dipsw & 0x01) && (reg[1] & 0x80)) { - return CPU_OPENBUS; - } - return CartBR(A); -} - -static DECLFW(M401Write) { - /* FCEU_printf("Wr A:%04x V:%02x index:%d\n", A, V, cmd); */ - if (!(reg[3] & 0x40)) { - reg[cmd] = V; - cmd = (cmd + 1) & 0x03; - MMC3_FixPRG(); - MMC3_FixCHR(); - } - CartBW(A, V); -} - -static void M401Reset(void) { - dipsw = (dipsw + 1) & 7; - FCEU_printf("dipsw = %d\n", dipsw); - reg[0] = 0x00; - reg[1] = 0x00; - reg[2] = 0x0F; - reg[3] = 0x00; - cmd = 0x00; - MMC3_Reset(); -} - -static void M401Power(void) { - dipsw = 7; - reg[0] = 0x00; - reg[1] = 0x00; - reg[2] = 0x0F; - reg[3] = 0x00; - cmd = 0x00; - MMC3_Power(); - SetReadHandler(0x8000, 0xFFFF, M401Read); - SetWriteHandler(0x6000, 0x7FFF, M401Write); -} - -void Mapper401_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_cwrap = M401CW; - MMC3_pwrap = M401PW; - info->Power = M401Power; - info->Reset = M401Reset; - AddExState(reg, 4, 0, "EXPR"); - AddExState(&cmd, 1, 0, "CMD0"); - AddExState(&dipsw, 1, 0, "DPSW"); -} diff --git a/src/mappers/mapper402.c b/src/mappers/mapper402.c deleted file mode 100644 index d645670ac..000000000 --- a/src/mappers/mapper402.c +++ /dev/null @@ -1,47 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 0x800) { - setprg8(0x6000, ((latch.addr & 0x1F) << 1) | 3); - } - if ((latch.addr & 0x40)) { - setprg16(0x8000, latch.addr & 0x1F); - setprg16(0xC000, latch.addr & 0x1F); - } else { - setprg32(0x8000, (latch.addr & 0x1F) >> 1); - } - if ((latch.addr & 0x400) == 0) { - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); - } else { - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); - } - setchr8(0); - setmirror(((latch.addr >> 7) & 0x01) ^ 0x01); -} - -void Mapper402_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper403.c b/src/mappers/mapper403.c deleted file mode 100644 index 5afff3ba7..000000000 --- a/src/mappers/mapper403.c +++ /dev/null @@ -1,86 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 403 denotes the 89433 circuit board with up to 1 MiB PRG-ROM and 32 KiB of CHR-RAM, bankable with 8 - * KiB granularity. - * - * Tetris Family - 玩家 19-in-1 智瑟實典 (NO-1683) - * Sachen Superpack (versions A-C) - */ - -#include "mapinc.h" - -static uint8 reg[3]; - -static SFORMAT StateRegs[] = { - { reg, 3, "REGS" }, - { 0 } -}; - -static void Sync(void) { - if (reg[2] & 0x01) { /* NROM-128 */ - setprg16(0x8000, reg[0] >> 1); - setprg16(0xC000, reg[0] >> 1); - } else { /* NROM-256 */ - setprg32(0x8000, reg[0] >> 2); - } - setchr8(reg[1]); - setmirror(((reg[2] >> 4) & 0x01) ^ 0x01); -} - -static DECLFW(M403Write4) { - if (A & 0x100) { - reg[A & 0x03] = V; - Sync(); - } -} - -static DECLFW(M403Write8) { - if (reg[2] & 0x04) { - reg[1] = V; - Sync(); - } -} - -static void M403Reset(void) { - reg[0] = reg[1] = reg[2] = 0; - Sync(); -} - -static void M403Power(void) { - reg[0] = reg[1] = reg[2] = 0; - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); /* For TetrisA (Tetris Family 19-in-1 NO 1683) */ - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4100, 0x5FFF, M403Write4); - SetWriteHandler(0x8000, 0xFFFF, M403Write8); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper403_Init(CartInfo *info) { - info->Reset = M403Reset; - info->Power = M403Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper404.c b/src/mappers/mapper404.c deleted file mode 100644 index 1695cb3d7..000000000 --- a/src/mappers/mapper404.c +++ /dev/null @@ -1,65 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 404 - JY012005 - * 1998 Super HiK 8-in-1 (JY-021B) - */ - -#include "mapinc.h" -#include "mmc1.h" - -static uint8 reg; - -static void M404PW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x40) ? 0x07 : 0x0F; - setprg16(A, ((reg << 3) & ~mask) | (V & mask)); -} - -static void M404CW(uint16 A, uint16 V) { - setchr4(A, (reg << 5) | (V & 0x1F)); -} - -static DECLFW(M404Write) { - if (!(reg & 0x80)) { - reg = V; - MMC1_FixPRG(); - MMC1_FixCHR(); - } -} - -static void M404Reset(void) { - reg = 0; - MMC1_Reset(); -} - -static void M404Power(void) { - reg = 0; - MMC1_Power(); - SetWriteHandler(0x6000, 0x7FFF, M404Write); -} - -void Mapper404_Init(CartInfo *info) { - MMC1_Init(info, 0, 0); - info->Power = M404Power; - info->Reset = M404Reset; - MMC1_cwrap = M404CW; - MMC1_pwrap = M404PW; - AddExState(®, 1, 0, "BANK"); -} diff --git a/src/mappers/mapper406.c b/src/mappers/mapper406.c deleted file mode 100644 index d1bf6810f..000000000 --- a/src/mappers/mapper406.c +++ /dev/null @@ -1,87 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 406 */ -/* Uses flashrom to save high scores. */ - -#include "mapinc.h" -#include "mmc3.h" -#include "flashrom.h" - -static uint8 *FLASHROM_data = NULL; -static uint32 FLASHROM_size = 0; - -static void M406PW(uint16 A, uint16 V) { - setprg8r(0x10, A, V & 0x3F); -} - -static DECLFR(M406Read) { - return FlashROM_Read(A); -} - -static DECLFW(M406Write) { - FlashROM_Write(A, V); - if (iNESCart.submapper == 0) { - A = (A & 0xFFFC) | ((A << 1) & 2) | ((A >> 1) & 1); - } else if ((A <= 0x9000) || (A >= 0xE000)) { - A = A ^ 0x6000; - } - MMC3_Write(A, V); -} - -static void M406Power(void) { - MMC3_Power(); - SetReadHandler(0x8000, 0xFFFF, M406Read); - SetWriteHandler(0x8000, 0xFFFF, M406Write); -} - -static void M406Close(void) { - MMC3_Close(); - if (FLASHROM_data) { - FCEU_free(FLASHROM_data); - } - FLASHROM_data = NULL; -} - -void Mapper406_Init(CartInfo *info) { - uint32 w, r, id; - - MMC3_Init(info, 0, 0); - info->Power = M406Power; - info->Close = M406Close; - MMC3_pwrap = M406PW; - MapIRQHook = FlashROM_CPUCyle; - - info->battery = 1; - FLASHROM_size = PRGsize[0]; - FLASHROM_data = (uint8 *)FCEU_gmalloc(FLASHROM_size); - info->SaveGame[0] = FLASHROM_data; - info->SaveGameLen[0] = FLASHROM_size; - AddExState(FLASHROM_data, FLASHROM_size, 0, "FROM"); - /* copy PRG ROM into FLASHROM_data, use it instead of PRG ROM */ - for (w = 0, r = 0; w < FLASHROM_size; w++) { - FLASHROM_data[w] = PRGptr[0][r]; - ++r; - } - SetupCartPRGMapping(0x10, FLASHROM_data, FLASHROM_size, 0); - - id = (info->submapper == 0) ? 0xC2 : 0x01; - FlashROM_Init(FLASHROM_data, FLASHROM_size, id, 0xA4, 65536, 0x5555, 0x02AAA); -} diff --git a/src/mappers/mapper409.c b/src/mappers/mapper409.c deleted file mode 100644 index 9729dfa54..000000000 --- a/src/mappers/mapper409.c +++ /dev/null @@ -1,33 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg16(0x8000, latch.addr); - setprg16(0xC000, ~0); - setchr8(0); -} - -void Mapper409_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper410.c b/src/mappers/mapper410.c deleted file mode 100644 index 67094a78b..000000000 --- a/src/mappers/mapper410.c +++ /dev/null @@ -1,96 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 410 is a variant of mapper 45 where the - * ASIC's PRG A21/CHR A20 output (set by bit 6 of the third write to $6000) - * selects between regularly-banked CHR-ROM (=0) and 8 KiB of unbanked CHR-RAM (=1). - * It is used solely for the Super 8-in-1 - 98格鬥天王+熱血 (JY-302) multicart. - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; -static uint8 cmd; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &cmd, 1, "CMD0" }, - { 0 } -}; - -static void M410PW(uint16 A, uint16 V) { - uint32 mask = ~reg[3] & 0x3F; - uint32 base = ((reg[2] << 2) & 0x300) | reg[1]; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M410CW(uint16 A, uint16 V) { - if (!(reg[2] & 0x40)) { - uint32 mask = 0xFF >> (~reg[2] & 0x0F); - uint32 base = ((reg[2] << 4) & 0xF00) | reg[0]; - - setchr1(A, (base & ~mask) | (V & mask)); - } else { - setchr8r(0x10, 0); - } -} - -static DECLFW(M410Write) { - if (!(reg[3] & 0x40)) { - reg[cmd] = V; - cmd = (cmd + 1) & 0x03; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M410Close(void) { - MMC3_Close(); -} - -static void M410Reset(void) { - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - MMC3_Reset(); -} - -static void M410Power(void) { - MMC3_Power(); - reg[0] = reg[1] = reg[3] = cmd = 0; - reg[2] = 0x0F; - SetWriteHandler(0x6000, 0x7FFF, M410Write); -} - -void Mapper410_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M410CW; - MMC3_pwrap = M410PW; - info->Reset = M410Reset; - info->Power = M410Power; - info->Close = M410Close; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAM = (uint8 *)FCEU_gmalloc(8192); - SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); - AddExState(CHRRAM, 8192, 0, "CRAM"); -} \ No newline at end of file diff --git a/src/mappers/mapper411.c b/src/mappers/mapper411.c deleted file mode 100644 index b60ff8ad7..000000000 --- a/src/mappers/mapper411.c +++ /dev/null @@ -1,89 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Mapper 411 - A88S-1 - * 1997 Super 7-in-1 (JY-201) - * 1997 Super 6-in-1 (JY-202) - * 1997 Super 7-in-1 (JY-203) - * 1997 龍珠武鬥會 7-in-1 (JY-204) - * 1997 Super 7-in-1 (JY-205) - * 1997 Super 7-in-1 (JY-206) - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; -static uint8 dipsw; - -static void M411CW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x02) ? 0xFF : 0x7F; - uint16 base = ((reg[0] << 4) & 0x100) | ((reg[1] << 5) & 0x80); - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M411PW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x02) ? 0x1F : 0x0F; - uint16 base = ((reg[1] >> 1) & 0x40) | ((reg[1] << 1) & 0x10); - - /* NROM Mode */ - if ((reg[0] & 0x40) && !(reg[0] & 0x20)) { /* $5xx0 bit 5 check required for JY-212 */ - uint16 bank = (base >> 1) | (reg[0] & 0x05) | ((reg[0] >> 2) & 0x02); - if (reg[0] & 0x02) { /* NROM-256 */ - setprg32(0x8000, bank >> 1); - } else { /* NROM-128 */ - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } else { /* MMC3 */ - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static DECLFW(M411Write) { - reg[A & 0x01] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M411Reset(void) { - reg[0] = 0x80; - reg[1] = 0x82; - MMC3_Reset(); -} - -static void M411Power(void) { - reg[0] = 0x80; - reg[1] = 0x82; - MMC3_Power(); - SetWriteHandler(0x5800, 0x5FFF, M411Write); -} - -void Mapper411_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M411PW; - MMC3_cwrap = M411CW; - info->Power = M411Power; - info->Reset = M411Reset; - AddExState(reg, 2, 0, "EXPR"); -} diff --git a/src/mappers/mapper412.c b/src/mappers/mapper412.c deleted file mode 100644 index 75040dfe9..000000000 --- a/src/mappers/mapper412.c +++ /dev/null @@ -1,93 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 412 is a variant of mapper 45 where the - * ASIC's PRG A21/CHR A20 output (set by bit 6 of the third write to $6000) - * selects between regularly-banked CHR-ROM (=0) and 8 KiB of unbanked CHR-RAM (=1). - * It is used solely for the Super 8-in-1 - 98格鬥天王+熱血 (JY-302) multicart. - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; - -static void M412CW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x20) ? 0x7F : 0xFF; - uint16 base = ((reg[1] << 5) & 0x100) | (reg[1] & 0x80); - uint16 bank = reg[0] >> 2; - - if (reg[2] & 0x02) { - setchr8(bank); - } else { - setchr1(A, (base & ~mask) | (V & mask)); - } -} - -static void M412PW(uint16 A, uint16 V) { - uint16 mask = 0x3F & ~(((reg[1] << 4) & 0x20) | (reg[1] & 0x10)); - uint16 base = ((reg[1] << 3) & 0x20) | ((reg[1] >> 2) & 0x10); - uint16 bank = reg[2] >> 3; - - if (reg[2] & 0x02) { - if (reg[2] & 0x04) { - setprg32(0x8000, bank >> 1); - } else { - setprg16(0x8000, bank); - setprg16(0xC000, bank); - } - } else { - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static DECLFW(M412Write) { - if (MMC3_WramIsWritable()) { - CartBW(A, V); - if (!(reg[1] & 0x01)) { - reg[A & 0x03] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } - } -} - -static void M412Reset(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Reset(); - mmc3.wram = 0x80; -} - -static void M412Power(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Power(); - mmc3.wram = 0x80; - SetWriteHandler(0x6000, 0x7FFF, M412Write); -} - -void Mapper412_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M412CW; - MMC3_pwrap = M412PW; - info->Reset = M412Reset; - info->Power = M412Power; - AddExState(reg, 4, 0, "EXPR"); -} diff --git a/src/mappers/mapper413.c b/src/mappers/mapper413.c deleted file mode 100644 index 0bb80c0dd..000000000 --- a/src/mappers/mapper413.c +++ /dev/null @@ -1,147 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * Copyright (C) 2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[4]; -static uint8 IRQCount; -static uint8 IRQReload; -static uint8 IRQa; -static uint8 serialControl; -static uint32 serialAddress; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &IRQCount, 1, "IRQC" }, - { &IRQReload, 1, "IRQR" }, - { &IRQa, 1, "IRQA" }, - { &serialAddress, 4, "ADDR" }, - { &serialControl, 1, "CTRL" }, - { 0 } -}; - -static void Sync(void) { - setprg4(0x5000, 0x01); - setprg8(0x6000, reg[0]); - - setprg8(0x8000, reg[1]); - setprg8(0xA000, reg[2]); - setprg4(0xD000, 0x07); - setprg8(0xE000, 0x04); - - setchr4(0x0000, reg[3]); - setchr4(0x1000, ~0x02); -} - -static uint64 lreset; -static uint32 laddr; -static DECLFR(M413ReadPCM) { - uint8 ret = CPU_OPENBUS; - if ((A == laddr) && ((timestampbase + timestamp) < (lreset + 4))) { - return ret; - } - if (serialControl & 0x02) { - ret = MISC_ROM_PTR[serialAddress++ & (MISC_ROM_SIZE - 1)]; - } else { - ret = MISC_ROM_PTR[serialAddress & (MISC_ROM_SIZE - 1)]; - } - laddr = A; - lreset = timestampbase + timestamp; - return ret; -} - -static DECLFW(M413Write) { - switch (A & 0xF000) { - case 0x8000: - IRQReload = V; - break; - case 0x9000: - IRQCount = 0; - break; - case 0xA000: - case 0xB000: - IRQa = (A & 0x1000) != 0; - if (!IRQa) { - X6502_IRQEnd(FCEU_IQEXT); - } - break; - case 0xC000: - serialAddress = (serialAddress << 1) | (V >> 7); - break; - case 0xD000: - serialControl = V; - break; - case 0xE000: - case 0xF000: - reg[V >> 6] = V & 0x3F; - Sync(); - break; - } -} - -static void M413Power(void) { - serialAddress = 0; - serialControl = 0; - - IRQCount = 0; - IRQReload = 0; - IRQa = 0; - - reg[0] = 0; - reg[1] = 0; - reg[2] = 0; - reg[3] = 0; - - laddr = 0; - lreset = 0; - - Sync(); - - SetReadHandler(0x4800, 0x4FFF, M413ReadPCM); - SetReadHandler(0xC000, 0xCFFF, M413ReadPCM); - SetReadHandler(0x5000, 0x7FFF, CartBR); - SetReadHandler(0x8000, 0xBFFF, CartBR); - SetReadHandler(0xD000, 0xFFFF, CartBR); - - SetWriteHandler(0x8000, 0xFFFF, M413Write); -} - -static void M413IRQHook(void) { - if (IRQCount == 0) { - IRQCount = IRQReload; - } else { - IRQCount--; - } - if ((IRQCount == 0) && IRQa) { - X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper413_Init(CartInfo *info) { - info->Power = M413Power; - GameHBIRQHook = M413IRQHook; - GameStateRestore = StateRestore; - AddExState(&StateRegs, ~0, 0, 0); -} diff --git a/src/mappers/mapper414.c b/src/mappers/mapper414.c deleted file mode 100644 index 8064142e5..000000000 --- a/src/mappers/mapper414.c +++ /dev/null @@ -1,60 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - if (latch.addr & 0x2000) { /* NROM-256 */ - setprg32(0x8000, latch.addr >> 2); - } else { /* NROM-128 */ - setprg16(0x8000, latch.addr >> 1); - setprg16(0xC000, latch.addr >> 1); - } - setchr8(latch.data); - setmirror((latch.addr & 0x01) ^ 0x01); -} - -static DECLFR(M414Read) { - if ((A >= 0xC000) && !(latch.addr & 0x100) && (latch.addr & (dipsw << 4))) { - return CPU_OPENBUS; - } - return CartBR(A); -} - -static void M414Reset(void) { - dipsw++; - dipsw &= 0x0F; - Sync(); -} - -void Mapper414_Init(CartInfo *info) { - Latch_Init(info, Sync, M414Read, FALSE, TRUE); - info->Reset = M414Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper415.c b/src/mappers/mapper415.c deleted file mode 100644 index c6a4fde57..000000000 --- a/src/mappers/mapper415.c +++ /dev/null @@ -1,40 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg8(0x6000, latch.data); - setprg32(0x8000, ~0); - setchr8(0); - setmirror(((latch.data >> 4) & 0x01) ^ 0x01); -} - -static void M415Power(void) { - Latch_Power(); - SetReadHandler(0x6000, 0x7FFF, CartBR); -} - -void Mapper415_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M415Power; -} diff --git a/src/mappers/mapper416.c b/src/mappers/mapper416.c deleted file mode 100644 index ed9ccde82..000000000 --- a/src/mappers/mapper416.c +++ /dev/null @@ -1,110 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 smb2j_reg; -static uint8 IRQa; -static uint16 IRQCount; - -static SFORMAT StateRegs[] = { - { &smb2j_reg, 1, "SMB2" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 2, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - uint8 prg = ((latch.data >> 1) & 0x04) | ((latch.data >> 6) & 0x02) | ((latch.data >> 5) & 0x01); - - if (latch.addr >= 0xA000) { - /* latch should not respond to $A000-$FFFF */ - return; - } - - setprg8(0x6000, 0x07); - if (latch.data & 0x08) { - switch (latch.data & 0xC0) { - case 0x00: - setprg8(0x8000, prg << 1); - setprg8(0xA000, prg << 1); - setprg8(0xC000, prg << 1); - setprg8(0xE000, prg << 1); - break; - case 0x40: - setprg16(0x8000, prg); - setprg16(0xC000, prg); - break; - case 0x80: - case 0xC0: - setprg32(0x8000, prg >> 1); - break; - } - } else { - setprg8(0x8000, 0x00); - setprg8(0xA000, 0x01); - setprg8(0xC000, smb2j_reg); - setprg8(0xE000, 0x03); - } - setchr8((latch.data >> 1) & 0x03); - setmirror(((latch.data >> 2) & 0x01) ^ 0x01); -} - -static DECLFW(M416WriteReg) { - if ((A & 0x20) && !(A & 0x40)) { - if (A & 0x100) { - IRQa = V & 0x01; - if (!IRQa) { - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - } - } else { - smb2j_reg = (V & ~0x07) | ((V << 2) & 0x04) | ((V >> 1) & 0x03); - Sync(); - } - } -} - -static void M416Power(void) { - smb2j_reg = IRQa = IRQCount = 0; - Latch_Power(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x4020, 0x5FFF, M416WriteReg); -} - -static void M416IRQHook(int a) { - if (IRQa & 0x01) { - IRQCount += a; - if (IRQCount & 0x1000) { - X6502_IRQBegin(FCEU_IQEXT); - } else { - X6502_IRQEnd(FCEU_IQEXT); - } - } -} - -void Mapper416_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M416Power; - MapIRQHook = M416IRQHook; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper417.c b/src/mappers/mapper417.c deleted file mode 100644 index b5667b895..000000000 --- a/src/mappers/mapper417.c +++ /dev/null @@ -1,115 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[4]; -static uint8 chr[8]; -static uint8 nt[4]; -static uint8 IRQa; -static uint16 IRQCount; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { nt, 4, "NREG" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 2, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, ~0); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - setmirrorw(nt[0] & 0x01, nt[1] & 0x01, nt[2] & 0x01, nt[3] & 0x01); -} - -static DECLFW(M417Write) { - switch ((A >> 4) & 0x07) { - case 0: - prg[A & 0x03] = V; - Sync(); - break; - case 1: - chr[0 | (A & 0x03)] = V; - if (iNESCart.submapper == 1) nt[A & 0x03] = V >> 7; - Sync(); - break; - case 2: - chr[4 | (A & 0x03)] = V; - Sync(); - break; - break; - case 3: - IRQCount = 0; - IRQa = TRUE; - break; - case 4: - IRQa = FALSE; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 5: - if (iNESCart.submapper == 0) nt[A & 0x03] = V & 0x01; - Sync(); - break; - } -} - -static void M417Power(void) { - memset(prg, 0, sizeof(prg)); - memset(chr, 0, sizeof(chr)); - memset(nt, 0, sizeof(nt)); - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M417Write); -} - -static void M417IRQHook(int a) { - uint16 mask = (iNESCart.submapper == 1) ? 0x1000 : 0x400; - - IRQCount += a; - if (IRQa && (IRQCount > mask)) { - X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper417_Init(CartInfo *info) { - info->Power = M417Power; - MapIRQHook = M417IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper418.c b/src/mappers/mapper418.c deleted file mode 100644 index cb757380f..000000000 --- a/src/mappers/mapper418.c +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 418 denotes the 820106-C/821007C circuit boards for the LH42 bootleg cartridge versions of Highway Star. */ - -#include "mapinc.h" -#include "n118.h" - -static void M418FixCHR(void) { - setchr2(0x0000, (n118.reg[0] & 0x3F) >> 1); - setchr2(0x0800, (n118.reg[1] & 0x3F) >> 1); - setchr1(0x1000, n118.reg[2] & 0x3F); - setchr1(0x1400, n118.reg[3] & 0x3F); - setchr1(0x1800, n118.reg[4] & 0x3F); - setchr1(0x1C00, n118.reg[5] & 0x3F); - setmirror((n118.reg[5] & 0x01) ^ 0x01); -} - -void Mapper418_Init(CartInfo *info) { - N118_Init(info, 0, 0); - N118_FixCHR = M418FixCHR; -} diff --git a/src/mappers/mapper420.c b/src/mappers/mapper420.c deleted file mode 100644 index ce92ed691..000000000 --- a/src/mappers/mapper420.c +++ /dev/null @@ -1,70 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[4]; - -static void M420CW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x80) ? 0x7F : 0xFF; - uint16 base = ((reg[1] << 1) & 0x100) | ((reg[1] << 5) & 0x80); - - setchr1(A, base | (V & mask)); -} - -static void M420PW(uint16 A, uint16 V) { - if (reg[0] & 0x80) { - setprg32(0x8000, ((reg[2] >> 2) & 0x08) | ((reg[0] >> 1) & 0x07)); - } else { - uint8 mask = (reg[0] & 0x20) ? 0x0F : ((reg[3] & 0x20) ? 0x1F : 0x3F); - uint8 base = (reg[3] << 3) & 0x20; - - setprg8(A, base | (V & mask)); - } -} - -static DECLFW(M420Write) { - /* writes possible regardless of MMC3 wram state */ - CartBW(A, V); - reg[A & 0x03] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M420Reset(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Reset(); -} - -static void M420Power(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M420Write); -} - -void Mapper420_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M420CW; - MMC3_pwrap = M420PW; - info->Reset = M420Reset; - info->Power = M420Power; - AddExState(reg, 4, 0, "EXPR"); -} diff --git a/src/mappers/mapper421.c b/src/mappers/mapper421.c deleted file mode 100644 index 46a6ff3a0..000000000 --- a/src/mappers/mapper421.c +++ /dev/null @@ -1,41 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "jyasic.h" - -static uint32 GetPRGBank(uint32 V) { - if (jyasic.mode[3] & 0x04) { - return (((jyasic.mode[3] << 4) & ~0x3F) | (V & 0x3F)); - } else { - return (((jyasic.mode[3] << 4) & ~0x1F) | (V & 0x1F)); - } -} - -static uint32 GetCHRBank(uint32 V) { - return (((jyasic.mode[3] << 8) & 0x300) | (V & 0x01FF)); -} - -void Mapper421_Init(CartInfo *info) { - /* Multicart */ - JYASIC_Init(info, TRUE); - JYASIC_GetPRGBank = GetPRGBank; - JYASIC_GetCHRBank = GetCHRBank; -} diff --git a/src/mappers/mapper428.c b/src/mappers/mapper428.c deleted file mode 100644 index 445ac1896..000000000 --- a/src/mappers/mapper428.c +++ /dev/null @@ -1,84 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[4]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { reg, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) { - int mask = reg[2] >> 6; /* There is an CNROM mode that takes either two or four inner CHR banks from a CNROM-like - latch register at $8000-$FFFF. */ - - if (reg[1] & 0x10) { - setprg32(0x8000, reg[1] >> 6); - } else { - setprg16(0x8000, reg[1] >> 5); - setprg16(0xC000, reg[1] >> 5); - } - - setchr8(((reg[1] & 0x07) & ~mask) | (latch.data & mask)); - - setmirror(((reg[1] >> 3) & 0x01) ^ 0x01); -} - -static DECLFW(M428Write) { - reg[A & 0x03] = V; - Sync(); -} - -static DECLFR(M428Read) { - return (CPU_OPENBUS & ~0x03) | (dipsw & 0x03); -} - -static void M428Power(void) { - dipsw = 0; - reg[0] = 0; - reg[1] = 0; - reg[2] = 0; - reg[3] = 0; - Latch_Power(); - SetWriteHandler(0x6000, 0x7FFF, M428Write); - SetReadHandler(0x6000, 0x7FFF, M428Read); - SetReadHandler(0x8000, 0xFFFF, CartBR); -} - -static void M428Reset(void) { - dipsw++; - reg[0] = 0; - reg[1] = 0; - reg[2] = 0; - reg[3] = 0; - Sync(); -} - -void Mapper428_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M428Power; - info->Reset = M428Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper429.c b/src/mappers/mapper429.c deleted file mode 100644 index 29b8474d8..000000000 --- a/src/mappers/mapper429.c +++ /dev/null @@ -1,40 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* Mapper 429: LIKO BBG-235-8-1B/Milowork FCFC1 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.data >> 2); - setchr8(latch.data); -} - -static void Mapper429_Reset(void) { - latch.data = 4; /* Initial CHR bank 0, initial PRG bank 1 */ - Sync(); -} - -void Mapper429_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Mapper429_Reset; -} diff --git a/src/mappers/mapper430.c b/src/mappers/mapper430.c deleted file mode 100644 index db9b3decd..000000000 --- a/src/mappers/mapper430.c +++ /dev/null @@ -1,77 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M430PW(uint16 A, uint16 V) { - uint8 mask = 0x0F; - uint8 base = (reg << 4) & 0x30; - - if (reg & 0x08) { - setprg8(0x8000, (base | ((mmc3.reg[6] & ~0x02) & mask))); - setprg8(0xA000, (base | ((mmc3.reg[7] & ~0x02) & mask))); - setprg8(0xC000, (base | ((mmc3.reg[6] | 0x02) & mask))); - setprg8(0xE000, (base | ((mmc3.reg[7] | 0x02) & mask))); - } else { - setprg8(A, (base | (V & mask))); - } -} - -static void M430CW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x04) ? 0x7F : 0xFF; - - setchr1(A, ((reg << 6) & ~mask) | (V & mask)); -} - -static DECLFW(M430Write) { - if (MMC3_WramIsWritable()) { - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M430Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M430Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M430Write); -} - -void Mapper430_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M430CW; - MMC3_pwrap = M430PW; - info->Reset = M430Reset; - info->Power = M430Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper431.c b/src/mappers/mapper431.c deleted file mode 100644 index 85e5f3bdc..000000000 --- a/src/mappers/mapper431.c +++ /dev/null @@ -1,64 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, ((reg[0] >> 2) & ~0x07) | (reg[1] & 0x07)); - setprg16(0xC000, ((reg[0] >> 2) & ~0x07) | 0x07); - setchr8(0); - setmirror((reg[0] & 0x01) ^ 0x01); -} - -static DECLFW(M431Write) { - reg[(A >> 14) & 0x01] = V; - Sync(); -} - -static void M431Reset(void) { - reg[1] = reg[0] = 0; - Sync(); -} - -static void M431Power(void) { - reg[1] = reg[0] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M431Write); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper431_Init(CartInfo *info) { - info->Power = M431Power; - info->Reset = M431Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper432.c b/src/mappers/mapper432.c deleted file mode 100644 index 7295bc89f..000000000 --- a/src/mappers/mapper432.c +++ /dev/null @@ -1,98 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; -static uint8 dipsw; - -static void M432CW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x04) ? 0x7F : 0xFF; - uint16 base = ((reg[1] << 7) & 0x080) | ((reg[1] << 5) & 0x100) | ((reg[1] << 4) & 0x200); - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M432PW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x02) ? 0x0F : 0x1F; - uint16 base = ((reg[1] << 4) & 0x10) | ((reg[1] << 1) & 0x60); - - if (reg[1] & 0x40) { /* NROM */ - if (reg[1] & 0x80) { /* NROM-256 */ - setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & ~0x02) & mask)); - setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & ~0x02) & mask)); - setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] | 0x02) & mask)); - setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] | 0x02) & mask)); - } else { /* NROM-128 */ - setprg8(0x8000, (base & ~mask) | (mmc3.reg[6] & mask)); - setprg8(0xA000, (base & ~mask) | (mmc3.reg[7] & mask)); - setprg8(0xC000, (base & ~mask) | (mmc3.reg[6] & mask)); - setprg8(0xE000, (base & ~mask) | (mmc3.reg[7] & mask)); - } - } else { /* MMC3 */ - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static DECLFR(M432Read) { - if ((reg[0] & 0x01) || ((reg[1] & 0x20) && (PRG_ROM_SIZE < (1024 * 1024)))) { - return dipsw; - } - return CartBR(A); -} - -static DECLFW(M432Write) { - if (MMC3_WramIsWritable()) { - reg[A & 0x01] = V; - if (!(A & 0x01) && !(V & 0x01) && (PRG_ROM_SIZE < (1024 * 1024))) { - reg[1] &= ~0x20; /* Writing 0 to register 0 clears register 1's DIP bit */ - } - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M432Reset(void) { - reg[0] = 0; - reg[1] = 0; - dipsw++; - MMC3_Reset(); -} - -static void M432Power(void) { - reg[0] = 0; - reg[1] = 0; - dipsw = 0; - MMC3_Power(); - SetReadHandler(0x8000, 0xFFFF, M432Read); - SetWriteHandler(0x6000, 0x7FFF, M432Write); -} - -void Mapper432_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M432CW; - MMC3_pwrap = M432PW; - info->Power = M432Power; - info->Reset = M432Reset; - AddExState(reg, 2, 0, "EXPR"); - AddExState(&dipsw, 1, 0, "CMD0"); -} diff --git a/src/mappers/mapper433.c b/src/mappers/mapper433.c deleted file mode 100644 index e7e4ae67a..000000000 --- a/src/mappers/mapper433.c +++ /dev/null @@ -1,44 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 433 denotes the NC-20MB PCB, used for the 20-in-1 (CA-006) multicart. It is almost identical to INES Mapper 433, except that mirroring is selected just by single bit 6 (1=Horizontal). - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = latch.data & 0x1F; - - if (latch.data & 0x20) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { - setprg32(0x8000, prg >> 1); - } - setmirror(((latch.data >> 6) & 0x01) ^ 0x01); - setchr8(0); -} - -void Mapper433_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper434.c b/src/mappers/mapper434.c deleted file mode 100644 index f2e1210ba..000000000 --- a/src/mappers/mapper434.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* S-009. UNROM plus outerbank register at $6000-$7FFF. */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg; - -static void Sync(void) { - setprg16(0x8000, (reg << 3) | (latch.data & 0x07)); - setprg16(0xC000, (reg << 3) | 0x07); - setchr8(0); - setmirror((reg >> 5) & 0x01); -} - -static DECLFW(M434WriteOuterBank) { - reg = V; - Sync(); -} - -static void M434Reset(void) { - reg = 0; - Sync(); -} - -static void M434Power(void) { - reg = 0; - Latch_Power(); - SetWriteHandler(0x6000, 0x7FFF, M434WriteOuterBank); -} - -void Mapper434_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Reset = M434Reset; - info->Power = M434Power; - AddExState(®, 1, 0, "REGS"); -} diff --git a/src/mappers/mapper435.c b/src/mappers/mapper435.c deleted file mode 100644 index 779920a5f..000000000 --- a/src/mappers/mapper435.c +++ /dev/null @@ -1,53 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint16 prg = ((latch.addr >> 4) & 0x40) | ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); - - if (latch.addr & 0x200) { - if (latch.addr & 0x001) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { - setprg32(0x8000, prg >> 1); - } - } else { - setprg16(0x8000, prg); - setprg16(0xC000, prg | 0x07); - } - - if (latch.addr & 0x800) { - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); - } else { - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); - } - - setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); - setchr8(0); -} - -void Mapper435_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper436.c b/src/mappers/mapper436.c deleted file mode 100644 index 6a914ce25..000000000 --- a/src/mappers/mapper436.c +++ /dev/null @@ -1,66 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2008 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 436: 820401/T-217 */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M436PW(uint16 A, uint16 V) { - if (reg & 0x01) { - setprg8(A, ((reg >> 2) & 0x30) | (V & 0x0F)); - } else { - setprg32(0x8000, (reg >> 4)); - } -} - -static void M436CW(uint16 A, uint16 V) { - setchr1(A, ((reg << 1) & ~0x7F) | (V & 0x7F)); -} - -static DECLFW(M436Write) { - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M436Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M436Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M436Write); -} - -void Mapper436_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = M436PW; - MMC3_cwrap = M436CW; - info->Power = M436Power; - info->Reset = M436Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper437.c b/src/mappers/mapper437.c deleted file mode 100644 index 70c2cc1da..000000000 --- a/src/mappers/mapper437.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NTDEC TH2348 circuit board. UNROM plus reg bank register at $5FFx. */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg; - -static void Sync(void) { - setprg16(0x8000, (reg << 3) | (latch.data & 0x07)); - setprg16(0xC000, (reg << 3) | 0x07); - setchr8(0); - setmirror(((reg >> 3) & 0x01) ^ 0x01); -} - -static DECLFW(M437Write) { - reg = A & 0x0F; - Sync(); -} - -static void M437_Reset(void) { - reg = 0; - Sync(); -} - -static void M437_Power(void) { - reg = 0; - Latch_Power(); - SetWriteHandler(0x5000, 0x5FFF, M437Write); -} - -void Mapper437_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Reset = M437_Reset; - info->Power = M437_Power; - AddExState(®, 1, 0, "OUTB"); -} diff --git a/src/mappers/mapper438.c b/src/mappers/mapper438.c deleted file mode 100644 index a8be1301c..000000000 --- a/src/mappers/mapper438.c +++ /dev/null @@ -1,46 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* K-3071 */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint16 prg = latch.addr >> 1; - uint16 chr = latch.data >> 1; - uint16 mirr = (latch.data & 0x01) ^ 0x01; - - if (latch.addr & 1) - setprg32(0x8000, prg >> 1); - else { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } - setchr8(chr); - setmirror(mirr); -} - -void Mapper438_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper439.c b/src/mappers/mapper439.c deleted file mode 100644 index eb3885762..000000000 --- a/src/mappers/mapper439.c +++ /dev/null @@ -1,66 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 439 denotes the YS2309 multicart PCB. - * Its UNIF MAPRs are BMC-DS-07 and BMC-K86B. - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[2]; - -static void Sync(void) { - uint8 mask = ((~reg[1] >> 1) & 0x38) | 0x07; - uint8 base = reg[0] >> 1; - setprg16(0x8000, (base & ~mask) | (latch.data & mask)); - setprg16(0xC000, (base & ~mask) | (0x3F & mask)); - setchr8(0); - setmirror(((latch.data >> 7) & 0x01) ^ 0x01); -} - -static DECLFW(M439WriteReg) { - reg[A & 0x01] = V; - Sync(); -} - -static DECLFW(M439WriteLatch) { - uint8 mask = (reg[1] & 0x80) | ((reg[1] >> 1) & 0x38); - Latch_Write(A, (V & ~mask) | (latch.data & mask)); -} - -static void M439Reset(void) { - reg[0] = reg[1] = 0; - Latch_RegReset(); -} - -static void M439Power(void) { - reg[0] = reg[1] = 0; - Latch_Power(); - SetWriteHandler(0x6000, 0x7FFF, M439WriteReg); - SetWriteHandler(0x8000, 0xFFFF, M439WriteLatch); -} - -void Mapper439_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M439Power; - info->Reset = M439Reset; - AddExState(reg, 2, 0, "REGS"); -} diff --git a/src/mappers/mapper441.c b/src/mappers/mapper441.c deleted file mode 100644 index 902d2f256..000000000 --- a/src/mappers/mapper441.c +++ /dev/null @@ -1,77 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* 841026C and 850335C multicart circuit boards */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M441PW(uint16 A, uint16 V) { - uint8 mask = (reg & 0x08) ? 0x0F : 0x1F; - uint8 base = (reg << 4) & 0x30; - - if (reg & 0x04) { - setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & ~0x02) & mask)); - setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & ~0x02) & mask)); - setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] | 0x02) & mask)); - setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] | 0x02) & mask)); - } else { - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static void M441CW(uint16 A, uint16 V) { - uint16 mask = (reg & 0x40) ? 0x7F : 0xFF; - uint16 base = (reg << 3) & 0x180; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M441Write) { - if (MMC3_WramIsWritable()) { - if (!(reg & 0x80)) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } - } -} - -static void M441Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M441Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M441Write); -} - -void Mapper441_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M441CW; - MMC3_pwrap = M441PW; - info->Power = M441Power; - info->Reset = M441Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper443.c b/src/mappers/mapper443.c deleted file mode 100644 index cc9aabc30..000000000 --- a/src/mappers/mapper443.c +++ /dev/null @@ -1,84 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NC3000M PCB */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static void M443PW(uint16 A, uint16 V) { - uint8 mask = 0x0F; - uint8 base = ((reg << 4) & 0x20) | (reg & 0x10); - - if (reg & 0x04) { /* NROM */ - uint16 bank = (base & ~mask) | (mmc3.reg[6] & mask); - if (reg & 0x08) { /* NROM-128 */ - setprg16(0x8000, bank >> 1); - setprg16(0xC000, bank >> 1); - } else { /* NROM-256 */ - setprg32(0x8000, bank >> 2); - } - } else { /* MMC3 */ - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static void M443CW(uint16 A, uint16 V) { - setchr1(A, ((reg << 8) & ~0xFF) | (V & 0xFF)); -} - -static DECLFR(M443Read) { - return (((reg & 0x0C) == 0x08) ? dipsw : CartBR(A)); -} - -static DECLFW(M443Write) { - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M443Reset(void) { - dipsw++; - dipsw &= 15; - reg = 0; - MMC3_Reset(); -} - -static void M443Power(void) { - dipsw = 0; - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M443Write); - SetReadHandler(0x8000, 0xFFFF, M443Read); -} - -void Mapper443_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M443CW; - MMC3_pwrap = M443PW; - info->Power = M443Power; - info->Reset = M443Reset; - AddExState(®, 1, 0, "EXPR"); - AddExState(&dipsw, 1, 0, "DIPS"); -} diff --git a/src/mappers/mapper444.c b/src/mappers/mapper444.c deleted file mode 100644 index 7896492fe..000000000 --- a/src/mappers/mapper444.c +++ /dev/null @@ -1,92 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NC7000M PCB, with incorrect UNIF MAPR BS-110 due to a mix-up. Submapper bits 0 and 1. denote the setting of two - * solder info->submapper that configure CHR banking. */ -/* NC8000M PCB, indicated by submapper bit 2. */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static void M444PW(uint16 A, uint16 V) { - uint16 mask = ((iNESCart.submapper & 0x04) && (reg & 0x02)) ? 0x1F : 0x0F; - uint16 base = reg << 4; - - if (reg & 0x04) { /* NROM */ - uint16 bank = (base & ~mask) | (mmc3.reg[6] & mask); - if (reg & 0x08) { /* NROM-128 */ - setprg16(0x8000, bank >> 1); - setprg16(0xC000, bank >> 1); - } else { /* NROM-256 */ - setprg32(0x8000, bank >> 2); - } - } else { /* MMC3 */ - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static void M444CW(uint16 A, uint16 V) { - uint16 mask = (iNESCart.submapper & 0x01) ? 0xFF : 0x7F; - uint16 base = ((reg << 7) & ((iNESCart.submapper & 0x01) ? 0x00 : 0x80)) | ((reg << ((iNESCart.submapper & 0x02) ? 4 : 7)) & 0x100); - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static DECLFR(M444Read) { - if ((reg & 0x0C) == 0x08) { - return dipsw; - } - return CartBR(A); -} - -static DECLFW(M444Write) { - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static void M444Reset(void) { - dipsw++; - dipsw &= 3; - reg = 0; - MMC3_Reset(); -} - -static void M444Power(void) { - dipsw = 0; - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M444Write); - SetReadHandler(0x8000, 0xFFFF, M444Read); -} - -void Mapper444_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M444CW; - MMC3_pwrap = M444PW; - info->Power = M444Power; - info->Reset = M444Reset; - AddExState(®, 1, 0, "EXPR"); - AddExState(&dipsw, 1, 0, "DIPS"); -} diff --git a/src/mappers/mapper445.c b/src/mappers/mapper445.c deleted file mode 100644 index 745fdbf7c..000000000 --- a/src/mappers/mapper445.c +++ /dev/null @@ -1,120 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 445 - * DG574B MMC3-compatible multicart circuit board. - */ - -#include "mapinc.h" -#include "mmc3.h" -#include "vrc24.h" - -#define MAPPER_MMC3 0x00 -#define MAPPER_VRC4 0x10 - -static uint8 reg[4]; - -static void M445PW(uint16 A, uint16 V) { - uint8 mask = (reg[2] & 0x01) ? 0x0F : 0x1F; - uint8 base = reg[0]; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M445CW(uint16 A, uint16 V) { - uint16 mask = (reg[2] & 0x08) ? 0x7F : 0xFF; - uint16 base = reg[1] << 3; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M445WriteREG) { - if (!(reg[3] & 0x20)) { - reg[A & 0x03] = V; - vrc24.A0 = reg[3] & 0x01 ? 0x0A : 0x05; - vrc24.A1 = reg[3] & 0x01 ? 0x05 : 0x0A; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static DECLFW(M445WriteASIC) { - switch (reg[3] & 0x10) { - case MAPPER_VRC4: - VRC24_Write(A, V); - break; - case MAPPER_MMC3: - default: - MMC3_Write(A, V); - break; - } -} - -static void M445Reset(void) { - reg[0] = 0x00; - reg[1] = 0x00; - reg[2] = 0x00; - reg[3] = 0x00; - VRC24_Reset(); - MMC3_Reset(); -} - -static void M445Power(void) { - reg[0] = 0x00; - reg[1] = 0x00; - reg[2] = 0x00; - reg[3] = 0x00; - VRC24_Power(); - MMC3_Power(); - SetWriteHandler(0x5000, 0x5FFF, M445WriteREG); - SetWriteHandler(0x8000, 0xFFFF, M445WriteASIC); -} - -static void StateRestore(int version) { - switch (reg[3] & 0x10) { - case MAPPER_VRC4: - VRC24_FixPRG(); - VRC24_FixCHR(); - VRC24_FixMIR(); - break; - case MAPPER_MMC3: - default: - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - } -} - -void Mapper445_Init(CartInfo *info) { - MMC3_Init(info, info->PRGRamSize + info->PRGRamSaveSize, info->battery); - MMC3_pwrap = M445PW; - MMC3_cwrap = M445CW; - - VRC24_Init(info, VRC4, 0x01, 0x02, FALSE, TRUE); - VRC24_pwrap = M445PW; - VRC24_cwrap = M445CW; - - info->Power = M445Power; - info->Reset = M445Reset; - - GameStateRestore = StateRestore; - AddExState(reg, 4, 0, "EXPR"); -} diff --git a/src/mappers/mapper446.c b/src/mappers/mapper446.c deleted file mode 100644 index f8a69b9df..000000000 --- a/src/mappers/mapper446.c +++ /dev/null @@ -1,475 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" -#include "mmc1.h" -#include "mmc3.h" -#include "vrc24.h" -#include "vrc6.h" -#include "flashrom.h" - -#define MAPPER_UNROM 0x00 -#define MAPPER_MMC3 0x01 -#define MAPPER_NROM 0x02 -#define MAPPER_CNROM 0x03 -#define MAPPER_ANROM 0x04 -#define MAPPER_SLROM 0x05 -#define MAPPER_SNROM 0x06 -#define MAPPER_SUROM 0x07 -#define MAPPER_GNROM 0x08 -#define MAPPER_PNROM 0x09 -#define MAPPER_HKROM 0x0A -#define MAPPER_BANDAI152 0x0B -#define MAPPER_TLSROM 0x0E -#define MAPPER_189 0x0F -#define MAPPER_VRC6 0x10 -#define MAPPER_VRC2_22 0x12 -#define MAPPER_VRC4_25 0x15 -#define MAPPER_VRC4_23 0x18 -#define MAPPER_VRC1 0x1A - -#define WRAM_CHIP 0x10 -#define FLASH_CHIP 0x11 - -static uint8 *flash = NULL; -static uint8_t reg[9]; - -static SFORMAT StateRegs[] = { - { reg, 9, "REGS" }, - { 0 } -}; - -static uint32 GetPRGBase(void) { - return ((reg[2] << 8) | reg[1]); -} - -static uint32 GetPRGMask(void) { - return (~reg[3]); -} - -static uint32 GetCHRBase(void) { - return reg[6]; -} - -static void M446MMC1PW(uint16 A, uint16 V) { - setprg16r(FLASH_CHIP, A, (GetPRGBase() >> 1) | (V & (GetPRGMask() >> 1))); -} -static void M446MMC1CW(uint16 A, uint16 V) { - setchr4(A, (GetCHRBase() >> 2) | (V & 0x1F)); -} - -static void M446MMC3PW(uint16 A, uint16 V) { - switch (reg[0] & 0x1F) { - case MAPPER_MMC3: - case MAPPER_TLSROM: - setprg8r(FLASH_CHIP, A, GetPRGBase() | (V & GetPRGMask())); - break; - - case MAPPER_189: - setprg32r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 2) | (reg[8] & 0x03)); - break; - } -} -static void M446MMC3CW(uint16 A, uint16 V) { - switch (reg[0] & 0x1F) { - case MAPPER_TLSROM: - setchr1(A, GetCHRBase() | (V & 0x7F)); - break; - - case MAPPER_MMC3: - case MAPPER_189: - setchr1(A, GetCHRBase() | (V & 0xFF)); - break; - } -} - -static void M446VRC24PW(uint16 A, uint16 V) { - switch (reg[0] & 0x1F) { - case MAPPER_VRC2_22: - case MAPPER_VRC4_23: - case MAPPER_VRC4_25: - setprg8r(FLASH_CHIP, A, GetPRGBase() | (V & GetPRGMask())); - break; - } -} -static void M446VRC24CW(uint16 A, uint16 V) { - switch (reg[0] & 0x1F) { - case MAPPER_VRC2_22: - setchr1(A, V >> 1); - break; - - case MAPPER_VRC4_23: - case MAPPER_VRC4_25: - setchr1(A, V & 0xFF); - break; - } -} - -static void M446VRC6PW(uint16 A, uint16 V) { - setprg8r(FLASH_CHIP, A, GetPRGBase() | (V & GetPRGMask())); -} - -static void M446VRC6CW(uint16 A, uint16 V) { - setchr1(A, V & 0xFF); -} - -static void Sync(void) { - /* CHR-RAM Protect */ - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], (reg[5] & 0x04) ? 0 : 1); - - if (reg[0] & 0x80) { - switch (reg[0] & 0x1F) { - case MAPPER_NROM: - setprg8r(FLASH_CHIP, 0x8000, GetPRGBase() | (0x00 & GetPRGMask())); - setprg8r(FLASH_CHIP, 0xA000, GetPRGBase() | (0x01 & GetPRGMask())); - setprg8r(FLASH_CHIP, 0xC000, GetPRGBase() | (0x02 & GetPRGMask())); - setprg8r(FLASH_CHIP, 0xE000, GetPRGBase() | (0x03 & GetPRGMask())); - setchr8(GetCHRBase()); - setmirror(reg[4] & 0x01); - break; - - case MAPPER_CNROM: - setprg8r(FLASH_CHIP, 0x8000, GetPRGBase() | (0x00 & GetPRGMask())); - setprg8r(FLASH_CHIP, 0xA000, GetPRGBase() | (0x01 & GetPRGMask())); - setprg8r(FLASH_CHIP, 0xC000, GetPRGBase() | (0x02 & GetPRGMask())); - setprg8r(FLASH_CHIP, 0xE000, GetPRGBase() | (0x03 & GetPRGMask())); - setchr8(latch.data & 3); - setmirror(reg[4] & 0x01); - break; - - case MAPPER_UNROM: - setprg16r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 1) | (latch.data & (GetPRGMask() >> 1))); - setprg16r(FLASH_CHIP, 0xC000, (GetPRGBase() >> 1) | ((GetPRGMask() >> 1) & 0x1F)); - setchr8(GetCHRBase()); - setmirror(reg[4] & 0x01); - break; - - case MAPPER_BANDAI152: - setprg16r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 1) | ((latch.data >> 4) & (GetPRGMask() >> 1))); - setprg16r(FLASH_CHIP, 0xC000, (GetPRGBase() >> 1) | (0xFF & (GetPRGMask() >> 1))); - setchr8(latch.data & 0xF); - setmirror(MI_0 + ((latch.data & 0x80) >> 7)); - break; - - case MAPPER_ANROM: - setprg32r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 2) | (latch.data & (GetPRGMask() >> 2))); - setchr8(GetCHRBase()); - setmirror(MI_0 + ((latch.data & 0x10) >> 4)); - break; - - case MAPPER_GNROM: - setprg32r(FLASH_CHIP, 0x8000, (GetPRGBase() >> 2) | ((latch.data >> 4) & (GetPRGMask() >> 2))); - setchr8(latch.data & 0x03); - setmirror(reg[4] & 0x01); - break; - - case MAPPER_SLROM: - case MAPPER_SNROM: - setprg8r(WRAM_CHIP, 0x6000, 0); - MMC1_FixPRG(); - MMC1_FixCHR(); - MMC1_FixMIR(); - break; - - case MAPPER_MMC3: - setprg8r(WRAM_CHIP, 0x6000, 0); - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - - case MAPPER_TLSROM: - setprg8r(WRAM_CHIP, 0x6000, 0); - MMC3_FixPRG(); - MMC3_FixCHR(); - if (mmc3.cmd & 0x80) { - setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); - } else { - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); - } - break; - - case MAPPER_189: - setprg8r(WRAM_CHIP, 0x6000, 0); - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - - case MAPPER_VRC2_22: - setprg8r(WRAM_CHIP, 0x6000, 0); - VRC24_FixPRG(); - VRC24_FixCHR(); - VRC24_FixMIR(); - break; - - case MAPPER_VRC4_23: - case MAPPER_VRC4_25: - setprg8r(WRAM_CHIP, 0x6000, 0); - VRC24_FixPRG(); - VRC24_FixCHR(); - VRC24_FixMIR(); - break; - - case MAPPER_VRC6: - setprg8r(WRAM_CHIP, 0x6000, 0); - VRC6_FixPRG(); - VRC6_FixCHR(); - break; - } - } else { - setprg8r(FLASH_CHIP, 0x8000, GetPRGBase()); - setprg8r(FLASH_CHIP, 0xA000, 0x3D); - setprg8r(FLASH_CHIP, 0xC000, 0x3E); - setprg8r(FLASH_CHIP, 0xE000, 0x3F); - setchr8(GetCHRBase()); - setmirror(reg[4] & 0x01); - } -} - -static void apply_mode(void) { - if (reg[0] & 0x80) { - switch (reg[0] & 0x1F) { - case MAPPER_ANROM: - case MAPPER_CNROM: - case MAPPER_UNROM: - case MAPPER_GNROM: - case MAPPER_BANDAI152: - Latch_RegReset(); - break; - case MAPPER_SLROM: - case MAPPER_SNROM: - MMC1_Reset(); - break; - case MAPPER_189: - case MAPPER_MMC3: - case MAPPER_TLSROM: - MMC3_Reset(); - break; - case MAPPER_VRC2_22: - vrc24.VRC4 = FALSE; - vrc24.A0 = 0x02; - vrc24.A1 = 0x01; - VRC24_Reset(); - break; - case MAPPER_VRC4_23: - vrc24.VRC4 = TRUE; - vrc24.A0 = 0x05; - vrc24.A1 = 0x0A; - VRC24_Reset(); - break; - case MAPPER_VRC4_25: - vrc24.VRC4 = TRUE; - vrc24.A0 = 0x0A; - vrc24.A1 = 0x05; - VRC24_Reset(); - break; - case MAPPER_VRC6: - VRC6_Reset(); - break; - } - } -} - -static DECLFR(M446Read) { - return FlashROM_Read(A); -} - -static DECLFW(M446WriteLatch) { - CartBW(A, V); - if (reg[0] & 0x1F == MAPPER_189) { - reg[8] = A & 0xFF; - Sync(); - } -} - -static DECLFW(M446WriteReg) { - if (!(reg[0] & 0x80)) { - A &= 0x07; - if (!A && !iNESCart.submapper && ((V & 0x1F) == 0x01)) { - V = (V & ~0x1F) | MAPPER_SNROM; - } - reg[A] = V; - apply_mode(); - Sync(); - } -} - -static DECLFW(M446Write) { - if (reg[0] & 0x80) { - switch (reg[0] & 0x1F) { - case MAPPER_ANROM: - case MAPPER_CNROM: - case MAPPER_UNROM: - case MAPPER_GNROM: - case MAPPER_BANDAI152: - Latch_Write(A, V); - break; - - case MAPPER_SLROM: - case MAPPER_SNROM: - MMC1_Write(A, V); - break; - - case MAPPER_189: - case MAPPER_MMC3: - case MAPPER_TLSROM: - MMC3_Write(A, V); - break; - - case MAPPER_VRC2_22: - VRC24_Write(A, V); - break; - - case MAPPER_VRC4_23: - VRC24_Write(A, V); - break; - - case MAPPER_VRC4_25: - VRC24_Write(A, V); - break; - - case MAPPER_VRC6: - VRC6_Write(A, V); - break; - } - } else { - FlashROM_Write(A, V); - } -} - -static void M446HBIRQHook(void) { - if (reg[0] & 0x80) { - switch (reg[0] & 0x1F) { - case MAPPER_MMC3: - case MAPPER_TLSROM: - case MAPPER_189: - MMC3_IRQHBHook(); - break; - } - } -} - -static void M446CPUIRQHook(int a) { - FlashROM_CPUCyle(a); - - if (reg[0] & 0x80) { - switch (reg[0] & 0x1F) { - case MAPPER_VRC2_22: - case MAPPER_VRC4_23: - case MAPPER_VRC4_25: - VRC24_IRQCPUHook(a); - break; - - case MAPPER_VRC6: - VRC6_IRQCPUHook(a); - break; - } - } -} - -static void M446Close(void) { - if (flash) { - FCEU_free(flash); - flash = NULL; - } -} - -static void M446Reset(void) { - memset(reg, 0, sizeof(reg)); - apply_mode(); - Sync(); -} - -static void M446Power(void) { - memset(reg, 0, sizeof(reg)); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - - SetReadHandler(0x8000, 0xFFFF, M446Read); - - SetWriteHandler(0x5000, 0x5FFF, M446WriteReg); - SetWriteHandler(0x6000, 0x6FFF, M446WriteLatch); - SetWriteHandler(0x8000, 0xFFFF, M446Write); - - apply_mode(); - Sync(); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper446_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - - MMC1_Init(info, FALSE, FALSE); - MMC1_pwrap = M446MMC1PW; - MMC1_cwrap = M446MMC1CW; - - MMC3_Init(info, FALSE, FALSE); - MMC3_pwrap = M446MMC3PW; - MMC3_cwrap = M446MMC3CW; - - VRC24_Init(info, VRC4, 0x01, 0x02, FALSE, TRUE); - VRC24_pwrap = M446VRC24PW; - VRC24_cwrap = M446VRC24CW; - - VRC6_Init(info, 0x01, 0x02, FALSE); - VRC6_pwrap = M446VRC6PW; - VRC6_cwrap = M446VRC6CW; - - info->Power = M446Power; - info->Reset = M446Reset; - info->Close = M446Close; - - MapIRQHook = M446CPUIRQHook; - GameHBIRQHook = M446HBIRQHook; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(WRAM_CHIP, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } - - /* Allocate memory for flash */ - flash = (uint8 *)FCEU_gmalloc(PRGsize[0]); - SetupCartPRGMapping(FLASH_CHIP, flash, PRGsize[0], 1); - AddExState(flash, PRGsize[0], 0, "FLSH"); - memcpy(flash, PRGptr[0], PRGsize[0]); - FlashROM_Init(flash, PRGsize[0], 0x01, 0x7E, 131072, 0xAAA, 0x555); -} diff --git a/src/mappers/mapper447.c b/src/mappers/mapper447.c deleted file mode 100644 index 68345ea7f..000000000 --- a/src/mappers/mapper447.c +++ /dev/null @@ -1,94 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 447 - KL-06 (VRC4 clone) - * 1993 New 860-in-1 Over-Valued Golden Version Games multicart - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 reg; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 }, -}; - -static void M447PW(uint16 A, uint16 V) { - uint16 mask = 0x0F; - uint16 base = reg << 4; - - if (reg & 0x04) { - uint8 A14 = (reg & 0x02) ^ 0x02; - setprg8(0x8000, (base & ~mask) | ((vrc24.prg[0] & ~A14) & mask)); - setprg8(0xA000, (base & ~mask) | ((vrc24.prg[1] & ~A14) & mask)); - setprg8(0xC000, (base & ~mask) | ((vrc24.prg[0] | A14) & mask)); - setprg8(0xE000, (base & ~mask) | ((vrc24.prg[1] | A14) & mask)); - } else { - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static void M447CW(uint16 A, uint16 V) { - setchr1(A, (reg << 7) | (V & 0x7F)); -} - -static DECLFR(M447Read) { - if ((A & 0x8000) && (reg & 0x08)) { - return CartBR((A & ~0x03) | (dipsw & 0x03)); - } - return CartBR(A); -} - -static DECLFW(M447WriteReg) { - CartBW(A, V); - if ((vrc24.cmd & 0x01) && !(reg & 0x01)) { - reg = A & 0xFF; - VRC24_FixPRG(); - VRC24_FixCHR(); - } -} - -static void M447Reset(void) { - reg = 0; - dipsw++; - VRC24_FixPRG(); - VRC24_FixCHR(); -} - -static void M447Power(void) { - reg = 0; - dipsw = 0; - VRC24_Power(); - SetReadHandler(0x8000, 0xFFFF, M447Read); - SetWriteHandler(0x6000, 0x7FFF, M447WriteReg); -} - -void Mapper447_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x04, 0x08, 1, 1); - info->Reset = M447Reset; - info->Power = M447Power; - VRC24_pwrap = M447PW; - VRC24_cwrap = M447CW; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper448.c b/src/mappers/mapper448.c deleted file mode 100644 index 106aaa775..000000000 --- a/src/mappers/mapper448.c +++ /dev/null @@ -1,98 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 448 - * VRC4-based 830768C multicart circuit board used by a Super 6-in-1 multicart. - */ - -#include "mapinc.h" -#include "latch.h" -#include "vrc24.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 }, -}; - -static void Sync(void) { - if (reg & 0x08) { /* AOROM */ - setprg32(0x8000, ((reg << 2) & ~0x07) | (latch.data & 0x07)); - setmirror(MI_0 + ((latch.data >> 4) & 0x01)); - } else { - if (reg & 0x04) { /* UOROM */ - setprg16(0x8000, ((reg << 3) & ~0x0F) | (vrc24.prg[0] & 0x0F)); - setprg16(0xC000, ((reg << 3) & ~0x0F) | 0x0F); - } else { /* UNROM */ - setprg16(0x8000, (reg << 3) | (vrc24.prg[0] & 0x07)); - setprg16(0xC000, (reg << 3) | 0x07); - } - switch (vrc24.mirr & 0x03) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } - } - setchr8(0); -} - -static DECLFW(M448WriteReg) { - if (vrc24.cmd & 0x01) { - reg = A & 0xFF; - Sync(); - } -} - -static DECLFW(M448WriteASIC) { - Latch_Write(A, V); - VRC24_Write(A, V); - Sync(); -} - -static void M448Reset(void) { - reg = 0; - Sync(); -} - -static void M448Power(void) { - reg = 0; - Latch_Power(); - VRC24_Power(); - Sync(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, M448WriteReg); - SetWriteHandler(0x8000, 0xFFFF, M448WriteASIC); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper448_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - VRC24_Init(info, VRC4, 0x04, 0x08, 0, 1); - info->Reset = M448Reset; - info->Power = M448Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper449.c b/src/mappers/mapper449.c deleted file mode 100644 index 43943dd34..000000000 --- a/src/mappers/mapper449.c +++ /dev/null @@ -1,59 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - uint32 prg = ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); - uint32 cpuA14 = latch.addr & 0x01; - uint32 nrom = (latch.addr >> 7) & 0x01; - - setprg16(0x8000, prg & ~(cpuA14 * nrom)); - setprg16(0xC000, prg | (cpuA14 * nrom) | (0x07 * !nrom)); - - setchr8(latch.data); - setmirror((((latch.addr >> 1) & 0x01) ^ 0x01)); -} - -static DECLFR(M449Read) { - if (latch.addr & 0x200) { - A |= dipsw; - } - return CartBR(A); -} - -static void M449Reset(void) { - dipsw = (dipsw + 1) & 0xF; - Latch_RegReset(); -} - -void Mapper449_Init(CartInfo *info) { - Latch_Init(info, Sync, M449Read, FALSE, FALSE); - info->Reset = M449Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper450.c b/src/mappers/mapper450.c deleted file mode 100644 index 4522711ea..000000000 --- a/src/mappers/mapper450.c +++ /dev/null @@ -1,39 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 450 - YY841157C - */ - -#include "mapinc.h" -#include "vrc24.h" - -static void M450PW(uint16 A, uint16 V) { - setprg8(A, (vrc24.latch << 4) | (V & 0x0F)); -} - -static void M450CW(uint16 A, uint16 V) { - setchr1(A, (vrc24.latch << 7) | (V & 0x7F)); -} - -void Mapper450_Init(CartInfo *info) { - VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); - VRC24_pwrap = M450PW; - VRC24_cwrap = M450CW; -} diff --git a/src/mappers/mapper451.c b/src/mappers/mapper451.c deleted file mode 100644 index e1d471641..000000000 --- a/src/mappers/mapper451.c +++ /dev/null @@ -1,111 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 451 */ -/* Uses flashrom to save high scores. */ - -#include "mapinc.h" -#include "mmc3.h" -#include "flashrom.h" - -static uint8 reg; - -static uint8 *FLASHROM = NULL; -static uint32 FLASHROM_size = 0; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M451FixPRG(void) { - setprg8r(0x10, 0x8000, 0); - setprg8r(0x10, 0xA000, 0x10 | ((reg << 2) & 0x08) | (reg & 0x01)); - setprg8r(0x10, 0xC000, 0x20 | ((reg << 2) & 0x08) | (reg & 0x01)); - setprg8r(0x10, 0xE000, 0x30); -} - -static void M451FixCHR(void) { - setchr8(reg & 0x01); -} - -static DECLFR(M451Read) { - return FlashROM_Read(A); -} - -static DECLFW(M451Write) { - FlashROM_Write(A, V); - switch (A & 0xE000) { - case 0xA000: - MMC3_CMDWrite(0xA000, A & 0x01); - break; - case 0xC000: - A &= 0xFF; - MMC3_IRQWrite(0xC000, A - 1); - MMC3_IRQWrite(0xC001, 0); - MMC3_IRQWrite(0xE000 + ((A == 0xFF) ? 0x00 : 0x01), 0x00); - break; - case 0xE000: - reg = A & 0x03; - MMC3_FixPRG(); - MMC3_FixCHR(); - break; - } -} - -static void M451Power(void) { - MMC3_Power(); - SetReadHandler(0x8000, 0xFFFF, M451Read); - SetWriteHandler(0x8000, 0xFFFF, M451Write); -} - -static void M451Close(void) { - MMC3_Close(); - if (FLASHROM) { - FCEU_free(FLASHROM); - } - FLASHROM = NULL; -} - -void Mapper451_Init(CartInfo *info) { - uint32 w, r; - - MMC3_Init(info, 0, 0); - info->Power = M451Power; - info->Close = M451Close; - MMC3_FixPRG = M451FixPRG; - MMC3_FixCHR = M451FixCHR; - MapIRQHook = FlashROM_CPUCyle; - AddExState(StateRegs, ~0, 0, NULL); - - info->battery = 1; - FLASHROM_size = PRGsize[0]; - FLASHROM = (uint8 *)FCEU_gmalloc(FLASHROM_size); - info->SaveGame[0] = FLASHROM; - info->SaveGameLen[0] = FLASHROM_size; - AddExState(FLASHROM, FLASHROM_size, 0, "FLAS"); - /* copy PRG ROM into FLASHROM, use it instead of PRG ROM */ - for (w = 0, r = 0; w < FLASHROM_size; w++) { - FLASHROM[w] = PRGptr[0][r]; - ++r; - } - SetupCartPRGMapping(0x10, FLASHROM, FLASHROM_size, 0); - FlashROM_Init(FLASHROM, FLASHROM_size, 0x37, 0x86, 65536, 0x0555, 0x02AA); -} diff --git a/src/mappers/mapper452.c b/src/mappers/mapper452.c deleted file mode 100644 index b42fd992a..000000000 --- a/src/mappers/mapper452.c +++ /dev/null @@ -1,80 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* DS-9-27. Absolutely insane PCB that overlays 8 KiB of WRAM into a selectable position between $8000 and $E000. */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint16 prgbank = latch.addr >> 1; - uint16 prgram_addr = 0x8000 | ((latch.data << 9) & 0x6000); - - if (latch.data & 0x02) { - setprg8(0x8000, prgbank); - setprg8(0xA000, prgbank); - setprg8(0xC000, prgbank); - setprg8(0xE000, prgbank); - } else if (latch.data & 0x08) { - setprg8(0x8000, (prgbank & ~0x01) | 0); - setprg8(0xA000, (prgbank & ~0x01) | 1); - setprg8(0xC000, (prgbank & ~0x01) | 2); - setprg8(0xE000, (prgbank & ~0x01) | 3 - | (latch.data & 0x04) - | ((latch.data & 0x04) && (latch.data & 0x40) ? 0x08 : 0x00)); - } else { - setprg16(0x8000, latch.addr >> 2); - setprg16(0xC000, 0); - } - - setchr8(0); - setmirror((latch.data & 0x01) ^ 0x01); - - setprg8r(0x10, prgram_addr, 0); - if (latch.data & 0x02) { - setprg8r(0x10, prgram_addr ^ 0x4000, 0); - } -} - -static DECLFW(M452Write) { - switch (A & 0xE000) { - case 0x8000: - case 0xA000: - case 0xC000: - Latch_Write(A, V); - break; - case 0xE000: - CartBW(A, V); - break; - } -} - -static void M452Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M452Write); -} - -void Mapper452_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, TRUE, FALSE); - info->Reset = Latch_RegReset; - info->Power = M452Power; -} diff --git a/src/mappers/mapper453.c b/src/mappers/mapper453.c deleted file mode 100644 index 11eb0aea5..000000000 --- a/src/mappers/mapper453.c +++ /dev/null @@ -1,59 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 453 - Realtec 8042 - * 3-in-1 1995 World Competitive Champion Edition (DG-002) - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.data & 0x40) { - setprg32(0x8000, ((latch.data >> 3) & 0x18) | (latch.data & 0x07)); - setmirror(MI_0 + (((latch.data >> 4) & 0x01) ^ 0x01)); - } else { - setprg16(0x8000, ((latch.data >> 2) & 0x38) | (latch.data & 0x07)); - setprg16(0xC000, (latch.data >> 2 & 0x38) | 0x07); - setmirror(((latch.data >> 4) & 0x01) ^ 0x01); - } - setchr8(0); -} - -static DECLFW(M453Write) { - if (latch.data & 0xE0) { - latch.data = (latch.data & 0xE0) | (V & ~0xE0); - } else { - latch.data = V; - } - Sync(); -} - -static void M453Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M453Write); -} - -void Mapper453_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M453Power; - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper454.c b/src/mappers/mapper454.c deleted file mode 100644 index 644cbbd87..000000000 --- a/src/mappers/mapper454.c +++ /dev/null @@ -1,63 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NOTE: Only loading Contra after a reset? RAM init also affects powerup */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = ((latch.addr >> 3) & 0x20) | ((latch.addr >> 2) & 0x1F); - uint8 cpuA14 = latch.addr & 0x01; - uint8 nrom = (latch.addr >> 7) & 0x01; - uint8 unrom = (latch.addr >> 9) & 0x01; - - setprg16(0x8000, ((prg & ~cpuA14) & ~(0x07 * unrom)) | (latch.data * unrom)); - setprg16(0xC000, ((prg | cpuA14) & ~(0x07 * !nrom * !unrom)) | (0x07 * !nrom * unrom)); - setchr8(0); - setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); - if (nrom) { - /* CHR-RAM write protect hack, needed for some multicarts */ - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 0); - } else { - SetupCartCHRMapping(0, CHRptr[0], 0x2000, 1); - } -} - -static DECLFW(M454Write) { - if (latch.addr & 0x100) { - latch.data = V & 0x07; - } else { - latch.data = V; - latch.addr = A; - } - Sync(); -} - -static void M454Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M454Write); -} - -void Mapper454_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, 0, 0); - info->Power = M454Power; -} diff --git a/src/mappers/mapper455.c b/src/mappers/mapper455.c deleted file mode 100644 index f578d1afb..000000000 --- a/src/mappers/mapper455.c +++ /dev/null @@ -1,79 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; - -static void M455PW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x01) ? 0x1F : 0x0F; - uint16 base = ((reg[0] >> 2) & 0x10) | ((reg[1] << 1) & 0x08) | ((reg[0] >> 2) & 0x07); - - if (reg[0] & 0x01) { - if (reg[0] & 0x02) { - setprg32(0x8000, base >> 1); - } else { - setprg16(0x8000, base); - setprg16(0xC000, base); - } - } else { - setprg8(A, ((base << 1) & ~mask) | (V & mask)); - } -} - -static void M455CW(uint16 A, uint16 V) { - uint16 mask = (reg[1] & 0x02) ? 0xFF : 0x7F; - uint16 base = ((reg[0] >> 2) & 0x10) | ((reg[1] << 1) & 0x08) | ((reg[0] >> 2) & 0x07); - - setchr1(A, ((base << 4) & ~mask) | (V & mask)); -} - -static DECLFW(M455Write) { - if (A & 0x100) { - reg[0] = V; - reg[1] = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M455Reset(void) { - reg[0] = 1; - reg[1] = 0; - MMC3_Reset(); -} - -static void M455Power(void) { - reg[0] = 1; - reg[1] = 0; - MMC3_Power(); - SetWriteHandler(0x4100, 0x5FFF, M455Write); -} - -void Mapper455_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M455CW; - MMC3_pwrap = M455PW; - info->Power = M455Power; - info->Reset = M455Reset; - AddExState(reg, 2, 0, "EXPR"); -} diff --git a/src/mappers/mapper456.c b/src/mappers/mapper456.c deleted file mode 100644 index 9139dfacf..000000000 --- a/src/mappers/mapper456.c +++ /dev/null @@ -1,61 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2022 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M456PW(uint16 A, uint16 V) { - setprg8(A, (reg << 4) | (V & 0x0F)); -} - -static void M456CW(uint16 A, uint16 V) { - setchr1(A, (reg << 7) | (V & 0x7F)); -} - -static DECLFW(M456Write) { - if (A & 0x100) { - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M456Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M456Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x4100, 0x5FFF, M456Write); -} - -void Mapper456_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_cwrap = M456CW; - MMC3_pwrap = M456PW; - info->Power = M456Power; - info->Reset = M456Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper457.c b/src/mappers/mapper457.c deleted file mode 100644 index f47c83f28..000000000 --- a/src/mappers/mapper457.c +++ /dev/null @@ -1,67 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M457CW(uint16 A, uint16 V) { - uint32 mask = (reg & 0x08) ? 0xFF : 0x7F; - uint32 base = reg << 7; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M457PW(uint16 A, uint16 V) { - uint32 mask = (reg & 0x08) ? 0x1F : 0x0F; - uint32 base = reg << 4; - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static DECLFW(M457Write) { - if (MMC3_WramIsWritable()) { - CartBW(A, V); - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M457Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M457Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, M457Write); -} - -void Mapper457_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M457CW; - MMC3_pwrap = M457PW; - info->Reset = M457Reset; - info->Power = M457Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper458.c b/src/mappers/mapper458.c deleted file mode 100644 index 07eb85ead..000000000 --- a/src/mappers/mapper458.c +++ /dev/null @@ -1,82 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static void M458CW(uint16 A, uint16 V) { - uint16 mask = 0x7F; - uint16 base = reg << 4; - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M458PW(uint16 A, uint16 V) { - uint8 prg = reg & 0x0F; - - if (reg & 0x10) { - setprg32(0x8000, prg >> 1); - } else { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } -} - -static DECLFR(M458Read) { - if ((reg & 0x20) && (dipsw & 0x03)) { - return CartBR((A & ~0x1F) | (dipsw & 0x1F)); - } - return CartBR(A); -} - -static DECLFW(M458Write) { - if (MMC3_WramIsWritable()) { - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M458Reset(void) { - reg = 0; - dipsw++; - MMC3_Reset(); -} - -static void M458Power(void) { - reg = 0; - dipsw = 0; - MMC3_Power(); - SetReadHandler(0x8000, 0xFFFF, M458Read); - SetWriteHandler(0x6000, 0x7FFF, M458Write); -} - -void Mapper458_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M458CW; - MMC3_pwrap = M458PW; - info->Reset = M458Reset; - info->Power = M458Power; - AddExState(®, 1, 0, "EXPR"); - AddExState(&dipsw, 1, 0, "CMD0"); -} diff --git a/src/mappers/mapper459.c b/src/mappers/mapper459.c deleted file mode 100644 index 52ad00122..000000000 --- a/src/mappers/mapper459.c +++ /dev/null @@ -1,42 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = latch.addr >> 4; - uint8 chr = (latch.addr & 0x03) | ((latch.addr >> 2) & 0x04) | ((latch.addr >> 4) & 0x08); - uint8 mirr = ((latch.addr >> 8) & 0x01) ^ 0x01; - - if (latch.addr & 0x04) { - setprg32(0x8000, prg >> 1); - } else { - setprg16(0x8000, prg ); - setprg16(0xC000, prg | 0x07); - } - setchr8(chr); - setmirror(mirr); -} - -void Mapper459_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper460.c b/src/mappers/mapper460.c deleted file mode 100644 index f69db9184..000000000 --- a/src/mappers/mapper460.c +++ /dev/null @@ -1,112 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void M460PW(uint16 A, uint16 V) { - uint32 mask = 0x0F; - uint32 base = reg << 4; - - if (reg & 0x20) { - /* Menu selection by selectively connecting CPU D7 to reg or not */ - if (reg & 0x10) { - setprg8(0x8000, (base & ~mask) | ((mmc3.reg[6] & ~0x02) & mask)); - setprg8(0xA000, (base & ~mask) | ((mmc3.reg[7] & ~0x02) & mask)); - setprg8(0xC000, (base & ~mask) | ((mmc3.reg[6] | 0x02) & mask)); - setprg8(0xE000, (base & ~mask) | ((mmc3.reg[7] | 0x02) & mask)); - } else { - setprg8(0x8000, (base & ~mask) | (mmc3.reg[6] & mask)); - setprg8(0xA000, (base & ~mask) | (mmc3.reg[7] & mask)); - setprg8(0xC000, (base & ~mask) | (mmc3.reg[6] & mask)); - setprg8(0xE000, (base & ~mask) | (mmc3.reg[7] & mask)); - } - } else { - setprg8(A, (base & ~mask) | (V & mask)); - } -} - -static void M460CW(uint16 A, uint16 V) { - if (reg & 0x04) { - setchr2(0x0000, mmc3.reg[0] & 0xFE); - setchr2(0x0800, mmc3.reg[1] | 0x01); - setchr2(0x1000, mmc3.reg[2]); - setchr2(0x1800, mmc3.reg[5]); - } else { - setchr8r(0x10, 0); - } -} - -static DECLFR(M460Read) { - /* Menu selection by selectively connecting reg's D7 to PRG /CE or not */ - if ((reg & 0x80) && (dipsw & 0x01)) { - return CPU_OPENBUS; - } - return CartBR(A); -} - -static DECLFW(M460Write) { - if (MMC3_WramIsWritable()) { - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); - } -} - -static void M460Reset(void) { - reg = 0; - dipsw++; - MMC3_Reset(); -} - -static void M460Power(void) { - reg = 0; - dipsw = 0; - MMC3_Power(); - SetReadHandler(0x8000, 0xFFFF, M460Read); - SetWriteHandler(0x6000, 0x7FFF, M460Write); -} - -static void M460close(void) { - MMC3_Close(); -} - -void Mapper460_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M460CW; - MMC3_pwrap = M460PW; - info->Power = M460Power; - info->Reset = M460Reset; - info->Close = M460close; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAM = (uint8 *)FCEU_gmalloc(8192); - SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); - AddExState(CHRRAM, 8192, 0, "CRAM"); -} diff --git a/src/mappers/mapper461.c b/src/mappers/mapper461.c deleted file mode 100644 index 01fad0118..000000000 --- a/src/mappers/mapper461.c +++ /dev/null @@ -1,40 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = (latch.addr << 1) | ((latch.addr >> 5) & 0x01); - uint8 chr = latch.addr >> 8; - - if (!(latch.addr & 0x10)) { - setprg32(0x8000, prg >> 1); - } else { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } - setchr8(chr); - setmirror(((latch.addr >> 7) & 0x01) ^ 0x01); -} - -void Mapper461_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); -} diff --git a/src/mappers/mapper463.c b/src/mappers/mapper463.c deleted file mode 100644 index 813afe95f..000000000 --- a/src/mappers/mapper463.c +++ /dev/null @@ -1,77 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 regs[4]; -static uint8 dipsw; - -static SFORMAT StateRegs[] = { - { regs, 4, "EXPR" }, - { &dipsw, 1, "DPSW" }, - { 0 } -}; - -static void Sync(void) { - uint8 prg = regs[1]; - uint8 chr = regs[2]; - uint8 mirr = (regs[0] & 0x01) ^ 0x01; - - if (regs[0] & 0x04) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { - setprg32(0x8000, prg >> 1); - } - setchr8(chr); - setmirror(mirr); -} - -static DECLFW(M463Write5000) { - if (A & (0x10 << dipsw)) { - regs[A & 0x03] = V; - Sync(); - } -} - -static void M463Reset(void) { - dipsw = (dipsw + 1) & 0x07; - regs[0] = regs[1] = regs[2] = regs[3] = 0; - Sync(); -} - -static void M463Power(void) { - dipsw = 0; - regs[0] = regs[1] = regs[2] = regs[3] = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, M463Write5000); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper463_Init(CartInfo *info) { - info->Power = M463Power; - info->Reset = M463Reset; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper464.c b/src/mappers/mapper464.c deleted file mode 100644 index 327f94254..000000000 --- a/src/mappers/mapper464.c +++ /dev/null @@ -1,42 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = latch.addr >> 7; - uint8 chr = latch.addr & 0x1F; - uint8 mirr = ((latch.addr >> 5) & 0x01) ^ 0x01; - - if (latch.addr & 0x40) { - setprg32(0x8000, prg >> 1); - } else { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } - setchr8(chr); - setmirror(mirr); -} - -void Mapper464_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper465.c b/src/mappers/mapper465.c deleted file mode 100644 index 272c43e3a..000000000 --- a/src/mappers/mapper465.c +++ /dev/null @@ -1,62 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - uint8 prg = ((latch.addr >> 2) & 0x1F) | ((latch.addr >> 5) & 0x20); - - if (latch.addr & 0x200) { - /* unrom */ - setprg16(0x8000, (prg & ~0x07) | (latch.data & 0x07)); - setprg16(0xC000, prg | 0x07); - } else { - if (latch.addr & 0x01) { - setprg32(0x8000, prg >> 1); - } else { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } - } - setchr8(0); - setmirror(((latch.addr >> 1) & 0x01) ^ 0x01); -} - -static DECLFW(M465WriteLatch) { - if (latch.addr & 0x200) { - /* unrom latch */ - latch.data = V; - } else { - latch.addr = A & 0xFFFF; - } - Sync(); -} - -static void M465Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M465WriteLatch); -} - -void Mapper465_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M465Power; - info->Reset = Latch_RegReset; -} \ No newline at end of file diff --git a/src/mappers/mapper466.c b/src/mappers/mapper466.c deleted file mode 100644 index 216a3de33..000000000 --- a/src/mappers/mapper466.c +++ /dev/null @@ -1,108 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 regs[4]; - -static SFORMAT StateRegs[] = { - { regs, 4, "EXPR" }, - { 0 } -}; - -static uint32 getPRGBank(void) { - return ((regs[1] << 5) | ((regs[0] << 1) & 0x1E) | ((regs[0] >> 5) & 0x01)); -} - -static void Sync(void) { - uint32 prg = getPRGBank(); - - if (regs[0] & 0x40) { - if (regs[0] & 0x10) { - setprg16(0x8000, prg); - setprg16(0xC000, prg); - } else { - setprg32(0x8000, prg >> 1); - } - } else { - setprg16(0x8000, (prg & ~0x07) | (regs[2] & 0x07)); - setprg16(0xC000, (prg & ~0x07) | 0x07); - } - setprg8r(0x10, 0x6000, 0); - setchr8(0); - setmirror(((regs[0] >> 7) & 0x01) ^ 0x01); -} - -static DECLFR(M466ReadLatch) { - /* Return open bus when selecting unpopulated PRG chip */ - if ((getPRGBank() & 0x20) && (PRGsize[0] < (1024 * 1024))) { - return CPU_OPENBUS; - } - return CartBR(A); -} - -static DECLFW(M466Write5000) { - regs[(A >> 11) & 0x01] = A & 0xFF; - Sync(); -} - -static DECLFW(M466WriteLatch) { - regs[2] = V; - Sync(); -} - -static void M466Reset(void) { - regs[0] = regs[1] = 0; - Sync(); -} - - -static void M466Close(void) { -} - -static void M466Power(void) { - regs[0] = regs[1] = 0; - Sync(); - - SetReadHandler(0x8000, 0xFFFF, M466ReadLatch); - SetWriteHandler(0x5000, 0x5FFF, M466Write5000); - SetWriteHandler(0x8000, 0xFFFF, M466WriteLatch); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper466_Init(CartInfo *info) { - info->Power = M466Power; - info->Close = M466Close; - info->Reset = M466Reset; - GameStateRestore = StateRestore; - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper467.c b/src/mappers/mapper467.c deleted file mode 100644 index e25135cb9..000000000 --- a/src/mappers/mapper467.c +++ /dev/null @@ -1,102 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M467PW(uint16 A, uint16 V) { - if (reg & 0x20) { - uint8 mask = (reg & 0x40) ? 0x0F : 0x03; - uint8 base = reg << 1; - - setprg8(A, (base & ~mask) | (V & mask)); - } else { - setprg16(0x8000, reg & 0x1F); - setprg16(0xC000, reg & 0x1F); - } -} - -static void M467CHR(void) { - uint16 base = (reg << 2) & 0x100; - - if (reg & 0x40) { - setchr2(0x0000, base | (mmc3.reg[0] & ~0x01)); - setchr2(0x0800, base | (mmc3.reg[0] | 0x01)); - setchr2(0x1000, base | mmc3.reg[2]); - setchr2(0x1800, base | mmc3.reg[3]); - } else { - setchr2(0x0000, base | (mmc3.reg[0] & ~0x03) | 0); - setchr2(0x0800, base | (mmc3.reg[0] & ~0x03) | 1); - setchr2(0x1000, base | (mmc3.reg[2] & ~0x03) | 2); - setchr2(0x1800, base | (mmc3.reg[3] & ~0x03) | 3); - } -} - -static void M467MIR(void) { - setmirror(((reg >> 7) & 0x01) ^ 0x01); -} - -static DECLFW(M467Write) { - switch (A & 0xF000) { - case 0x9000: - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - default: - switch (A & 0xE001) { - case 0x8000: - mmc3.cmd = V & 0x3F; - break; - case 0x8001: - mmc3.reg[mmc3.cmd & 0x07] = V; - if (mmc3.cmd < 6) MMC3_FixCHR(); - else MMC3_FixPRG(); - break; - case 0xA000: - break; - } - } -} - - -static void M467Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void M467Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x8000, 0xBFFF, M467Write); -} - -void Mapper467_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_FixCHR = M467CHR; - MMC3_FixMIR = M467MIR; - MMC3_pwrap = M467PW; - info->Power = M467Power; - info->Reset = M467Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper471.c b/src/mappers/mapper471.c deleted file mode 100644 index 14ec8262d..000000000 --- a/src/mappers/mapper471.c +++ /dev/null @@ -1,52 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 471 denotes the Impact Soft IM1 circuit board, used for Haratyler (without HG or MP) and Haraforce. - * It is basically INES Mapper 201 with the addition of a scanline IRQ.*/ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, latch.addr); - setchr8(latch.addr); -} - -static DECLFW(M471Write) { - X6502_IRQEnd(FCEU_IQEXT); - Latch_Write(A, V); -} - -static void M471HBHook(void) { - X6502_IRQBegin(FCEU_IQEXT); -} - -static void M471Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M471Write); -} - -void Mapper471_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M471Power; - info->Reset = Latch_RegReset; - GameHBIRQHook = M471HBHook; -} diff --git a/src/mappers/mapper500.c b/src/mappers/mapper500.c deleted file mode 100644 index da176c706..000000000 --- a/src/mappers/mapper500.c +++ /dev/null @@ -1,58 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg4(0x7000, 0); - setprg16(0x8000, (reg[0] << 3) | (latch.data & 0x07)); - setprg16(0xC000, (reg[0] << 3) | 0x07); - setchr8(0); - setmirror(reg[1] & 0x01); -} - -static DECLFW(M500WriteReg) { - if (!(reg[1] & 0x80)) { - reg[A & 0x01] = V; - Sync(); - } -} - -static void M500Power(void) { - reg[0] = reg[1] = 0; - Latch_Power(); - SetReadHandler(0x7000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x6FFF, M500WriteReg); -} - -void Mapper500_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M500Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper501.c b/src/mappers/mapper501.c deleted file mode 100644 index b0bad58c4..000000000 --- a/src/mappers/mapper501.c +++ /dev/null @@ -1,57 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg4(0x7000, 0); - setprg32(0x8000, (reg[0] << 2) + (latch.data & 0x07)); - setchr8(0); - setmirror(MI_0 + ((latch.data >> 4) & 0x01)); -} - -static DECLFW(M501WriteReg) { - if (!(reg[1] & 0x80)) { - reg[A & 0x01] = V; - Sync(); - } -} - -static void M501Power(void) { - reg[0] = reg[1] = 0; - Latch_Power(); - SetReadHandler(0x7000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x6FFF, M501WriteReg); -} - -void Mapper501_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M501Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper502.c b/src/mappers/mapper502.c deleted file mode 100644 index 1df5fa74e..000000000 --- a/src/mappers/mapper502.c +++ /dev/null @@ -1,68 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 reg[2]; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { 0 } -}; - -static void Sync(void) { - uint8 mask = (8 << ((reg[1] >> 4) & 0x03)) - 1; - - setprg4(0x7000, 0); - if (reg[1] & 0x06) { - setprg32(0x8000, (reg[0] << 2) + (latch.data & (mask >> 1))); - } else { - setprg16(0x8000, (reg[0] << 3) + (latch.data & mask)); - setprg16(0xC000, (reg[0] << 3) + mask); - } - setchr8(0); - if (reg[1] & 0x02) { - setmirror(MI_0 + ((latch.data >> 4) & 0x01)); - } else { - setmirror(reg[1] & 0x01); - } -} - -static DECLFW(M502WriteReg) { - if (!(reg[1] & 0x80)) { - reg[A & 0x01] = V; - Sync(); - } -} - -static void M502Power(void) { - reg[0] = reg[1] = 0; - Latch_Power(); - SetReadHandler(0x7000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x6FFF, M502WriteReg); -} - -void Mapper502_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M502Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper512.c b/src/mappers/mapper512.c deleted file mode 100644 index 5ad27d824..000000000 --- a/src/mappers/mapper512.c +++ /dev/null @@ -1,85 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * 8-in-1 Rockin' Kats, Snake, (PCB marked as "8 in 1"), similar to 12IN1, - * but with MMC3 on board, all games are hacked the same, Snake is buggy too! - * - * no reset-citcuit, so selected game can be reset, but to change it you must use power - * - */ - -/* NES 2.0 Mapper 512 is used for 中國大亨 (Zhōngguó Dàhēng) */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M512MIR(void) { - if (reg == 1) { - SetupCartMirroring(4, 0, &CHRRAM[4096]); - } else { - setmirror((mmc3.mirr & 0x01) ^ 0x01); - } -} - -static void M512CW(uint16 A, uint16 V) { - if (reg & 0x02) { - setchr1r(0x10, A, (V & 0x03)); - } else { - setchr1(A, V & 0xFF); - } -} - -static void M512PW(uint16 A, uint16 V) { - setprg8(A, (V & 0x3F)); -} - -static DECLFW(M512Write) { - if (A & 0x100) { - reg = V & 0x03; - MMC3_FixCHR(); - MMC3_FixMIR(); - } -} - -static void M512Close(void) { - MMC3_Close(); -} - -static void M512Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x4100, 0x4FFF, M512Write); -} - -void Mapper512_Init(CartInfo *info) { - MMC3_Init(info, 8, info->battery); - MMC3_cwrap = M512CW; - MMC3_pwrap = M512PW; - MMC3_FixMIR = M512MIR; - info->Power = M512Power; - info->Close = M512Close; - AddExState(®, 1, 0, "EXPR"); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); -} diff --git a/src/mappers/mapper513.c b/src/mappers/mapper513.c deleted file mode 100644 index f12607bdf..000000000 --- a/src/mappers/mapper513.c +++ /dev/null @@ -1,85 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2012 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 513 - Sachen UNL-SA-9602B */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M513CW(uint16 A, uint16 V) { - setchr1(A, V & 0x3F); -} - -static void M513PW(uint16 A, uint16 V) { - if (!(A & 0x4000)) { - setprg8(A, (reg & 0xC0) | (V & 0x3F)); - } else { - setprg8(A, (V & 0x3F)); - } -} - -static DECLFW(M513Write) { - switch (A & 0xE001) { - case 0x8000: - mmc3.cmd = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - break; - case 0x8001: - mmc3.reg[mmc3.cmd & 0x07] = V; - switch (mmc3.cmd & 0x07) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - reg = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - break; - default: - MMC3_FixPRG(); - break; - } - default: - break; - } -} - -static void M513Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x8000, 0x9FFF, M513Write); -} - -void Mapper513_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_pwrap = M513PW; - MMC3_cwrap = M513CW; - mmc3.opts |= 2; - info->SaveGame[0] = CHR_ROM_PTR; - info->SaveGameLen[0] = info->CHRRamSaveSize; - info->Power = M513Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper514.c b/src/mappers/mapper514.c deleted file mode 100644 index 956cf66fe..000000000 --- a/src/mappers/mapper514.c +++ /dev/null @@ -1,95 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" - -static uint8 mode; -static uint32 lastnt; - -static SFORMAT StateRegs[] = { - { &mode, 1, "MODE" }, - { &lastnt, 4, "LSNT" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - setprg32(0x8000, mode & 0x3F); - setchr4(0x0000, lastnt); - setchr4(0x1000, 1); - setmirror(((mode >> 6) & 0x01) ^ 0x01); -} - -static DECLFW(M514Write8) { - if ((A & 0xFFF) == 0) { - mode = V; - Sync(); - } -} - -static void M514PPUHook(uint32 A) { - if ((A & 0x3000) == 0x2000) { - uint32 mask = (mode & 0x40) ? 0x02 : 0x01; - uint32 bank = A >> 10; - if ((mode & 0x80) && (bank & mask)) { - setchr4(0, 1); - lastnt = 1; - } else { - lastnt = 0; - setchr4(0, 0); - } - } -} - -static void M514Reset(void) { - lastnt = 0; - mode = 0; - Sync(); -} - -static void M514Power(void) { - lastnt = 0; - mode = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0x8FFF, M514Write8); -} - -static void M514Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper514_Init(CartInfo *info) { - info->Power = M514Power; - info->Reset = M514Reset; - info->Close = M514Close; - PPU_hook = M514PPUHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper516.c b/src/mappers/mapper516.c deleted file mode 100644 index 05d7874f5..000000000 --- a/src/mappers/mapper516.c +++ /dev/null @@ -1,61 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 516 - Brilliant Com Cocoma Pack */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void M516CW(uint16 A, uint16 V) { -/* FCEU_printf("CHR: A:%04x V:%02x R0:%02x\n", A, V, reg); */ - setchr1(A, ((reg << 5) & 0x180) | (V & 0x7F)); -} - -static void M516PW(uint16 A, uint16 V) { -/* FCEU_printf("PRG: A:%04x V:%02x R0:%02x\n", A, V, reg); */ - setprg8(A, ((reg << 4) & 0x30) | (V & 0x0F)); -} - -static DECLFW(M516Write) { -/* FCEU_printf("Wr: A:%04x V:%02x R0:%02x\n", A, V, reg); */ - if (A & 0x10) { - reg = A & 0x0F; - MMC3_FixPRG(); - MMC3_FixCHR(); - } - MMC3_Write(A, V); -} - -static void M516Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x8000, 0xFFFF, M516Write); -} - -void Mapper516_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M516CW; - MMC3_pwrap = M516PW; - info->Power = M516Power; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/mapper517.c b/src/mappers/mapper517.c deleted file mode 100644 index c89756310..000000000 --- a/src/mappers/mapper517.c +++ /dev/null @@ -1,101 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "mapinc.h" -#include "latch.h" - -static int32 adc_data; -static int32 adc_high; -static int32 adc_low; -static uint8 adc_state; - -static SFORMAT StateRegs[] = { - { &adc_data, sizeof(adc_data), "DATA" }, - { &adc_high, sizeof(adc_high), "DTHI" }, - { &adc_low, sizeof(adc_low), "DTLO" }, - { &adc_state, sizeof(adc_state), "STAT" }, - { 0 }, -}; - -static void Sync(void) { - setprg16(0x8000, latch.data); - setprg16(0xC000, ~0); - setchr8(0); -} - -static DECLFR(M517Read) { - uint8 result = 0; - if (A == 0x6000) { - switch (adc_state) { - case 0: - adc_state = 1; - result = 0; - break; - case 1: - adc_state = 2; - result = 1; - break; - case 2: - if (adc_low > 0) { - adc_low--; - result = 1; - } else { - adc_state = 0; - result = 0; - } - break; - } - } else { - result = adc_high-- > 0 ? 0 : 1; - } - return result; -} - -static DECLFW(M517Write) { - /* TODO: implement mic input from frontend */ - /* adc_data = MIC * 63.0; */ - adc_data = 0.0 * 63.0; - adc_high = adc_data >> 2; - adc_low = 0x40 - adc_high - ((adc_data & 0x03) << 2); - adc_state = 0; - Latch_Write(A,V); -} - -static void M517Reset(void) { - adc_data = 0; - adc_state = 0; - Sync(); -} - -static void M517Power(void) { - adc_data = 0; - adc_state = 0; - Latch_Power(); - SetReadHandler(0x6000, 0x6FFF, M517Read); - SetWriteHandler(0x8000, 0x8FFF, M517Write); -} - -void Mapper517_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M517Power; - info->Reset = M517Reset; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper518.c b/src/mappers/mapper518.c deleted file mode 100644 index cf1023e2b..000000000 --- a/src/mappers/mapper518.c +++ /dev/null @@ -1,109 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Dance 2000 12-in-1 - * - */ - -#include "mapinc.h" - -static uint8 prg, mode; -static uint32 lastnt = 0; - -static SFORMAT StateRegs[] = -{ - { &prg, 1, "REGS" }, - { &mode, 1, "MODE" }, - { &lastnt, 4, "LSNT" }, - { 0 } -}; - -static void Sync(void) { - setmirror((mode ^ 1) & 1); - setprg8r(0x10, 0x6000, 0); - setchr4(0x0000, lastnt); - setchr4(0x1000, 1); - if (mode & 4) { - setprg32(0x8000, prg & 7); - } else { - setprg16(0x8000, prg & 0x0f); - setprg16(0xC000, 0); - } -} - -static DECLFW(M518Write) { - switch (A) { - case 0x5000: prg = V; Sync(); break; - case 0x5200: mode = V; if (mode & 4) Sync(); break; - } -} - -static DECLFR(M518Read) { - if (prg & 0x40) - return CPU_OPENBUS; - else - return CartBR(A); -} - -static void M518Power(void) { - prg = mode = 0; - Sync(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, M518Read); - SetWriteHandler(0x5000, 0x5FFF, M518Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M518PPUHook(uint32 A) { - if (mode & 2) { - if ((A & 0x3000) == 0x2000) { - uint32 curnt = A & 0x800; - if (curnt != lastnt) { - setchr4(0x0000, curnt >> 11); - lastnt = curnt; - } - } - } else { - lastnt = 0; - setchr4(0x0000, 0); - } -} - -static void M518Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper518_Init(CartInfo *info) { - info->Power = M518Power; - info->Close = M518Close; - PPU_hook = M518PPUHook; - GameStateRestore = StateRestore; - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper519.c b/src/mappers/mapper519.c deleted file mode 100644 index e756ada64..000000000 --- a/src/mappers/mapper519.c +++ /dev/null @@ -1,86 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2015 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 519 - * UNIF board name UNL-EH8813A - */ - -#include "mapinc.h" -#include "latch.h" - -static uint8 lock, dipsw, chr, ram[4]; - -static SFORMAT StateRegs[] = { - { &dipsw, 1, "DPSW" }, - { &lock, 1, "LOCK" }, - { &chr, 1, "CREG" }, - { 0 } -}; - -static void Sync(void) { - if (lock == 0) { - if (latch.addr & 0x80) { - setprg16(0x8000, latch.addr); - setprg16(0xC000, latch.addr); - } else { - setprg32(0x8000, latch.addr >> 1); - } - setmirror(((latch.data >> 7) & 0x01) ^ 0x01); - lock = (latch.addr & 0x100) == 0x100; - chr = latch.data & 0x7C; - } - setchr8(chr | (latch.data & 0x03)); -} - -static DECLFR(M519ReadRAM) { - return ram[A & 0x03]; -} - -static DECLFW(M519WriteRAM) { - ram[A & 0x03] = V & 0x0F; -} - -static DECLFR(M519Read) { - if (latch.addr & 0x40) { - return CartBR((A & 0xFFF0) | (dipsw & 0x0F)); - } - return CartBR(A); -} - -static void M519Power(void) { - dipsw = lock = 0; - Latch_Power(); - SetReadHandler(0x5800, 0x5FFF, M519ReadRAM); - SetWriteHandler(0x5800, 0x5FFF, M519WriteRAM); -} - -static void M519Reset(void) { - lock = 0; - dipsw++; - Latch_RegReset(); -} - -void Mapper519_Init(CartInfo *info) { - Latch_Init(info, Sync, M519Read, FALSE, FALSE); - info->Reset = M519Reset; - info->Power = M519Power; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper520.c b/src/mappers/mapper520.c deleted file mode 100644 index cad8d0e47..000000000 --- a/src/mappers/mapper520.c +++ /dev/null @@ -1,57 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 520 - VRC4 clone - * Datach Dragon Ball Z/Datach Yu Yu Hakusho - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 PPUCHRBus; - -static SFORMAT StateRegs[] = { - { &PPUCHRBus, 1, "PPUC" }, - { 0 }, -}; - -static void M520PW(uint16 A, uint16 V) { - setprg8(A, ((vrc24.chr[PPUCHRBus] << 2) & 0x20) | (V & 0x1F)); -} - -static void M520CW(uint16 A, uint16 V) { - setchr1(A, V & 0x07); -} - -static void M520PPUHook(uint32 A) { - uint8 bank = (A & 0x1FFF) >> 10; - if ((PPUCHRBus != bank) && ((A & 0x3000) != 0x2000)) { - PPUCHRBus = bank; - VRC24_FixPRG(); - } -} - -void Mapper520_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x04, 0x08, 0, 1); - PPU_hook = M520PPUHook; - VRC24_pwrap = M520PW; - VRC24_cwrap = M520CW; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper521.c b/src/mappers/mapper521.c deleted file mode 100644 index 3212daf59..000000000 --- a/src/mappers/mapper521.c +++ /dev/null @@ -1,52 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg; - -static void Sync(void) { - setprg16(0x8000, prg); - setprg16(0xC000, 0x08); - setchr8(0); -} - -static DECLFW(M521Write) { - prg = V; - Sync(); -} - -static void M521Power(void) { - prg = 0; - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x5020, 0x5020, M521Write); -} - -static void Restore(int version) { - Sync(); -} - -void Mapper521_Init(CartInfo *info) { - GameStateRestore = Restore; - info->Power = M521Power; - AddExState(&prg, 1, 0, "LATC"); -} diff --git a/src/mappers/mapper522.c b/src/mappers/mapper522.c deleted file mode 100644 index c7302892e..000000000 --- a/src/mappers/mapper522.c +++ /dev/null @@ -1,83 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2011 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 522 - UNL-LH10 - * - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg[8], cmd; - -static SFORMAT StateRegs[] = -{ - { &cmd, 1, "CMD" }, - { reg, 8, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x6000, ~1); - setprg8(0x8000, reg[6]); - setprg8(0xA000, reg[7]); - setprg8r(0x10, 0xC000, 0); - setprg8(0xE000, ~0); - setchr8(0); - setmirror(0); -} - -static DECLFW(M522Write) { - if (A & 0x0001) { - reg[cmd & 0x07] = V; - Sync(); - } else { - cmd = V; - } -} - -static void M522Power(void) { - FDSSound_Power(); - reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = reg[6] = reg[7] = 0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0x9FFF, M522Write); - SetWriteHandler(0xC000, 0xDFFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M522Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper522_Init(CartInfo *info) { - info->Power = M522Power; - info->Close = M522Close; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper524.c b/src/mappers/mapper524.c deleted file mode 100644 index e0106b3bc..000000000 --- a/src/mappers/mapper524.c +++ /dev/null @@ -1,74 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 524 - BTL-900218 */ -/* http://wiki.nesdev.com/w/index.php/UNIF/900218 - * NES 2.0 Mapper 524 describes the PCB used for the pirate port Lord of King or Axe of Fight. - * UNIF board name is BTL-900218. - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint16 IRQCount; -static uint8 IRQa; - -static SFORMAT IRQStateRegs[] = { - { &IRQCount, 2, "IRQC" }, - { &IRQa, 1, "IRQA" }, - - { 0 } -}; - -static DECLFW(M524Write) { - switch (A & 0xF00C) { - case 0xF008: - IRQa = 1; - break; - case 0xF00C: - IRQa = 0; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -static void M524IRQHook(int a) { - if (!IRQa) - return; - - IRQCount += a; - if (IRQCount & 1024) - X6502_IRQBegin(FCEU_IQEXT); -} - -static void M524Power(void) { - IRQa = IRQCount = 0; - VRC24_Power(); - SetWriteHandler(0xF000, 0xFFFF, M524Write); -} - -void Mapper524_Init(CartInfo *info) { - VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); - info->Power = M524Power; - MapIRQHook = M524IRQHook; - AddExState(IRQStateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper525.c b/src/mappers/mapper525.c deleted file mode 100644 index 15c45c103..000000000 --- a/src/mappers/mapper525.c +++ /dev/null @@ -1,87 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES Mapper 525 - UNL-M525 - * http://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_525 - * NES 2.0 Mapper 525 is used for a bootleg version of versions of Contra and 月風魔伝 (Getsu Fūma Den). - * Its similar to Mapper 23 Submapper 3) with non-nibblized CHR-ROM bank registers. - */ - -#include "mapinc.h" - -static uint8 prg; -static uint8 chr[8]; -static uint8 mirr; - -static SFORMAT StateRegs[] = { - { chr, 8, "CHRR" }, - { &prg, 1, "PRGR" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - setprg16(0x8000, prg >> 1); - setprg16(0xC000, ~0); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - setmirror((mirr & 0x01) ^ 0x01); -} - -static DECLFW(M525WritePRG) { - prg = V; - Sync(); -} - -static DECLFW(M525WriteMIR) { - prg = V; - Sync(); -} - -static DECLFW(M525WriteCHR) { - chr[A & 0x07] = V; - Sync(); -} - -static void M525Power(void) { - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0x8FFF, M525WritePRG); - SetWriteHandler(0x9000, 0x9FFF, M525WriteMIR); - SetWriteHandler(0xB000, 0xBFFF, M525WriteCHR); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper525_Init(CartInfo *info) { - info->Power = M525Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper526.c b/src/mappers/mapper526.c deleted file mode 100644 index a15e8b0de..000000000 --- a/src/mappers/mapper526.c +++ /dev/null @@ -1,123 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 526 is used for a bootleg version of Namco's 三国志: 中原の覇者 (Sangokushi: Chūgen no Hasha). - * Its UNIF board name is UNL-BJ-56. - * Mirroring seems to be hard-wired (to vertical). - * https://wiki.nesdev.com/w/index.php/NES_2.0_Mapper_526 - */ - -#include "mapinc.h" - -static uint8 prg[4], chr[8]; -static uint32 IRQCount; - -static SFORMAT StateRegs[] = { - { prg, 4, "PREG" }, - { chr, 8, "CREG" }, - { &IRQCount, 4, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, prg[3]); - - setchr1(0x0000, chr[0]); - setchr1(0x0400, chr[1]); - setchr1(0x0800, chr[2]); - setchr1(0x0C00, chr[3]); - setchr1(0x1000, chr[4]); - setchr1(0x1400, chr[5]); - setchr1(0x1800, chr[6]); - setchr1(0x1C00, chr[7]); - - setmirror(MI_V); -} - -static DECLFW(M526Write) { - /* FCEU_printf("Wr: A:%04x V:%02x\n", A, V); */ - switch (A & 0x0F) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - chr[A & 0x07] = V; - Sync(); - break; - case 0x08: case 0x09: case 0x0A: case 0x0B: - prg[A & 0x03] = V; - Sync(); - break; - case 0x0D: - case 0x0F: - /* One of these two acknowledges a pending IRQ, and the other - * resets to IRQ counter to zero. Because they are always written - * to one after the other, it's not clear which one does which. */ - X6502_IRQEnd(FCEU_IQEXT); - IRQCount = 0; - break; - } -} - -static void M526IRQHook(int a) { - IRQCount += a; - if (IRQCount & 0x1000) { - X6502_IRQBegin(FCEU_IQEXT); - } -} - -static void M526Close(void) { -} - -static void M526Power(void) { - prg[0] = ~3; - prg[1] = ~2; - prg[2] = ~1; - prg[3] = ~0; - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0x8000, 0x800F, M526Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper526_Init(CartInfo *info) { - info->Power = M526Power; - info->Close = M526Close; - MapIRQHook = M526IRQHook; - GameStateRestore = StateRestore; - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper527.c b/src/mappers/mapper527.c deleted file mode 100644 index 46b79012d..000000000 --- a/src/mappers/mapper527.c +++ /dev/null @@ -1,40 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 527 is used for a bootleg version of - * Taito's 不動明王伝 (Fudō Myōō Den). - * Its UNIF board name is UNL-AX-40G. The original INES Mapper 207 is - * replaced with a VRC2 clone (A0/A1, i.e. VRC2b) while retaining - * Mapper 207's extended mirroring. - */ - -#include "mapinc.h" -#include "vrc24.h" - -static void M527CW(uint16 A, uint16 V) { - setchr1(A, V); - setmirrorw((vrc24.chr[0] >> 7) & 1, (vrc24.chr[0] >> 7) & 1, (vrc24.chr[1] >> 7) & 1, (vrc24.chr[1] >> 7) & 1); -} - -void Mapper527_Init(CartInfo *info) { - VRC24_Init(info, VRC2, 0x01, 0x02, 0, 1); - VRC24_cwrap = M527CW; -} diff --git a/src/mappers/mapper528.c b/src/mappers/mapper528.c deleted file mode 100644 index 083f7c785..000000000 --- a/src/mappers/mapper528.c +++ /dev/null @@ -1,98 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 528 - * UNIF BMC-831128C - */ - -#include "mapinc.h" -#include "fme7.h" -#include "vrcirq.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = { - { ®, 1, "REGS" }, - { 0 } -}; - -static void M528CW(uint16 A, uint16 V) { - uint16 mask = 0xFF; - uint16 base = reg << 4; - - setchr1(A, (base | (V & mask))); -} - -static void M528PW(uint16 A, uint16 V) { - uint16 base = reg; - uint16 mask = base | 0x0F; - - setprg8(A, base + (V & mask)); -} - -static void M528SyncWRAM(void) { - uint16 base = reg; - uint16 mask = base | 0x0F; - - if (fme7.prg[0] == 1) { - setprg8r(0x10, 0x6000, 0); - } else { - setprg8(0x6000, (base + (fme7.prg[0] & mask))); - } -} - -static DECLFW(M528Write) { - switch (A & 0x0F) { - case 0x0B: break; - case 0x0D: VRCIRQ_Control(V); break; - case 0x0E: VRCIRQ_Acknowledge(); break; - case 0x0F: VRCIRQ_Latch(V); break; - default: - FME7_WriteIndex(0x8000, A & 0x0F); - FME7_WriteReg(0xA000, V); - break; - } - reg = (A & 0x4000) >> 10; - FME7_FixPRG(); - FME7_FixCHR(); - FME7_FixWRAM(); -} - -static void M528Power(void) { - reg = 0; - FME7_Power(); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0xA000, 0xAFFF, M528Write); - SetWriteHandler(0xC000, 0xCFFF, M528Write); -} - -void Mapper528_Init(CartInfo *info) { - FME7_Init(info, TRUE, info->battery); - FME7_FixWRAM = M528SyncWRAM; - FME7_pwrap = M528PW; - FME7_cwrap = M528CW; - info->Power = M528Power; - AddExState(StateRegs, ~0, 0, NULL); - - VRCIRQ_Init(TRUE); - MapIRQHook = VRCIRQ_CPUHook; - AddExState(&VRCIRQ_StateRegs, ~0, 0, 0); -} diff --git a/src/mappers/mapper529.c b/src/mappers/mapper529.c deleted file mode 100644 index 5647f3941..000000000 --- a/src/mappers/mapper529.c +++ /dev/null @@ -1,72 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 529 - YY0807/J-2148/T-230 - * UNIF UNL-T-230 - */ - -#include "mapinc.h" -#include "vrc24.h" -#include "eeprom_93Cx6.h" - -static uint8 haveEEPROM; -static uint8 eeprom_data[256]; - -static void M529PW(uint16 A, uint16 V) { - setprg16(0x8000, vrc24.prg[1]); - setprg16(0xC000, ~0); -} - -static DECLFR(M529EEPROMRead) { - if (haveEEPROM) { - return eeprom_93Cx6_read() ? 0x01 : 0x00; - } - return 0x01; -} - -static DECLFW(M529Write) { - if (A & 0x800) { - if (haveEEPROM) { - eeprom_93Cx6_write(!!(A & 0x04), !!(A & 0x02), !!(A & 0x01)); - } - } else { - VRC24_Write(A, V); - } -} - -static void M529Power(void) { - VRC24_Power(); - SetReadHandler(0x5000, 0x5FFF, M529EEPROMRead); - SetWriteHandler(0x8000, 0xFFFF, M529Write); -} - -void Mapper529_Init(CartInfo *info) { - haveEEPROM = (info->PRGRamSaveSize & 0x100) != 0; - VRC24_Init(info, VRC4, 0x04, 0x08, !haveEEPROM, 1); - info->Power = M529Power; - VRC24_pwrap = M529PW; - if (haveEEPROM) { - eeprom_93Cx6_init(eeprom_data, 256, 16); - info->battery = 1; - info->SaveGame[0] = eeprom_data; - info->SaveGameLen[0] = 256; - } -} diff --git a/src/mappers/mapper530.c b/src/mappers/mapper530.c deleted file mode 100644 index ef7b24915..000000000 --- a/src/mappers/mapper530.c +++ /dev/null @@ -1,55 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 530 - UNL-AX5705 - * Super Bros. Pocker Mali (VRC4 mapper) - */ - -#include "mapinc.h" -#include "vrc24.h" - -static DECLFW(UNLAX5705Write) { - A |= (A & 0x0008) ? 0x1000 : 0x0000; - switch (A & 0xF000) { - case 0x8000: - case 0xA000: - V = ((V & 0x02) << 2) | ((V & 0x08) >> 2) | (V & 0x05); - break; - case 0xB000: - case 0xC000: - case 0xD000: - case 0xE000: - if (A & 0x0001) { - V = ((V & 0x04) >> 1) | ((V & 0x02) << 1) | (V & 0x09); - } - break; - } - VRC24_Write(A, V); -} - -static void M530Power(void) { - VRC24_Power(); - SetWriteHandler(0x8000, 0xFFFF, UNLAX5705Write); -} - -void Mapper530_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x01, 0x02, 0, 1); - info->Power = M530Power; -} diff --git a/src/mappers/mapper533.c b/src/mappers/mapper533.c deleted file mode 100644 index 14e478fc6..000000000 --- a/src/mappers/mapper533.c +++ /dev/null @@ -1,48 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023 - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 533 is used for the Sachen 3014 board, used for the game - * 動動腦 II: 國中英文(一) (Dòngdòngnǎo II: Guózhōng Yīngwén (I), - * also known as Middle School English II, SA-003). - * It's a CNROM-like board with the added ability to read back - * the latch content for protection purposes. - */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - setprg32(0x8000, 0); - setchr8((latch.data >> 4) & 0x01); -} - -static DECLFR(M533Read) { - switch (A & 0xF000) { - case 0xE000: - return ((PRGptr[0][0x6000 | (A & 0xFFFF)] & 0xF0) | (latch.data >> 4)); - default: - break; - } - return CartBROB(A); -} - -void Mapper533_Init(CartInfo *info) { - Latch_Init(info, Sync, M533Read, FALSE, TRUE); -} diff --git a/src/mappers/mapper535.c b/src/mappers/mapper535.c deleted file mode 100644 index 3d31f637e..000000000 --- a/src/mappers/mapper535.c +++ /dev/null @@ -1,99 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * NES 2.0 Mapper 535 - UNL-M535 - * FDS Conversion - Nazo no Murasamejō - * - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg, IRQa; -static int32 IRQCount; - -static SFORMAT StateRegs[] = -{ - { ®, 1, "REG" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 4, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - setchr8(0); - setprg8(0x6000, reg); - setprg32(0x8000, 0x03); - setprg8r(0x10, 0xB800, 0); -} - -static DECLFW(M535RamWrite) { - WRAM[(A - 0xB800) & 0x1FFF] = V; -} - -static DECLFW(M535Write) { - reg = V; - Sync(); -} - -static DECLFW(M535IRQaWrite) { - IRQa = V & 0x02; - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); -} - -static void M535IRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount > 7560) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -static void M535Power(void) { - FDSSound_Power(); - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0xB800, 0xD7FF, M535RamWrite); - SetWriteHandler(0xE000, 0xEFFF, M535IRQaWrite); - SetWriteHandler(0xF000, 0xFFFF, M535Write); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M535Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper535_Init(CartInfo *info) { - info->Power = M535Power; - info->Close = M535Close; - MapIRQHook = M535IRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper538.c b/src/mappers/mapper538.c deleted file mode 100644 index de337cf2f..000000000 --- a/src/mappers/mapper538.c +++ /dev/null @@ -1,80 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 538 denotes the 60-1064-16L PCB, used for a - * bootleg cartridge conversion named Super Soccer Champion - * of the Konami FDS game Exciting Soccer. - */ - -#include "mapinc.h" -#include "latch.h" -#include "fdssound.h" - -/* this code emulates rom dump with wrong bank order */ -static uint8 M538Banks[16] = { - 0, 1, 2, 1, 3, 1, 4, 1, - 5, 5, 1, 1, 6, 6, 7, 7 -}; - -static void Sync_alt(void) { - setprg8(0x6000, (latch.data >> 1) | 8); - setprg8(0x8000, M538Banks[latch.data & 0x0F]); - setprg8(0xA000, 14); - setprg8(0xC000, 7); - setprg8(0xE000, 15); - setchr8(0); - setmirror(1); -} - -static void Sync(void) { - setprg8(0x6000, latch.data | 1); - setprg8(0x8000, (latch.data & 1) && (~latch.data & 8) ? 10 : (latch.data & ~1)); - setprg8(0xA000, 13); - setprg8(0xC000, 14); - setprg8(0xE000, 15); - setchr8(0); - setmirror(MI_V); -} - -static DECLFW(M538Write) { - switch (A & 0xF000) { - case 0xC000: - case 0xD000: - latch.data = V; - Sync(); - break; - } -} - -static void M538Power(void) { - FDSSound_Power(); - Latch_RegReset(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M538Write); -} - -void Mapper538_Init(CartInfo *info) { - if (info->CRC32 == 0xA8C6D77D) { - Latch_Init(info, Sync_alt, NULL, 0, 0); - } - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M538Power; -} diff --git a/src/mappers/mapper539.c b/src/mappers/mapper539.c deleted file mode 100644 index 5a31b3372..000000000 --- a/src/mappers/mapper539.c +++ /dev/null @@ -1,115 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* FDS Conversion - Kid Icarus (パルテナの鏡) (Parthena) */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 prg; -static uint8 mirr; - -static SFORMAT StateRegs[] = { - { &prg, 1, "PREG" }, - { &mirr, 1, "MIRR" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x6000, 0x0D); - setprg8(0x8000, 0x0C); - setprg8(0xA000, prg & 0x0F); - setprg8(0xC000, 0x0E); - setprg8(0xE000, 0x0F); - setchr8(0); - setmirror(((mirr & 8) >> 3) ^ 1); -} - -static DECLFR(M539ReadWRAM) { - A = (((A) & 0x1FFF) | (((A) < 0xC000) ? 0x1000 : 0x0000) | (((A) < 0x8000) ? 0x800 : 0x000)); - return WRAM[A]; -} - -static DECLFW(M539WriteWRAM) { - A = (((A) & 0x1FFF) | (((A) < 0xC000) ? 0x1000 : 0x0000) | (((A) < 0x8000) ? 0x800 : 0x000)); - WRAM[A] = V; -} - -static DECLFW(M539WritePRG) { - prg = V; - Sync(); -} - -static DECLFW(M539WriteMirroring) { - if ((A & 0x25) == 0x25) { - mirr = V; - Sync(); - } -} - -static void M539Power(void) { - FDSSound_Power(); - prg = 0; - mirr = 0; - Sync(); - - SetReadHandler(0x6000, 0xFFFF, CartBR); - - SetWriteHandler(0xA000, 0xAFFF, M539WritePRG); - SetWriteHandler(0xF000, 0xFFFF, M539WriteMirroring); - - /* Certain ranges in the CPU address space are overlaid with portions of 8 KiB of PRG-RAM as follows: - * CPU $6000-$60FF - * CPU $6200-$62FF - * CPU $6400-$65FF - * CPU $8200-$82FF - * CPU $C000-$D1FF - * CPU $DF00-$DFFF - */ - - SetReadHandler(0x6000, 0x60FF, M539ReadWRAM); - SetReadHandler(0x6200, 0x62FF, M539ReadWRAM); - SetReadHandler(0x6400, 0x65FF, M539ReadWRAM); - SetReadHandler(0x8200, 0x82FF, M539ReadWRAM); - SetReadHandler(0xC000, 0xD1FF, M539ReadWRAM); - SetReadHandler(0xDF00, 0xDFFF, M539ReadWRAM); - - SetWriteHandler(0x6000, 0x60FF, M539WriteWRAM); - SetWriteHandler(0x6200, 0x62FF, M539WriteWRAM); - SetWriteHandler(0x6400, 0x65FF, M539WriteWRAM); - SetWriteHandler(0x8200, 0x82FF, M539WriteWRAM); - SetWriteHandler(0xC000, 0xD1FF, M539WriteWRAM); - SetWriteHandler(0xDF00, 0xDFFF, M539WriteWRAM); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper539_Init(CartInfo *info) { - info->Power = M539Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper541.c b/src/mappers/mapper541.c deleted file mode 100644 index 38193fe77..000000000 --- a/src/mappers/mapper541.c +++ /dev/null @@ -1,54 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* LittleCom 160-in-1 multicart */ - -#include "mapinc.h" -#include "latch.h" - -static void Sync(void) { - if (latch.addr & 2) { /* NROM-128 */ - setprg16(0x8000, latch.addr >> 2); - setprg16(0xC000, latch.addr >> 2); - } else { /* NROM=256 */ - setprg32(0x8000, latch.addr >> 3); - } - setchr8(0); - setmirror(latch.addr & 0x01); -} - -static DECLFW(M541Write) { - if (A >= 0xC000) { - latch.addr = A; - Sync(); - } -} - -static void M541Power(void) { - Latch_Power(); - SetWriteHandler(0x8000, 0xFFFF, M541Write); -} - -void Mapper541_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, FALSE); - info->Power = M541Power; - info->Reset = Latch_RegReset; -} diff --git a/src/mappers/mapper543.c b/src/mappers/mapper543.c deleted file mode 100644 index b3b9562e2..000000000 --- a/src/mappers/mapper543.c +++ /dev/null @@ -1,90 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 543 - 1996 無敵智カ卡 5-in-1 (CH-501) */ -/* NOTE: needs RAM to be initialized to all 0x00 */ - -#include "mapinc.h" -#include "mmc1.h" - -static uint8 reg; -static uint8 bits; -static uint8 shift; - -static SFORMAT StateRegs[] = { - { &bits, 1, "BITS" }, - { &shift, 1, "SHFT" }, - { ®, 1, "REG0" }, - { 0 } -}; - -static void M543PW(uint16 A, uint16 V) { - setprg16(A, (reg << 4) | (V & 0x0F)); -} - -static void M543CW(uint16 A, uint16 V) { - setchr4(A, (V & 0x07)); -} - -static void M543WW(void) { - uint32 wramBank; - - if (reg & 0x02) { - wramBank = 0x04 | ((reg >> 1) & 0x02) | (reg & 0x01) ; - } else { - wramBank = ((reg << 1) & 0x02) | ((MMC1_GetCHRBank(0) >> 3) & 0x01); - } - setprg8r(0x10, 0x6000, wramBank); -} - -static DECLFW(M543Write) { - bits |= ((V >> 3) & 0x01) << shift++; - if (shift == 4) { - reg = bits; - bits = shift = 0; - MMC1_FixPRG(); - MMC1_FixCHR(); - } -} - -static void M543Reset(void) { - bits = 0; - shift = 0; - reg = 0; - MMC1_Reset(); -} - -static void M543Power(void) { - bits = 0; - shift = 0; - reg = 0; - MMC1_Power(); - SetWriteHandler(0x5000, 0x5FFF, M543Write); -} - -void Mapper543_Init(CartInfo *info) { - MMC1_Init(info, 64, info->battery ? 64 : 0); - info->Power = M543Power; - info->Reset = M543Reset; - MMC1_cwrap = M543CW; - MMC1_pwrap = M543PW; - MMC1_wwrap = M543WW; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper544.c b/src/mappers/mapper544.c deleted file mode 100644 index 5e1c68651..000000000 --- a/src/mappers/mapper544.c +++ /dev/null @@ -1,119 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 544 - Waixing FS306 */ -#include "mapinc.h" -#include "vrc24.h" - -static uint8 nt[4]; -static uint8 cpuC; - -static uint8 chrRamMask; -static uint8 chrRamCompare; - -static writefunc writePPU; -extern uint32 RefreshAddr; - -static SFORMAT StateRegs[] = { - { nt, 4, "NTBL" }, - { &cpuC, 1, "CPUC" }, - { &chrRamMask, 1, "CHRM" }, - { &chrRamCompare, 1, "CHRB" }, - { 0 }, -}; - -static void M544PW(uint16 A, uint16 V) { - V &= 0x1F; - if (A == 0xC000) { - V = cpuC; - } - setprg8(A, V); -} - -static void M544CW(uint16 A, uint16 V) { - if ((V & chrRamMask) == chrRamCompare) { - setchr1r(0x10, A, V); - } else { - setchr1(A, V); - } -} - -static void M544WriteExtra(uint16 A, uint8 V) { - if (A & 0x04) { - nt[A & 0x03] = V & 0x01; - setmirrorw(nt[0], nt[1], nt[2], nt[3]); - } else { - cpuC = V; - VRC24_FixPRG(); - } -} - -static const uint8 compareMasks[8] = { - 0x28, 0x00, 0x4C, 0x64, 0x46, 0x7C, 0x04, 0xFF -}; - -static DECLFW(M544PPUWrite) { - if (RefreshAddr < 0x2000) { - uint8 reg = RefreshAddr >> 10; - uint8 chrBank = vrc24.chr[reg]; - if (chrBank & 0x80) { - if (chrBank & 0x10) { - chrRamMask = 0x00; - chrRamCompare = 0xFF; - } else { - chrRamMask = (chrBank & 0x40) ? 0xFE : 0xFC; - chrRamCompare = compareMasks[((chrBank >> 1) & 0x01) | ((chrBank >> 2) & 0x02) | ((chrBank >> 4) & 0x04)]; - } - VRC24_FixCHR(); - } - } - writePPU(A, V); -} - -static void M544Power(void) { - chrRamMask = 0xFC; - chrRamCompare = 0x28; - nt[0] = 0; - nt[1] = 0; - nt[2] = 1; - nt[3] = 1; - cpuC = ~1; - VRC24_Power(); - writePPU = GetWriteHandler(0x2007); - SetWriteHandler(0x2007, 0x2007, M544PPUWrite); -} - -static void M544Close(void) { -} - -void Mapper544_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x400, 0x800, 1, 1); - info->Power = M544Power; - info->Close = M544Close; - VRC24_pwrap = M544PW; - VRC24_cwrap = M544CW; - VRC24_miscWrite = M544WriteExtra; - AddExState(StateRegs, ~0, 0, NULL); - - CHRRAMSIZE = 2048; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper547.c b/src/mappers/mapper547.c deleted file mode 100644 index fc15dc0b6..000000000 --- a/src/mappers/mapper547.c +++ /dev/null @@ -1,220 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2005-2019 CaH4e3 (FCEUX) - * Copyright (C) 2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * VRC-V (CAI Shogakko no Sansu) - * - */ - -#include "mapinc.h" - -static uint8 reg[16]; -static uint8 IRQa; -static uint8 IRQr; -static uint32 IRQLatch; -static uint32 IRQCount; - -static SFORMAT StateRegs[] = { - { QTAINTRAM, 0x800, "IRAM" }, - { reg, 6, "REGS" }, - { &IRQCount, 4, "IRQC" }, - { &IRQLatch, 4, "IRQL" }, - { &IRQa, 1, "IRQA" }, - { &IRQr, 1, "IRQR" }, - { &qtaintramreg, 1, "IREG" }, - { 0 } -}; - -static void SyncWRAM(void) { -/* -D~7654 3210 - --------- - .... C..B - | +- PRG A12 - +---- Chip select - 0: External cartridge's 8 KiB (battery-backed) - 1: Internal 8 KiB (not battery-backed) */ - setprg4r(0x10, 0x6000, ((reg[0] & 0x08) >> 2) | (reg[0] & 0x01)); - setprg4r(0x10, 0x7000, ((reg[1] & 0x08) >> 2) | (reg[1] & 0x01)); -} - -static void SyncPRG(void) { -/* -D~7654 3210 - --------- - .CBB BBBB - |++-++++- PRG A13-A18 - +-------- Chip select - 0: Internal PRG-ROM (128 KiB) - 1: External PRG-ROM (512 KiB) */ - setprg8(0x8000, (reg[2] & 0x40) ? (0x10 + (reg[2] & 0x3F)) : (reg[2] & 0x0F)); - setprg8(0xA000, (reg[3] & 0x40) ? (0x10 + (reg[3] & 0x3F)) : (reg[3] & 0x0F)); - setprg8(0xC000, (reg[4] & 0x40) ? (0x10 + (reg[4] & 0x3F)) : (reg[4] & 0x0F)); - setprg8(0xE000, 0x10 + 0x3F); -} - -static void SyncCHR(void) { - setchr4r(0x10, 0x0000, reg[5] & 0x01); - setchr4r(0x10, 0x1000, 0x01); -} - -static void SyncMir(void) { - setmirror(((reg[10] >> 1) & 1) ^ 1); -} - -static void Sync(void) { - SyncPRG(); - SyncWRAM(); - SyncCHR(); - SyncMir(); -} - -static DECLFW(M547Write) { - int index = (A & 0x0F00) >> 8; - - reg[index] = V; - switch (A) { - case 0xD000: - case 0xD100: - SyncWRAM(); - break; - case 0xD200: - case 0xD300: - case 0xD400: - SyncPRG(); - break; - case 0xD500: - SyncCHR(); - break; - case 0xD600: - IRQLatch &= 0xFF00; - IRQLatch |= V; - break; - case 0xD700: - IRQLatch &= 0x00FF; - IRQLatch |= V << 8; - break; - case 0xD800: - IRQa = IRQr; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xD900: - IRQr = V & 0x01; - IRQa = V & 0x02; - if (IRQa) { - IRQCount = IRQLatch; - } - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xDA00: - SyncMir(); - /* register shadow to share it with ppu */ - qtaintramreg = reg[10] & 0x03; - break; - } -} - -static const uint8 pageTable[0x24] = { - /* JIS X 0208 rows $20-$4F. $20 is not a valid row number. */ - 0x0, 0x0, 0x2, 0x2, 0x1, 0x1, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, - /* JIS X 0208 rows $50-$7F. $7F is not a valid row number. */ - 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0xD, 0xD -}; - -static DECLFR(M547Read) { - uint8 row = reg[13] - 0x20; - uint8 col = reg[12] - 0x20; - - if ((row < 0x60) && (col < 0x60)) { - /* "row" and "col" are the first and second 7-bit JIS X 0208 code byte, respectively, each minus the $21 offset. */ - uint16 code = (col % 32) + /* First, go through 32 columns of a column-third. */ - (row % 16) * 32 + /* Then, through 16 rows of a row-third. */ - (col / 32) * 32 * 16 + /* Then, through three column-thirds. */ - (row / 16) * 32 * 16 * 3; /* Finally, through three row-thirds. */ - uint16 glyph = (code & 0xFF) | (pageTable[code >> 8] << 8); - uint32 tile = glyph * 4; /* four tiles per glyph */ - - if (A == 0xDC00) { - /* tile number */ - return ((tile & 0xFF) | (reg[11] & 0x03)); - } else { - /* bank byte */ - return (0x40 | ((reg[11] & 0x04) << 5) | (tile >> 8)); - } - } - return 0; -} - -static void M547CPUIRQHook(int a) { - if (IRQa) { - IRQCount += a; - if (IRQCount & 0x10000) { - X6502_IRQBegin(FCEU_IQEXT); - IRQCount = IRQLatch; - } - } -} - -static void M547Power(void) { - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetWriteHandler(0xD000, 0xDFFF, M547Write); - SetReadHandler(0xDC00, 0xDC00, M547Read); - SetReadHandler(0xDD00, 0xDD00, M547Read); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M547Close(void) { - QTAIHack = FALSE; -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper547_Init(CartInfo *info) { - QTAIHack = TRUE; - - info->Power = M547Power; - info->Close = M547Close; - MapIRQHook = M547CPUIRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, 0); - - if (iNESCart.iNES2) { - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - CHRRAMSIZE = info->CHRRamSize + info->CHRRamSaveSize; - } - - if (!CHRRAMSIZE) CHRRAMSIZE = 8192; - if (!WRAMSIZE) WRAMSIZE = 8192 + 8192; /* 8K external + 8K internal RAM */ - - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); - - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - info->battery = TRUE; - iNESCart.SaveGame[0] = WRAM; - iNESCart.SaveGameLen[0] = 8192; /* only bank 0, the external cartridge RAM is battery-backed */ -} diff --git a/src/mappers/mapper548.c b/src/mappers/mapper548.c deleted file mode 100644 index 6b9edb8fc..000000000 --- a/src/mappers/mapper548.c +++ /dev/null @@ -1,107 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * FDS Conversion - Almana no Kiseki - (Co Tung Co.)'s CTC-15 circuit board - * - */ - -#include "mapinc.h" -#include "fdssound.h" - -static uint8 reg, latch, IRQa; -static int32 IRQCount; - -static SFORMAT StateRegs[] = { - { ®, 1, "REG" }, - { &latch, 1, "LATC" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 4, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - setchr8(0); - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, reg); - setprg16(0xC000, 0x03); -} - -static DECLFW(M548Write4800) { - latch = ((A >> 3) & 0x04) | ((A >> 2) & 0x03); - IRQa = (A & 0x04) != 0x04; - if (!IRQa) { - IRQCount = 0; - X6502_IRQEnd(FCEU_IQEXT); - } -} - -static DECLFW(M548Write5000) { - reg = latch ^ 0x05; - Sync(); -} - - -static void M548IRQ(int a) { - int count = a; - if (IRQa) { - while (count > 0) { - if (IRQCount == 23680) { - X6502_IRQBegin(FCEU_IQEXT); - } else if (IRQCount == 24320) { - X6502_IRQEnd(FCEU_IQEXT); - } - count--; - IRQCount++; - } - } -} - -static void M548Power(void) { - latch = 7; - reg = latch ^ 0x05; - IRQa = 0; - IRQCount = 0; - FDSSound_Power(); - Sync(); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x4800, 0x4FFF, M548Write4800); - SetWriteHandler(0x5000, 0x57FF, M548Write5000); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void M548Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper548_Init(CartInfo *info) { - info->Power = M548Power; - info->Close = M548Close; - MapIRQHook = M548IRQ; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/mappers/mapper549.c b/src/mappers/mapper549.c deleted file mode 100644 index 1e7881574..000000000 --- a/src/mappers/mapper549.c +++ /dev/null @@ -1,52 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -/* NES 2.0 Mapper 549 - * Used for the Kaiser port of Meikyuu Jiin Dababa from the Famicom Disk System. - */ - -#include "mapinc.h" -#include "latch.h" -#include "fdssound.h" - -static void Sync(void) { - setprg8(0x6000, ((latch.addr >> 3) & 0x04) | (latch.addr >> 2)); - setprg32(0x8000, 0x02); - setchr8(0); -} - -static void M549Power(void) { - Latch_Power(); - FDSSound_Power(); - SetReadHandler(0x6000, 0x7FFF, CartBR); -} - -static void M549Reset(void) { - Sync(); - FDSSoundRegReset(); - FDSSound_SC(); -} - -void Mapper549_Init(CartInfo *info) { - Latch_Init(info, Sync, NULL, FALSE, TRUE); - info->Power = M549Power; - info->Reset = M549Reset; -} diff --git a/src/mappers/mapper550.c b/src/mappers/mapper550.c deleted file mode 100644 index 76336f018..000000000 --- a/src/mappers/mapper550.c +++ /dev/null @@ -1,89 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 550 - 7-in-1 1993 Chess Series (JY-015) */ - -#include "mapinc.h" -#include "mmc1.h" - -static uint8 latch; -static uint8 reg; - -static SFORMAT StateRegs[] = { - { &latch, 1, "LATC" }, - { ®, 1, "REGS" }, - { 0 } -}; - -static void M550PW(uint16 A, uint16 V) { - if ((reg & 0x06) == 0x06) { - setprg16(A, (reg << 2) | (V & 0x07)); - } else { - setprg32(0x8000, (reg << 1) | ((latch >> 4) & 0x01)); - } -} - -static void M550CW(uint16 A, uint16 V) { - if ((reg & 0x06) == 0x06) { - setchr4(A, ((reg << 2) & 0x18) | (V & 0x07)); - } else { - setchr8(((reg << 1) & 0x0C) | (latch & 0x03)); - } -} - -static DECLFW(M550Write7) { - if (!(reg & 0x08)) { - reg = A & 0x0F; - MMC1_FixPRG(); - MMC1_FixCHR(); - } -} - -static DECLFW(M550Write8) { - latch = V; - if ((reg & 0x06) == 0x06) { - MMC1_Write(A, V); - } - MMC1_FixPRG(); - MMC1_FixCHR(); -} - -static void M550Reset(void) { - latch = 0; - reg = 0; - MMC1_Reset(); -} - -static void M550Power(void) { - latch = 0; - reg = 0; - MMC1_Power(); - SetWriteHandler(0x7000, 0x7FFF, M550Write7); - SetWriteHandler(0x8000, 0xFFFF, M550Write8); -} - -void Mapper550_Init(CartInfo *info) { - MMC1_Init(info, 8, 0); - info->Power = M550Power; - info->Reset = M550Reset; - MMC1_cwrap = M550CW; - MMC1_pwrap = M550PW; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper553.c b/src/mappers/mapper553.c deleted file mode 100644 index 695524eb2..000000000 --- a/src/mappers/mapper553.c +++ /dev/null @@ -1,38 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static DECLFR(M553Read) { - if (A < 0xC000) { - return 0x3A; - } - return CartBR(A); -} - -static void M553Power(void) { - setprg16(0xC000, 0); - setchr8(0); - SetReadHandler(0x8000, 0xFFFF, M553Read); -} - -void Mapper553_Init(CartInfo *info) { - info->Power = M553Power; -} diff --git a/src/mappers/mapper554.c b/src/mappers/mapper554.c deleted file mode 100644 index adf338d9a..000000000 --- a/src/mappers/mapper554.c +++ /dev/null @@ -1,85 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Mapper 554 - Kaiser KS-7010 - * used for one of several cartridge conversions of the FDS version of - * 悪魔城 Dracula, the Japanese version of Castlevania - */ - -#include "mapinc.h" - -static uint8 reg; - -static SFORMAT StateRegs[] = -{ - { ®, 1, "REG" }, - { 0 } -}; - -static void Sync(void) { - setprg8(0x6000, reg); - setprg8(0x8000, 0x0A); - setprg8(0xA000, 0x0B); - setprg8(0xC000, 0x06); - setprg8(0xE000, 0x07); - setchr8(reg); -} - -static DECLFR(M544Read) { - uint16 adr = A & 0xFFFE; - - switch (A & 0xF000) { - case 0xC000: - if ((adr >= 0xCAB6) && (adr <= 0xCAD7)) { - reg = (adr >> 2) & 0x0F; - Sync(); - } - break; - case 0xE000: - if ((adr == 0xEBE2) || (adr == 0xEE32)) { - reg = (A >> 2) & 0x0F; - Sync(); - } - break; - case 0xF000: - if (adr == 0xFFFC) { - reg = (A >> 2) & 0x0F; - Sync(); - } - break; - } - - return CartBR(A); -} - -static void M554Power(void) { - Sync(); - SetReadHandler(0x6000, 0xFFFF, M544Read); -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper554_Init(CartInfo *info) { - info->Power = M554Power; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper555.c b/src/mappers/mapper555.c deleted file mode 100644 index 24da40c75..000000000 --- a/src/mappers/mapper555.c +++ /dev/null @@ -1,133 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2020 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* NES 2.0 Mapper 516 - Brilliant Com Cocoma Pack */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg[2]; -static uint8 count_expired; -static uint32 count; -static uint32 count_target = 0x20000000; - -static SFORMAT StateRegs[] = { - { reg, 2, "REGS" }, - { &count, 2, "CNTR" }, - { &count_expired, 2, "CNTE" }, - { 0 } -}; - -static void M555CW(uint16 A, uint16 V) { - uint16 base = (reg[0] << 5) & 0x80; - - if ((reg[0] & 0x06) == 0x02) { - if (V & 0x40) { - setchr1r(0x10, A, base | (V & 0x07)); - } else { - setchr1(A, base | (V & 0xFF)); - } - } else { - setchr1(A, base | (V & 0x7F)); - } -} - -static void M555PW(uint16 A, uint16 V) { - uint16 mask = ((reg[0] << 3) & 0x18) | 0x07; - uint16 base = ((reg[0] << 3) & 0x20); - - setprg8(A, base | (V & mask)); -} - -static DECLFR(M555Read5) { - if (A & 0x800) { - return (0x5C | (count_expired ? 0x80 : 0)); - } - return WRAM[0x2000 | (A & 0xFFF)]; -} - -static DECLFW(M555Write5) { - if (A & 0x800) { - reg[(A >> 10) & 0x01] = V; - MMC3_FixPRG(); - MMC3_FixCHR(); - } else { - WRAM[0x2000 | (A & 0xFFF)] = V; - } -} - -static void M555Reset(void) { - count_target = 0x20000000 | ((uint32)GameInfo->cspecial << 25); - count = 0; - memset(reg, 0, sizeof(reg)); - MMC3_Reset(); -} - -static void M555Power(void) { - count_target = 0x20000000 | ((uint32)GameInfo->cspecial << 25); - count = 0; - memset(reg, 0, sizeof(reg)); - MMC3_Power(); - - SetReadHandler(0x5000, 0x5FFF, M555Read5); - SetWriteHandler(0x5000, 0x5FFF, M555Write5); - - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); -} - -static void M555CPUIRQHook(int a) { - while (a--) { - if (!(reg[0] & 0x08)) { - count = 0; - count_expired = false; - } else { - if (++count == count_target) { - count_expired = TRUE; - } - if ((count % 1789773) == 0) { - uint32 seconds = (count_target - count) / 1789773; - FCEU_DispMessage(RETRO_LOG_INFO, 1000, "Time left: %02i:%02i\n", seconds / 60, seconds % 60); - } - } - } -} - -void Mapper555_Init(CartInfo *info) { - MMC3_Init(info, 0, 0); - MMC3_cwrap = M555CW; - MMC3_pwrap = M555PW; - info->Power = M555Power; - info->Reset = M555Reset; - MapIRQHook = M555CPUIRQHook; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = 16 * 1024; - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - - CHRRAMSIZE = 8 * 1024; - CHRRAM = (uint8 *)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, TRUE); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/mapper556.c b/src/mappers/mapper556.c deleted file mode 100644 index 6e40e9153..000000000 --- a/src/mappers/mapper556.c +++ /dev/null @@ -1,180 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 556 - * Used for the for the 超强小新2+瑪莉家族 7-in-1 (JY-215) multicart. - */ - -#include "mapinc.h" -#include "mmc3.h" -#include "vrc24.h" - -static uint8 cmd; -static uint8 reg[4]; - -static SFORMAT StateRegs[] = { - { reg, 5, "REGS" }, - { &cmd, 1, "CMD0" }, - { 0 }, -}; - -static uint32 M556PRGMask(void) { - return (~reg[3] & 0x3F); -} - -static uint32 M556PRGBase(void) { - return (((reg[3] & 0x40) << 2) | reg[1]); -} - -static uint32 M556CHRMask(void) { - return (0xFF >> (~reg[2] & 0x0F)); -} - -static uint32 M556CHRBase(void) { - return (((reg[3] & 0x40) << 6) | ((reg[2] & 0xF0) << 4) | reg[0]); -} - -static void M556MMC3PW(uint16 A, uint16 V) { - uint32 mask = M556PRGMask(); - uint32 base = M556PRGBase(); - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M556MMC3CW(uint16 A, uint16 V) { - uint32 mask = M556CHRMask(); - uint32 base = M556CHRBase(); - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M556VRC4PW(uint16 A, uint16 V) { - uint32 mask = M556PRGMask(); - uint32 base = M556PRGBase(); - - setprg8(A, (base & ~mask) | (V & mask)); -} - -static void M556VRC4CW(uint16 A, uint16 V) { - uint32 mask = M556CHRMask(); - uint32 base = M556CHRBase(); - - setchr1(A, (base & ~mask) | (V & mask)); -} - -static void M556Sync(void) { - if (reg[2] & 0x80) { - VRC24_FixPRG(); - VRC24_FixCHR(); - VRC24_FixMIR(); - } else { - MMC3_FixPRG(); - MMC3_FixCHR(); - MMC3_FixMIR(); - } -} - -static DECLFW(M556WriteREG) { - if (!(reg[3] & 0x80)) { - reg[cmd] = V; - cmd = (cmd + 1) & 0x03; - M556Sync(); - } -} - -static DECLFW(M556WriteASIC) { - if (reg[2] & 0x80) { - VRC24_Write(A, V); - } else { - MMC3_Write(A, V); - } -} - -static void M556CPUIRQHook(int a) { - if (reg[2] & 0x80) { - VRC24_IRQCPUHook(a); - } -} - -static void M556HBIRQHook(void) { - if (!(reg[2] & 0x80)) { - MMC3_IRQHBHook(); - } -} - -static void M556Reset(void) { - memset(reg, 0, sizeof(reg)); - reg[2] = 0x0F; - M556Sync(); -} - -static void M556Power(void) { - memset(reg, 0, sizeof(reg)); - reg[2] = 0x0F; - - MMC3_Reset(); - VRC24_Reset(); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x5000, 0x5FFF, M556WriteREG); - SetWriteHandler(0x8000, 0xFFFF, M556WriteASIC); - - if (WRAM) { - setprg8r(0x10, 0x6000, 0); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - } -} - -static void M556Close(void) { -} - -static void StateRestore(int version) { - M556Sync(); -} - -void Mapper556_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x05, 0x0A, 0, TRUE); - VRC24_pwrap = M556VRC4PW; - VRC24_cwrap = M556VRC4CW; - - MMC3_Init(info, 0, 0); - MMC3_pwrap = M556MMC3PW; - MMC3_cwrap = M556MMC3CW; - - info->Reset = M556Reset; - info->Power = M556Power; - info->Close = M556Close; - MapIRQHook = M556CPUIRQHook; - GameHBIRQHook = M556HBIRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = info->PRGRamSize + info->PRGRamSaveSize; - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - } -} diff --git a/src/mappers/mapper557.c b/src/mappers/mapper557.c deleted file mode 100644 index 679c41f42..000000000 --- a/src/mappers/mapper557.c +++ /dev/null @@ -1,43 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 557 is used for Kaiser's cartridge conversion of the Famicom Disk System game Moero TwinBee: Cinnamon-hakase o Sukue!. */ - -#include "mapinc.h" -#include "n118.h" - -static void M557FixPRG(void) { - setprg8r(0x10, 0x6000, 0); - setprg8(0x8000, n118.reg[6] & 0x0F); - setprg8(0xA000, n118.reg[7] & 0x0F); - setprg8(0xC000, ~1); - setprg8(0xE000, ~0); -} - -static void M557FixCHR(void) { - setchr8(0); - setmirror(((n118.reg[5] >> 5) & 0x01) ^ 0x01); -} - -void Mapper557_Init(CartInfo *info) { - N118_Init(info, 8, 0); - N118_FixPRG = M557FixPRG; - N118_FixCHR = M557FixCHR; -} diff --git a/src/mappers/mapper558.c b/src/mappers/mapper558.c deleted file mode 100644 index 7e47d344b..000000000 --- a/src/mappers/mapper558.c +++ /dev/null @@ -1,144 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * Copyright (C) 2005 CaH4e3 - * Copyright (C) 2019 Libretro Team - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Yancheng YC-03-09/Waixing FS??? PCB */ - -#include "mapinc.h" - -#include "eeprom_93Cx6.h" - -static uint8 reg[4]; - -static uint8 haveEEPROM; -static uint8 eeprom_data[512]; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, (reg[1] << 4) | (reg[0] & 0xF) | ((reg[3] & 0x04) ? 0x00 : 0x03)); - setprg8r(0x10, 0x6000, 0); - if (!(reg[0] & 0x80)) { - setchr8(0); - } -} - -static void M558HBIRQHook(void) { - if ((reg[0] & 0x80) && - (scanline < 239)) { /* Actual hardware cannot look at the current scanline number, but instead latches PA09 on - PA13 rises. This does not seem possible with the current PPU emulation however. */ - setchr4(0x0000, (scanline >= 127) ? 1 : 0); - setchr4(0x1000, (scanline >= 127) ? 1 : 0); - } else { - setchr8(0); - } -} - -static DECLFR(readReg) { - if (haveEEPROM) { - return eeprom_93Cx6_read() ? 0x04 : 0x00; - } - return reg[2] & 0x04; -} - -static DECLFW(writeReg) { - switch (A & 0xFF00) { - case 0x5000: - if (!(reg[3] & 0x02)) { - V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); - } - reg[0] = V; - Sync(); - break; - case 0x5100: - if (!(reg[3] & 0x02)) { - V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); - } - reg[1] = V; - Sync(); - break; - case 0x5200: - if ((PRG_ROM_SIZE != (1024 * 1024)) && !(reg[3] & 0x02)) { - V = (V & ~0x03) | ((V >> 1) & 0x01) | ((V << 1) & 0x02); - } - reg[2] = V; - if (haveEEPROM) { - eeprom_93Cx6_write((reg[2] & 0x04), (reg[2] & 0x02), (reg[2] & 0x01)); - } - break; - case 0x5300: - reg[3] = V; - Sync(); - break; - } -} - -static void M558Power(void) { - memset(reg, 0, sizeof(reg)); - Sync(); - SetReadHandler(0x5000, 0x57FF, readReg); - SetWriteHandler(0x5000, 0x57FF, writeReg); - SetReadHandler(0x6000, 0xFFFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); -} - -static void M558Reset(void) { - memset(reg, 0, sizeof(reg)); - Sync(); -} - -static void M558Close(void) { -} - -static void StateRestore(int version) { - Sync(); -} - -void Mapper558_Init(CartInfo *info) { - info->Power = M558Power; - info->Reset = M558Reset; - info->Close = M558Close; - GameHBIRQHook = M558HBIRQHook; - - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = info->PRGRamSize + (info->PRGRamSaveSize & ~0x7FF); - WRAM = (uint8 *)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - - haveEEPROM = !!(info->PRGRamSaveSize & 0x200); - if (haveEEPROM) { - eeprom_93Cx6_init(eeprom_data, 512, 8); - info->battery = 1; - info->SaveGame[0] = eeprom_data; - info->SaveGameLen[0] = 512; - } else if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = (info->PRGRamSaveSize & ~0x7FF); - } -} diff --git a/src/mappers/mapper559.c b/src/mappers/mapper559.c deleted file mode 100644 index 70fa45845..000000000 --- a/src/mappers/mapper559.c +++ /dev/null @@ -1,91 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NES 2.0 Mapper 559 - VRC4 clone - * Subor 0102 - */ - -#include "mapinc.h" -#include "vrc24.h" - -static uint8 nt[4]; -static uint8 cpuC; - -static SFORMAT StateRegs[] = { - { &cpuC, 1, "CPUC" }, - { nt, 4, "NTBL" }, - { 0 }, -}; - -static void M559PW(uint16 A, uint16 V) { - V &= 0x1F; - if (A == 0xC000) { - V = cpuC; - } - setprg8(A, V); -} - -static void M559CW(uint16 A, uint16 V) { - setchr1(A, V & 0x1FF); -} - -static void M559MIRR(void) { - setmirrorw(nt[0], nt[1], nt[2], nt[3]); -} - -static void M559WriteMisc(uint16 A, uint8 V) { - if (A & 0x04) { - nt[A & 0x03] = V & 0x01; - VRC24_FixMIR(); - } else { - cpuC = V; - VRC24_FixPRG(); - } -} - -static DECLFW(M559WriteNibble) { - /* nibblize address */ - if (A & 0x400) { - V >>= 4; - } - VRC24_Write(A, V); -} - -static void M559Power(void) { - nt[0] = 0; - nt[1] = 0; - nt[2] = 1; - nt[3] = 1; - cpuC = ~1; - VRC24_Power(); - setprg8(0xC000, cpuC); - setmirrorw(nt[0], nt[1], nt[2], nt[3]); - SetWriteHandler(0xB000, 0xFFFF, M559WriteNibble); -} - -void Mapper559_Init(CartInfo *info) { - VRC24_Init(info, VRC4, 0x400, 0x800, 1, 1); - info->Power = M559Power; - VRC24_FixMIR = M559MIRR; - VRC24_pwrap = M559PW; - VRC24_cwrap = M559CW; - VRC24_miscWrite = M559WriteMisc; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/mapper561.c b/src/mappers/mapper561.c deleted file mode 100644 index 9c3058623..000000000 --- a/src/mappers/mapper561.c +++ /dev/null @@ -1,293 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 prg[4]; -static uint8 chr; -static uint8 latch; -static uint8 reg1M; -static uint8 reg4M; - -static uint8 IRQa_fds; -static int16 IRQCount_fds; -static int16 IRQCount_sgd; - -static SFORMAT StateRegs[] = { - { ®1M, 1, "REG1" }, - { ®4M, 1, "REG4" }, - { &latch, 1, "LATC" }, - { &chr, 1, "CREG" }, - { prg, 4, "PREG" }, - - { &IRQa_fds, 1, "IRQA" }, - { &IRQCount_fds, 2, "FDSC" }, - - { &IRQCount_sgd, 2, "SGDC" }, - - { 0 }, -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - /* PRG memory can be writable */ - SetupCartPRGMapping(0, PRGptr[0], PRGsize[0], !(reg1M & 0x02)); - if (!(reg4M & 0x01)) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, prg[3]); - } else { - switch (reg1M >> 5) { - case 0: - setprg16(0x8000, latch & 0x07); - setprg16(0xC000, 0x07); - break; - case 1: - setprg16(0x8000, (latch >> 2) & 0x0F); - setprg16(0xC000, 0x07); - break; - case 2: - setprg16(0x8000, latch & 0x0F); - setprg16(0xC000, 0x0F); - break; - case 3: - setprg16(0x8000, 0x0F); - setprg16(0xC000, latch & 0x0F); - break; - case 4: - setprg32(0x8000, (latch >> 4) & 0x03); - break; - case 5: - setprg32(0x8000, 0x03); - break; - case 6: - setprg8(0x8000, latch & 0x0F); - setprg8(0xA000, latch >> 4); - setprg16(0xC000, 0x07); - break; - case 7: - setprg8(0x8000, latch & 0x0E); - setprg8(0xA000, (latch >> 4) | 0x01); - setprg16(0xC000, 0x07); - break; - } - } - - /* CHR RAN can be write-protected */ - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !((reg1M & 0xE0) & 0x80)); - setchr8(chr); - - switch (reg1M & 0x11) { - case 0x00: setmirror(MI_0); break; - case 0x01: setmirror(MI_V); break; - case 0x10: setmirror(MI_1); break; - case 0x11: setmirror(MI_H); break; - } -} - -static DECLFW(M561WriteReg) { - switch (A) { - case 0x4024: - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x4025: - X6502_IRQEnd(FCEU_IQEXT); - IRQa_fds = V; - if (IRQa_fds & 0x42) { - IRQCount_fds = 0; - } - break; - case 0x4100: - X6502_IRQEnd(FCEU_IQEXT); - IRQCount_sgd = (int16)((IRQCount_sgd & 0xFF00) | V); - if (!V) { - IRQCount_sgd = V; - } - break; - case 0x4101: - X6502_IRQEnd(FCEU_IQEXT); - IRQCount_sgd = (int16)((IRQCount_sgd & 0x00FF) | (V << 8)); - break; - case 0x42FC: - case 0x42FD: - case 0x42FE: - case 0x42FF: - reg1M = (V & 0xF0) | (A & 0x03); - Sync(); - break; - case 0x43FC: - case 0x43FD: - case 0x43FE: - case 0x43FF: - reg4M = (V & 0xF0) | (A & 0x03); - chr = V & 0x03; - Sync(); - break; - } -} - -static DECLFW(M561Write) { - if (reg1M & 0x02) { - latch = V; - switch (reg1M >> 5) { - case 0: - case 2: - chr = 0; - break; - case 1: - case 4: - case 5: - chr = latch & 0x03; - break; - case 3: - chr = (latch >> 4) & 0x03; - break; - default: - /* keep chr bank from last mode */ - break; - } - prg[(A >> 13) & 0x03] = V >> 2; - Sync(); - } else { - CartBW(A, V); - } -} - -static void M561Reset(void) { - IRQa_fds = IRQCount_fds = IRQCount_sgd = 0; - Sync(); -} - -static void M561Power(void) { - reg1M = (iNESCart.submapper << 5) | ((iNESCart.mirror == MI_V) ? 0x01 : 0x11) | 0x02; - reg4M = 0x03; - prg[0] = 0x1C; - prg[1] = 0x1D; - prg[2] = 0x1E; - prg[3] = 0x1F; - chr = 0; - - SetWriteHandler(0x4020, 0x4FFF, M561WriteReg); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M561Write); - - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - - Sync(); - - if (MISC_ROM_SIZE && (MISC_ROM_SIZE >= 4)) { - uint16 trainerLoadAddr = 0x7000; - uint16 trainerInitAddr = 0x7003; - uint32 trainerSize = 512; - uint8 *trainerData = MISC_ROM_PTR; - int i; - - if (MISC_ROM_SIZE != 512) { - trainerLoadAddr = (MISC_ROM_PTR[1] << 8) | MISC_ROM_PTR[0]; - trainerInitAddr = (MISC_ROM_PTR[3] << 8) | MISC_ROM_PTR[2]; - trainerSize = MISC_ROM_SIZE - 4; - trainerData = MISC_ROM_PTR + 4; - } - - for (i = 0; i < MISC_ROM_SIZE; i++) { - WRAM[(trainerLoadAddr & 0x1FFF) + i] = trainerData[i]; - } - - if (trainerInitAddr) { - /* JSR init */ - (GetWriteHandler(0x0700))(0x0700, 0x20); - (GetWriteHandler(0x0701))(0x0701, trainerInitAddr & 0xFF); - (GetWriteHandler(0x0702))(0x0702, trainerInitAddr >> 8); - - /* JMP ($FFFC) */ - (GetWriteHandler(0x0703))(0x0703, 0x6C); - (GetWriteHandler(0x0704))(0x0704, 0xFC); - (GetWriteHandler(0x0705))(0x0705, 0xFF); - - X6502_SetNewPC(0x700); - } - } - (GetWriteHandler(0x4017))(0x4017, 0x40); -} - -static void StateRestore(int version) { - Sync(); -} - -static void M561CPUIRQHook(int a) { - IRQCount_fds += 3 * a; - while ((IRQCount_fds >= 448) && (IRQa_fds & 0x80)) { - IRQCount_fds -= 448; - X6502_IRQBegin(FCEU_IQEXT); - } - if (IRQCount_sgd < 0) { - IRQCount_sgd += a; - if (IRQCount_sgd >= 0) { - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - -void Mapper561_Init(CartInfo *info) { - uint32 wramsize = info->PRGRamSize + info->PRGRamSaveSize; - int i, ssize = PRG_ROM_SIZE; - - info->Power = M561Power; - info->Reset = M561Reset; - MapIRQHook = M561CPUIRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = wramsize ? wramsize : 8192; - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - - if ((info->submapper == 3) && (PRG_ROM_SIZE < (256 * 1024))) { - uint8 *tmp = (uint8 *)FCEU_malloc(PRG_ROM_SIZE); - - for (i = 0; i < ssize; i++) { - tmp[i] = PRG_ROM_PTR[i]; - } - ssize = (256 * 1024); - PRG_ROM_PTR = (uint8 *)realloc(PRG_ROM_PTR, ssize); - for (i = 0; i < ssize; i++) { - PRG_ROM_PTR[i] = tmp[i]; - } - FCEU_free(tmp); - SetupCartPRGMapping(0, PRG_ROM_PTR, ssize, FALSE); - } - - if (CHR_ROM_SIZE) { - /* Game Doctor only used CHR RAM, but some .nes files has CHR ROM instead. */ - /* Remap CHR as writable. */ - SetupCartCHRMapping(0, CHR_ROM_PTR, CHR_ROM_SIZE, TRUE); - AddExState(CHR_ROM_PTR, CHR_ROM_SIZE, 0, "CHRM"); - } - - /* PRG memory can be writable, so add to states */ - AddExState(PRG_ROM_PTR, ssize, 0, "PRGM"); -} diff --git a/src/mappers/mapper562.c b/src/mappers/mapper562.c deleted file mode 100644 index 39f3752f4..000000000 --- a/src/mappers/mapper562.c +++ /dev/null @@ -1,590 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static const uint8 tgd4800[2048] = { - 0xf6, 0x60, 0x20, 0xd3, 0xe7, 0xf0, 0x06, 0x20, 0xd3, 0xe7, 0x20, - 0xf5, 0xe7, 0xa2, 0x01, 0xb5, 0xf5, 0xa8, 0x55, 0xf7, 0x35, 0xf5, - 0x95, 0xf5, 0x94, 0xf7, 0xca, 0x10, 0xf2, 0x60, 0xa9, 0x08, 0x08, - 0xa0, 0x00, 0x18, 0x65, 0x00, 0x85, 0x00, 0xa9, 0x00, 0x65, 0x01, - 0x85, 0x01, 0x28, 0xc6, 0x02, 0x60, 0xa2, 0x08, 0xb0, 0x0a, 0xb1, - 0x00, 0x8d, 0x07, 0x20, 0xc8, 0xca, 0xd0, 0xf5, 0x60, 0xad, 0x07, - 0x20, 0x91, 0x00, 0xb0, 0xf4, 0xa5, 0x03, 0xa2, 0x08, 0xb0, 0x07, - 0x8d, 0x07, 0x20, 0xca, 0xd0, 0xf8, 0x60, 0xad, 0x07, 0x20, 0xb0, - 0xf7, 0xa2, 0x08, 0xa5, 0x03, 0x51, 0x00, 0x8d, 0x07, 0x20, 0xc8, - 0xca, 0xd0, 0xf5, 0x60, 0x85, 0x04, 0x86, 0x02, 0x84, 0x03, 0x20, - 0xfc, 0xe3, 0xad, 0x02, 0x20, 0xa5, 0xff, 0x29, 0xfb, 0x85, 0xff, - 0x8d, 0x00, 0x20, 0xa4, 0x03, 0x8c, 0x06, 0x20, 0xa5, 0x04, 0x29, - 0xf0, 0x8d, 0x06, 0x20, 0xa9, 0x00, 0x85, 0x03, 0xa5, 0x04, 0x29, - 0x0f, 0x4a, 0x90, 0x02, 0xc6, 0x03, 0x4a, 0x90, 0x03, 0xae, 0x07, - 0x20, 0xa8, 0xf0, 0x15, 0x88, 0xf0, 0x20, 0x88, 0xf0, 0x29, 0x88, - 0x20, 0x59, 0xe8, 0xa0, 0x00, 0x20, 0x32, 0xe8, 0x20, 0x1e, 0xe8, - 0xd0, 0xf3, 0x60, 0x20, 0x32, 0xe8, 0x20, 0x32, 0xe8, 0xa9, 0x10, - 0x20, 0x20, 0xe8, 0xd0, 0xf3, 0x60, 0x20, 0x32, 0xe8, 0x20, 0x47, - 0xe8, 0x20, 0x1e, 0xe8, 0xd0, 0xf5, 0x60, 0x20, 0x47, 0xe8, 0x20, - 0x32, 0xe8, 0x20, 0x1e, 0xe8, 0xd0, 0xf5, 0x60, 0xae, 0x00, 0x78, - 0x9a, 0xad, 0x11, 0x44, 0x29, 0xfc, 0x09, 0x06, 0x8d, 0x11, 0x44, - 0xa2, 0x00, 0xbd, 0x00, 0x70, 0x95, 0x00, 0xbd, 0x00, 0x71, 0x9d, - 0x00, 0x01, 0xe8, 0xd0, 0xf2, 0xad, 0x13, 0x44, 0x8d, 0x11, 0x44, - 0xad, 0x10, 0x44, 0x29, 0xfc, 0x8d, 0x10, 0x44, 0xad, 0x02, 0x20, - 0x10, 0xfb, 0xad, 0x02, 0x20, 0x10, 0xfb, 0x68, 0xa8, 0x68, 0xaa, - 0x68, 0x28, 0x6c, 0xfa, 0xff, 0x08, 0x48, 0xad, 0x10, 0x44, 0x29, - 0x03, 0xd0, 0x33, 0xad, 0x10, 0x44, 0x09, 0x02, 0x8d, 0x10, 0x44, - 0xad, 0x11, 0x44, 0x8d, 0x13, 0x44, 0x09, 0x04, 0x29, 0xfc, 0x8d, - 0x11, 0x44, 0xad, 0x06, 0x60, 0x10, 0x0b, 0x8a, 0x48, 0x98, 0x48, - 0xba, 0x8e, 0x00, 0x78, 0x4c, 0x03, 0x60, 0xad, 0x13, 0x44, 0x8d, - 0x11, 0x44, 0xad, 0x10, 0x44, 0x29, 0xfc, 0x8d, 0x10, 0x44, 0xad, - 0x10, 0x44, 0x29, 0xbf, 0x8d, 0x10, 0x44, 0x29, 0x03, 0xc9, 0x02, - 0xf0, 0x05, 0x68, 0x28, 0x6c, 0xfa, 0xff, 0x68, 0x28, 0x4c, 0x64, - 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa9, 0x00, 0x85, 0xfc, 0x85, 0xfd, 0x20, 0x3a, 0xe1, 0x20, - 0x73, 0xe3, 0xba, 0xee, 0x20, 0x22, 0xe4, 0x20, 0x73, 0xe3, 0xf6, - 0xee, 0x20, 0xa3, 0xee, 0x20, 0x3a, 0xe1, 0x20, 0x4e, 0xec, 0x20, - 0x22, 0xe4, 0x20, 0x73, 0xe3, 0xce, 0xee, 0x20, 0x73, 0xe3, 0x07, - 0xef, 0x20, 0xa3, 0xee, 0x20, 0x3a, 0xe1, 0x20, 0x67, 0xec, 0x20, - 0x7b, 0xec, 0x20, 0x22, 0xe4, 0x20, 0x73, 0xe3, 0xe2, 0xee, 0x20, - 0x73, 0xe3, 0x18, 0xef, 0x20, 0x99, 0xee, 0x20, 0x5c, 0xe3, 0x4c, - 0x00, 0xec, 0x20, 0xd4, 0xed, 0x20, 0x8c, 0xec, 0xea, 0xea, 0xea, - 0x20, 0x42, 0xe0, 0xa5, 0x06, 0x85, 0x94, 0x85, 0x95, 0x20, 0x01, - 0xed, 0x20, 0xa7, 0xe2, 0x60, 0x20, 0xd4, 0xed, 0x20, 0xad, 0xee, - 0x20, 0xa0, 0xec, 0xa5, 0x95, 0x85, 0x06, 0x20, 0x6e, 0xed, 0x20, - 0xa7, 0xe2, 0x60, 0x20, 0xd4, 0xed, 0x20, 0xdc, 0xec, 0xa5, 0x95, - 0x85, 0x06, 0x20, 0xa1, 0xed, 0x20, 0xa7, 0xe2, 0x60, 0x20, 0xe2, - 0xed, 0xa0, 0x00, 0x20, 0x12, 0xe3, 0x99, 0x00, 0x07, 0xc8, 0xc0, - 0x37, 0xd0, 0xf5, 0x20, 0xcd, 0xe1, 0x60, 0x20, 0xb4, 0xe2, 0xa5, - 0xfa, 0x29, 0x2b, 0x8d, 0x25, 0x40, 0xa9, 0x00, 0x8d, 0x24, 0x40, - 0xa0, 0xc5, 0x20, 0x2c, 0xe1, 0xa0, 0x56, 0x20, 0x2c, 0xe1, 0xa9, - 0x01, 0x20, 0x37, 0xe3, 0xa0, 0x00, 0xb9, 0x00, 0x07, 0x20, 0x12, - 0xe3, 0xc8, 0xc0, 0x37, 0xd0, 0xf5, 0x20, 0xf0, 0xe1, 0xa9, 0x02, - 0x20, 0x37, 0xe3, 0xa5, 0x94, 0x20, 0x12, 0xe3, 0x20, 0xf0, 0xe1, - 0x60, 0x20, 0xe2, 0xed, 0xa0, 0x00, 0x20, 0x12, 0xe3, 0xa2, 0x22, - 0xd9, 0x00, 0x07, 0x20, 0x2b, 0xe2, 0xc8, 0xc0, 0x37, 0xd0, 0xf0, - 0x20, 0xcd, 0xe1, 0x20, 0x42, 0xe0, 0xa5, 0x06, 0xa2, 0x23, 0xc5, - 0x94, 0x20, 0x2b, 0xe2, 0x60, 0xa9, 0x03, 0x20, 0x16, 0xe3, 0xa0, - 0x00, 0x20, 0x12, 0xe3, 0x99, 0xa0, 0x00, 0x20, 0x61, 0xee, 0xc8, - 0xc0, 0x0f, 0xd0, 0xf2, 0x20, 0xcd, 0xe1, 0xa9, 0x04, 0x20, 0x16, - 0xe3, 0x20, 0x89, 0xee, 0x90, 0x09, 0x20, 0x12, 0xe3, 0x20, 0x61, - 0xee, 0x4c, 0x1e, 0xed, 0x20, 0xcd, 0xe1, 0xc6, 0x06, 0xd0, 0xce, - 0x60, 0x20, 0x10, 0xee, 0xc9, 0x03, 0xd0, 0x32, 0xa0, 0x00, 0x20, - 0x12, 0xe3, 0x99, 0xa0, 0x00, 0x20, 0x61, 0xee, 0xc8, 0xc0, 0x0f, - 0xd0, 0xf2, 0x20, 0x22, 0xee, 0x20, 0x10, 0xee, 0xc9, 0x04, 0xd0, - 0x18, 0x20, 0x89, 0xee, 0x90, 0x09, 0x20, 0x12, 0xe3, 0x20, 0x61, - 0xee, 0x4c, 0x55, 0xed, 0x20, 0x22, 0xee, 0xd0, 0x05, 0xe6, 0x95, - 0x4c, 0x34, 0xed, 0x60, 0xa9, 0x03, 0x20, 0x37, 0xe3, 0xa0, 0x00, - 0x20, 0x68, 0xee, 0x99, 0xa0, 0x00, 0x20, 0x12, 0xe3, 0xc8, 0xc0, - 0x0f, 0xd0, 0xf2, 0x20, 0xf0, 0xe1, 0xa9, 0x04, 0x20, 0x37, 0xe3, - 0x20, 0x89, 0xee, 0x90, 0x09, 0x20, 0x68, 0xee, 0x20, 0x12, 0xe3, - 0x4c, 0x8b, 0xed, 0x20, 0xf0, 0xe1, 0xc6, 0x06, 0xd0, 0xce, 0x60, - 0xa9, 0x03, 0x20, 0x16, 0xe3, 0xa0, 0x00, 0x20, 0x12, 0xe3, 0x99, - 0xa0, 0x00, 0x20, 0x56, 0xee, 0xc8, 0xc0, 0x0f, 0xd0, 0xf2, 0x20, - 0xcd, 0xe1, 0xa9, 0x04, 0x20, 0x16, 0xe3, 0x20, 0x89, 0xee, 0x90, - 0x09, 0x20, 0x12, 0xe3, 0x20, 0x56, 0xee, 0x4c, 0xbe, 0xed, 0x20, - 0xcd, 0xe1, 0xc6, 0x06, 0xd0, 0xce, 0x60, 0xa9, 0x00, 0x85, 0x90, - 0x8d, 0xff, 0x43, 0x85, 0x88, 0xa9, 0x60, 0x85, 0x89, 0x60, 0x20, - 0xb4, 0xe2, 0xa0, 0xc5, 0x20, 0x2c, 0xe1, 0xa0, 0x46, 0x20, 0x2c, - 0xe1, 0xa9, 0x01, 0x20, 0x16, 0xe3, 0x60, 0xa0, 0x0f, 0xb9, 0x00, - 0x07, 0xc9, 0xb0, 0xd0, 0x11, 0xc8, 0xc0, 0x12, 0xd0, 0xf4, 0xb9, - 0x00, 0x07, 0xc9, 0xb1, 0xb0, 0x05, 0xa2, 0x06, 0x4c, 0x2d, 0xe2, - 0x60, 0xa0, 0x05, 0x20, 0x2c, 0xe1, 0xa5, 0xfa, 0x09, 0x40, 0x85, - 0xfa, 0x8d, 0x25, 0x40, 0x20, 0x03, 0xe3, 0x60, 0x20, 0x12, 0xe3, - 0xad, 0x30, 0x40, 0x29, 0x40, 0xd0, 0x29, 0xa5, 0xfa, 0x09, 0x10, - 0x85, 0xfa, 0x8d, 0x25, 0x40, 0x20, 0x12, 0xe3, 0xad, 0x30, 0x40, - 0x29, 0x10, 0xd0, 0x16, 0xa5, 0xfa, 0x29, 0x2f, 0x09, 0x04, 0x85, - 0xfa, 0x8d, 0x25, 0x40, 0xa2, 0x01, 0xad, 0x32, 0x40, 0x4a, 0x20, - 0x28, 0xe2, 0xa9, 0x00, 0x60, 0xa2, 0x00, 0xc1, 0x88, 0xf0, 0x10, - 0xa2, 0x26, 0x4c, 0x2d, 0xe2, 0xa2, 0x00, 0x81, 0x88, 0x4c, 0x6c, - 0xee, 0xa2, 0x00, 0xa1, 0x88, 0xe6, 0x88, 0xd0, 0x18, 0xe6, 0x89, - 0xa6, 0x89, 0xe0, 0xe0, 0x90, 0x10, 0xa2, 0x60, 0x86, 0x89, 0x48, - 0x18, 0xa5, 0x90, 0x69, 0x10, 0x85, 0x90, 0x8d, 0xff, 0x43, 0x68, - 0x60, 0xa5, 0xac, 0x38, 0xe9, 0x01, 0x85, 0xac, 0xb0, 0x06, 0xa5, - 0xad, 0xe9, 0x00, 0x85, 0xad, 0x60, 0x20, 0x76, 0xe4, 0x20, 0x8c, - 0xe1, 0x20, 0x5e, 0xe1, 0x60, 0x20, 0x99, 0xee, 0x20, 0x5c, 0xe3, - 0x20, 0x64, 0xe3, 0x60, 0xad, 0x32, 0x40, 0x29, 0x04, 0xd0, 0x01, - 0x60, 0xa2, 0x07, 0x4c, 0x2d, 0xe2, 0x3f, 0x00, 0x10, 0x0f, 0x2a, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0xff, 0x3f, 0x00, 0x10, 0x0f, 0x26, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0xff, 0x3f, 0x00, 0x10, 0x0f, 0x22, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, - 0x21, 0xe8, 0x0d, 0x12, 0x17, 0x1c, 0x0e, 0x1b, 0x1d, 0x24, 0x1c, - 0x18, 0x1e, 0x1b, 0x0c, 0x0e, 0xff, 0x21, 0xe8, 0x0d, 0x12, 0x17, - 0x1c, 0x0e, 0x1b, 0x1d, 0x24, 0x1d, 0x0a, 0x1b, 0x10, 0x0e, 0x1d, - 0xff, 0x21, 0xec, 0x07, 0x0c, 0x18, 0x19, 0x22, 0x24, 0x18, 0x14, - 0xff, 0xa9, 0x00, 0x8d, 0xff, 0x43, 0x8d, 0x0c, 0x44, 0x8d, 0x02, - 0x01, 0xa9, 0x80, 0x8d, 0xff, 0x42, 0xa9, 0x03, 0x8d, 0x11, 0x44, - 0xa9, 0x83, 0x8d, 0x10, 0x44, 0xd0, 0x2c, 0x78, 0xa9, 0x00, 0x8d, - 0x00, 0x20, 0x8d, 0x01, 0x20, 0x8d, 0x0c, 0x44, 0xa2, 0x03, 0xad, - 0x02, 0x20, 0x10, 0xfb, 0xca, 0xd0, 0xf8, 0x2c, 0x10, 0x44, 0x30, - 0x09, 0x70, 0x07, 0xad, 0x10, 0x44, 0x29, 0x1f, 0x10, 0x18, 0xad, - 0x10, 0x44, 0x29, 0x1f, 0x8d, 0x12, 0x44, 0xad, 0x10, 0x44, 0x29, - 0xfc, 0x09, 0x02, 0x8d, 0x10, 0x44, 0x6c, 0xf6, 0xff, 0xad, 0x12, - 0x44, 0x8d, 0x10, 0x44, 0x8d, 0x10, 0x44, 0x29, 0x03, 0xc9, 0x02, - 0xf0, 0x09, 0xa2, 0xff, 0x9a, 0xe8, 0x8a, 0xa8, 0x6c, 0xfc, 0xff, - 0x20, 0xbe, 0xe6, 0x4c, 0x3f, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4c, 0xd9, - 0x48, 0x4c, 0x18, 0x49, 0x4c, 0x23, 0x4f, 0x4c, 0x3f, 0x4f, 0x4c, - 0x78, 0x4f -}; - -static uint8 prg[4]; -static uint8 chr1K[8]; -static uint8 chr; -static uint8 latch; - -static uint8 reg1M; -static uint8 reg2M; -static uint8 regtgd; - -static uint8 lockCHR; -static uint8 lastCHRBank; - -static uint8 IRQa_fds; -static int16 IRQCount_fds; -static uint16 IRQCount_tgd; -static uint16 count_target_tgd; - -static uint32 lastAddr; - -static writefunc writePPU; - -static SFORMAT StateRegs[] = { - { ®1M, 1, "REG1" }, - { ®2M, 1, "REG2" }, - { ®tgd, 1, "REGT" }, - { &latch, 1, "LATC" }, - { &chr, 1, "CREG" }, - { &lockCHR, 1, "CHRL" }, - { chr1K, 8, "CHR1" }, - { prg, 4, "PREG" }, - - { &IRQa_fds, 1, "IRQa" }, - { &IRQCount_fds, 2, "FDSC" }, - - { &IRQCount_tgd, 2, "TGDC" }, - { &count_target_tgd, 2, "TGDT" }, - - { &lastAddr, 1, "LADR" }, - - { 0 }, -}; - -static void Sync(void) { - setprg8r(0x10, 0x6000, 0); - /* PRG memory can be writable */ - SetupCartPRGMapping(0, PRGptr[0], PRGsize[0], !(reg1M & 0x02)); - if (regtgd & 0x80) { - setprg8(0x8000, prg[0]); - setprg8(0xA000, prg[1]); - setprg8(0xC000, prg[2]); - setprg8(0xE000, prg[3]); - } else if (!(reg2M & 0x01)) { - setprg8(0x8000, (prg[0] & 0x0F) | ((reg2M >> 2) & 0x10)); - setprg8(0xA000, (prg[1] & 0x0F) | ((reg2M >> 2) & 0x10)); - setprg8(0xC000, (prg[2] & 0x0F)); - setprg8(0xE000, (prg[3] & 0x0F)); - } else { - switch (reg1M >> 5) { - case 0: - setprg16(0x8000, latch & 0x07); - setprg16(0xC000, 0x07); - break; - case 1: - setprg16(0x8000, (latch >> 2) & 0x0F); - setprg16(0xC000, 0x07); - break; - case 2: - setprg16(0x8000, latch & 0x0F); - setprg16(0xC000, 0x0F); - break; - case 3: - setprg16(0x8000, 0x0F); - setprg16(0xC000, latch & 0x0F); - break; - case 4: - setprg32(0x8000, (latch >> 4) & 0x03); - break; - case 5: - setprg32(0x8000, 0x03); - break; - case 6: - setprg8(0x8000, latch & 0x0F); - setprg8(0xA000, latch >> 4); - setprg16(0xC000, 0x07); - break; - case 7: - setprg8(0x8000, latch & 0x0E); - setprg8(0xA000, (latch >> 4) | 0x01); - setprg16(0xC000, 0x07); - break; - } - } - - /* CHR RAN can be write-protected */ - SetupCartCHRMapping(0, CHRptr[0], CHRsize[0], !(((reg1M & 0xE0) & 0x80) || lockCHR)); - - if (regtgd & 0x40) { - setchr1(0x0000, chr1K[0]); - setchr1(0x0400, chr1K[1]); - setchr1(0x0800, chr1K[2]); - setchr1(0x0C00, chr1K[3]); - setchr1(0x1000, chr1K[4]); - setchr1(0x1400, chr1K[5]); - setchr1(0x1800, chr1K[6]); - setchr1(0x1C00, chr1K[7]); - } else { - setchr8(chr); - } - - switch (reg1M & 0x11) { - case 0x00: setmirror(MI_0); break; - case 0x01: setmirror(MI_V); break; - case 0x10: setmirror(MI_1); break; - case 0x11: setmirror(MI_H); break; - } -} - -static DECLFR(M562ReadReg) { - switch (A) { - case 0x4400: - case 0x4401: - case 0x4402: - case 0x4403: - case 0x4404: - case 0x4405: - case 0x4406: - case 0x4407: - return chr1K[A & 0x07]; - case 0x4408: - case 0x4409: - case 0x440A: - case 0x440B: - return (prg[A & 0x03] << 2) | (latch & 0x03); - case 0x440C: - return (IRQCount_tgd >> 8); - case 0x440D: - return (IRQCount_tgd & 0xFF); - case 0x4411: - return regtgd; - case 0x4415: - return reg1M; - case 0x4420: - return chr1K[lastCHRBank]; - default: - if (A & 0x800) { - return tgd4800[A & 0x7FF]; - } - return CartBR(A); - } -} - -static DECLFW(M562WriteReg) { - switch (A) { - case 0x4024: - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0x4025: - X6502_IRQEnd(FCEU_IQEXT); - IRQa_fds = V; - if (IRQa_fds & 0x42) { - IRQCount_fds = 0; - } - break; - case 0x42FC: - case 0x42FD: - case 0x42FE: - case 0x42FF: - reg1M = (V & 0xF0) | (A & 0x03); - lockCHR = !((reg1M & 0xE0) & 0x80); - Sync(); - break; - case 0x43FC: - case 0x43FD: - case 0x43FE: - case 0x43FF: - reg2M = (V & 0xF0) | (A & 0x03); - chr = V & 0x03; - Sync(); - break; - case 0x4400: - case 0x4401: - case 0x4402: - case 0x4403: - case 0x4404: - case 0x4405: - case 0x4406: - case 0x4407: - chr1K[A & 7] = V; - Sync(); - break; - case 0x440C: - X6502_IRQEnd(FCEU_IQEXT); - if (!(V & 0x80)) { - IRQCount_tgd = 0x8000; - } - count_target_tgd = (count_target_tgd & 0x00FF) | (V << 8); - break; - case 0x440D: - X6502_IRQEnd(FCEU_IQEXT); - count_target_tgd = (count_target_tgd & 0xFF00) | V; - break; - case 0x4411: - regtgd = V; - Sync(); - break; - } -} - -static DECLFW(M562Write) { - if (reg1M & 0x02) { - latch = V; - switch (reg1M >> 5) { - case 1: - case 4: - case 5: - chr = latch & 0x03; - break; - case 3: - chr = (latch >> 4) & 0x03; - break; - } - prg[(A >> 13) & 0x03] = V >> 2; - Sync(); - } else { - CartBW(A, V); - } -} - -static DECLFW(M562CHRWrite) { - if (((reg1M >> 5) >= 5) && (~(reg1M & 0x11) & 0x01)) { - lockCHR = !!(reg1M & 0x10); - } - writePPU(A, V); -} - -static void M562Reset(void) { - IRQa_fds = 0; - IRQCount_fds = 0; - IRQCount_tgd = 0xFFFF; - count_target_tgd = 0; - Sync(); -} - -static void M562Power(void) { - reg1M = (iNESCart.submapper << 5) | ((iNESCart.mirror == MI_V) ? 0x01 : 0x11) | 0x04 | 0x02; - reg2M = 0x03; - regtgd = 0x03; - - latch = 0; - chr = 0; - lockCHR = FALSE; - - prg[0] = 0x1C; - prg[1] = 0x1D; - prg[2] = 0x1E; - prg[3] = 0x1F; - chr1K[0] = 0; - chr1K[1] = 1; - chr1K[2] = 2; - chr1K[3] = 3; - chr1K[4] = 4; - chr1K[5] = 5; - chr1K[6] = 6; - chr1K[7] = 7; - IRQa_fds = 0; - IRQCount_fds = 0; - IRQCount_tgd = 0xFFFF; - count_target_tgd = 0; - - writePPU = GetWriteHandler(0x2007); - SetWriteHandler(0x2007, 0x2007, M562CHRWrite); - - SetReadHandler(0x4020, 0x4FFF, M562ReadReg); - SetWriteHandler(0x4020, 0x4FFF, M562WriteReg); - - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x8000, 0xFFFF, M562Write); - - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - - Sync(); - - if (MISC_ROM_SIZE && (MISC_ROM_SIZE >= 4)) { - uint16 trainerLoadAddr = 0x7000; - uint16 trainerInitAddr = 0x7003; - uint32 trainerSize = 512; - uint8 *trainerData = MISC_ROM_PTR; - int i; - - if (MISC_ROM_SIZE != 512) { - trainerLoadAddr = (MISC_ROM_PTR[1] << 8) | MISC_ROM_PTR[0]; - trainerInitAddr = (MISC_ROM_PTR[3] << 8) | MISC_ROM_PTR[2]; - trainerSize = MISC_ROM_SIZE - 4; - trainerData = MISC_ROM_PTR + 4; - - FCEU_printf(" load addr : %04x\n", trainerLoadAddr); - FCEU_printf(" init addr : %04x\n", trainerInitAddr); - FCEU_printf(" data size : %d\n", trainerSize); - } - - for (i = 0; i < MISC_ROM_SIZE; i++) { - (GetWriteHandler(trainerLoadAddr))(trainerLoadAddr + i, trainerData[i]); - } - - if (trainerInitAddr) { - /* JSR init */ - (GetWriteHandler(0x0700))(0x0700, 0x20); - (GetWriteHandler(0x0701))(0x0701, trainerInitAddr & 0xFF); - (GetWriteHandler(0x0702))(0x0702, trainerInitAddr >> 8); - - /* JMP ($FFFC) */ - (GetWriteHandler(0x0703))(0x0703, 0x6C); - (GetWriteHandler(0x0704))(0x0704, 0xFC); - (GetWriteHandler(0x0705))(0x0705, 0xFF); - - X6502_SetNewPC(0x700); - } - } - (GetWriteHandler(0x4017))(0x4017, 0x40); -} - -static void StateRestore(int version) { - Sync(); -} - -static void M562CPUIRQHook(int a) { - while (a--) { - IRQCount_fds += 3; - while ((IRQCount_fds >= 448) && (IRQa_fds & 0x80)) { - IRQCount_fds -= 448; - X6502_IRQBegin(FCEU_IQEXT); - } - if (count_target_tgd & 0x8000) { - if (IRQCount_tgd == count_target_tgd && (IRQCount_tgd != 0xFFFF)) { - X6502_IRQBegin(FCEU_IQEXT); - } else { - IRQCount_tgd++; - } - } - } -} - -static void M562PPUHook(uint32 A) { - if ((lastAddr != A) && ((A & 0x3000) != 0x2000)) { - lastCHRBank = (A >> 13) & 0x07; - } - lastAddr = A; -} - -void Mapper562_Init(CartInfo *info) { - uint32 wramsize = info->PRGRamSize + info->PRGRamSaveSize; - - info->Power = M562Power; - info->Reset = M562Reset; - MapIRQHook = M562CPUIRQHook; - PPU_hook = M562PPUHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); - - WRAMSIZE = wramsize ? wramsize : 8192; - if (WRAMSIZE) { - WRAM = (uint8 *)FCEU_malloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, TRUE); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - } - - if (CHR_ROM_SIZE) { - /* Game Doctor only used CHR RAM, but some .nes files has CHR ROM instead. */ - /* Remap CHR as writable. */ - SetupCartCHRMapping(0, CHR_ROM_PTR, CHR_ROM_SIZE, TRUE); - AddExState(CHR_ROM_PTR, CHR_ROM_SIZE, 0, "CHRM"); - } - - /* PRG memory can be writable, so add to states */ - AddExState(PRG_ROM_PTR, PRG_ROM_SIZE, 0, "PRGM"); -} diff --git a/src/mappers/nsf.c b/src/mappers/nsf.c deleted file mode 100644 index 8533a1a2b..000000000 --- a/src/mappers/nsf.c +++ /dev/null @@ -1,858 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include - -#include -#include - -#include "../fceu-types.h" -#include "../x6502.h" -#include "../fceu.h" -#include "../video.h" -#include "../sound.h" -#include "../general.h" -#include "../fceu-memory.h" -#include "../file.h" -#include "../fds.h" -#include "../cart.h" -#include "../input.h" -#include "../state.h" - -#include "mappers/sound/vrc6sound.h" -#include "mappers/sound/vrc7sound.h" -#include "mappers/sound/fdssound.h" -#include "mappers/sound/mmc5sound.h" -#include "mappers/sound/n163sound.h" -#include "mappers/sound/s5bsound.h" - -#include "nsf.h" -#include "nsfe.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define FIXED_EXWRAM_SIZE (32768 + 8192) - -static DECLFW(NSF_write); -static DECLFR(NSF_read); - -static int vismode = 1; - -static uint8 NSFROM[0x30 + 6] = -{ -/* 0x00 - NMI */ - 0x8D, 0xF4, 0x3F, /* Stop play routine NMIs. */ - 0xA2, 0xFF, 0x9A, /* Initialize the stack pointer. */ - 0xAD, 0xF0, 0x3F, /* See if we need to init. */ - 0xF0, 0x09, /* If 0, go to play routine playing. */ - - 0xAD, 0xF1, 0x3F, /* Confirm and load A */ - 0xAE, 0xF3, 0x3F, /* Load X with PAL/NTSC byte */ - - 0x20, 0x00, 0x00, /* JSR to init routine */ - - 0xA9, 0x00, - 0xAA, - 0xA8, - 0x20, 0x00, 0x00, /* JSR to play routine */ - 0x8D, 0xF5, 0x3F, /* Start play routine NMIs. */ - 0x90, 0xFE, /* Loopie time. */ - -/* 0x20 */ - 0x8D, 0xF3, 0x3F, /* Init init NMIs */ - 0x18, - 0x90, 0xFE /* Loopie time. */ -}; - -static DECLFR(NSFROMRead) { - return (NSFROM - 0x3800)[A]; -} - -static int lastJoy; -static int doreset = 0; -static int NSFNMIFlags; - -static uint8 BSon; -static int special = 0; -static uint8 *ExWRAM = 0; - -static uint8 SongReload; - -static uint8 *mmc5_exram; -static uint8 mmc5_mul[2]; - -NSFINFO *NSFInfo; - -extern uint8 FCEU_GetJoyJoy(void); - -static SFORMAT StateRegs[] = { - { &lastJoy, 1, "JOY" }, - { &SongReload, 1, "SREL" }, - { &doreset, 1, "DORE" }, - { &NSFNMIFlags, 1, "NMIF" }, - { 0 } -}; - -static void FreeNSF(void) { - if (mmc5_exram) { - free(mmc5_exram); - mmc5_exram = NULL; - } - - if (ExWRAM) { - free(ExWRAM); - ExWRAM = 0; - } - - if (NSFInfo) { - if (NSFInfo->NSFDATA) { - free(NSFInfo->NSFDATA); - NSFInfo->NSFDATA = NULL; - } - - free(NSFInfo); - NSFInfo = NULL; - } -} - -static void NSFGI(int h) { - switch (h) { - case GI_CLOSE: - FreeNSF(); - break; - case GI_RESETM2: - case GI_POWER: - NSF_init(); - break; - } -} - -/* First 32KB is reserved for sound chip emulation in the iNES mapper code. */ - -static INLINE void BANKSET(uint32 A, uint32 bank) { - bank &= NSFInfo->NSFMaxBank; - if (NSFInfo->SoundChip & NSFSOUND_FDS) { - memcpy(ExWRAM + (A - 0x6000), NSFInfo->NSFDATA + (bank << 12), 4096); - } else { - setprg4(A, bank); - } -} - -static int LoadNSF(FCEUFILE *fp) { - size_t tmp_size = FCEU_fgetsize(fp) - 0x80; - NSF_HEADER NSFHeader; - - FCEU_fread(&NSFHeader, 1, 0x80, fp); - - /* NULL-terminate strings just in case. */ - NSFHeader.GameName[31] = NSFHeader.Artist[31] = NSFHeader.Copyright[31] = 0; - - sprintf((char *)NSFInfo->SongName, "%s", (const char *)NSFHeader.GameName); - sprintf((char *)NSFInfo->Artist, "%s", (const char *)NSFHeader.Artist); - sprintf((char *)NSFInfo->Copyright, "%s", (const char *)NSFHeader.Copyright); - - NSFInfo->LoadAddr = NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh << 8); - NSFInfo->InitAddr = NSFHeader.InitAddressLow | (NSFHeader.InitAddressHigh << 8); - NSFInfo->PlayAddr = NSFHeader.PlayAddressLow | (NSFHeader.PlayAddressHigh << 8); - - if (tmp_size > 16 * 1024 * 1024) { - FCEU_PrintError("NSF is too large.\n"); - return FALSE; - } - - NSFInfo->NSFSize = tmp_size; - - NSFInfo->NSFMaxBank = ((NSFInfo->NSFSize + (NSFInfo->LoadAddr & 0xfff) + 4095) / 4096); - NSFInfo->NSFMaxBank = PRGsize[0] = uppow2(NSFInfo->NSFMaxBank); - - if (!(NSFInfo->NSFDATA = (uint8 *)FCEU_malloc(NSFInfo->NSFMaxBank * 4096))) { - return FALSE; - } - - FCEU_fseek(fp, 0x80, SEEK_SET); - memset(NSFInfo->NSFDATA, 0x00, NSFInfo->NSFMaxBank * 4096); - FCEU_fread(NSFInfo->NSFDATA + (NSFInfo->LoadAddr & 0xfff), 1, NSFInfo->NSFSize, fp); - - NSFInfo->NSFMaxBank--; - - NSFInfo->VideoSystem = NSFHeader.VideoSystem; - NSFInfo->SoundChip = NSFHeader.SoundChip; - NSFInfo->TotalSongs = NSFHeader.TotalSongs; - - if (NSFHeader.StartingSong == 0) { - NSFHeader.StartingSong = 1; - } - - NSFInfo->StartingSong = NSFHeader.StartingSong - 1; - memcpy(NSFInfo->BankSwitch, NSFHeader.BankSwitch, 8); - - return TRUE; -} - -int NSFLoad(FCEUFILE *fp) { - char magic[5]; - int x; - - NSFInfo = (NSFINFO *)FCEU_malloc(sizeof(NSFINFO)); - - FCEU_fseek(fp, 0, SEEK_SET); - FCEU_fread(&magic, 1, 5, fp); - - if (!memcmp(magic, "NESM\x1a", 5)) { - FCEU_fseek(fp, 0, SEEK_SET); - if (!LoadNSF(fp)) { - FreeNSF(); - return FALSE; - } - } else if (!memcmp(magic, "NSFE", 4)) { - FCEU_fseek(fp, 0, SEEK_SET); - if (!LoadNSFE(fp)) { - FreeNSF(); - return FALSE; - } - } else { - return FALSE; - } - - if (NSFInfo->LoadAddr < 0x6000) { - FCEU_PrintError("Invalid load address!"); - FreeNSF(); - return FALSE; - } - - if (NSFInfo->TotalSongs < 1) { - FCEU_PrintError("Total number of songs is less than 1\n"); - FreeNSF(); - return FALSE; - } - - BSon = 0; - for (x = 0; x < 8; x++) { - BSon |= NSFInfo->BankSwitch[x]; - } - - if (BSon == 0) { - uint8 BankCounter = 0x00; - - if (((NSFInfo->LoadAddr >> 8) & 0x70) >= 0x70) { - BSon = 0xFF; /* Ice Climber, and other F000 base address tunes need this */ - } else { - for (x = ((NSFInfo->LoadAddr >> 8) & 0x70) / 0x10; x < 8; x++) { - NSFInfo->BankSwitch[x] = BankCounter; - BankCounter += 0x01; - } - BSon = 0; - } - } - - for (x = 0; x < 8; x++) { - BSon |= NSFInfo->BankSwitch[x]; - } - - GameInfo->type = GIT_NSF; - GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD; - GameInfo->cspecial = SIS_NSF; - - for (x = 0;; x++) { - if (NSFROM[x] == 0x20) { - NSFROM[x + 1] = NSFInfo->InitAddr & 0xFF; - NSFROM[x + 2] = NSFInfo->InitAddr >> 8; - NSFROM[x + 8] = NSFInfo->PlayAddr & 0xFF; - NSFROM[x + 9] = NSFInfo->PlayAddr >> 8; - break; - } - } - - if (NSFInfo->VideoSystem == 0) { - GameInfo->vidsys = GIV_NTSC; - } else if (NSFInfo->VideoSystem == 1) { - GameInfo->vidsys = GIV_PAL; - } - - GameInterface = NSFGI; - - FCEU_printf("\n"); - FCEU_printf("NSF Loaded.\n"); - FCEU_printf("File information:\n"); - FCEU_printf(" Name: %s\n", NSFInfo->SongName); - FCEU_printf(" Artist: %s\n", NSFInfo->Artist); - FCEU_printf(" Copyright: %s\n", NSFInfo->Copyright); - if (NSFInfo->Dumper[0]) { - FCEU_printf(" Dumper: %s\n", NSFInfo->Dumper); - } - FCEU_printf("\n"); - if (NSFInfo->SoundChip) { - static char *tab[6] = { - "Konami VRC6", - "Konami VRC7", - "Nintendo FDS", - "Nintendo MMC5", - "Namco 163", - "Sunsoft 5B", - }; - - for (x = 0; x < 6; x++) { - if (NSFInfo->SoundChip & (1 << x)) { - FCEU_printf(" Expansion hardware: %s\n", tab[x]); - #if 0 - NSFInfo->SoundChip = 1 << x; /* Prevent confusing weirdness if more than one bit is set. */ - break; - #endif - } - } - } - if (BSon) { - FCEU_printf(" Bank-switched.\n"); - } - FCEU_printf(" Load address: $%04x\n", NSFInfo->LoadAddr); - FCEU_printf(" Init address: $%04x\n", NSFInfo->InitAddr); - FCEU_printf(" Play address: $%04x\n", NSFInfo->PlayAddr); - FCEU_printf(" %s\n", (NSFInfo->VideoSystem & 1) ? "PAL" : "NTSC"); - FCEU_printf(" Starting song: %d / %d\n\n", NSFInfo->StartingSong + 1, NSFInfo->TotalSongs); - - ExWRAM = (uint8 *)FCEU_gmalloc(FIXED_EXWRAM_SIZE); - - FCEUI_SetVidSystem(NSFInfo->VideoSystem != 0); - lastJoy = 0; - - /* TODO: hard-clip strings for now because of DrawNSF limtis */ - NSFInfo->SongName[31] = 0; - NSFInfo->Artist[31] = 0; - NSFInfo->Copyright[31] = 0; - NSFInfo->Dumper[31] = 0; - for (x = 0; x < (int)(sizeof(NSFInfo->SongNames) / sizeof(NSFInfo->SongNames[0])); x++) { - NSFInfo->SongNames[x][31] = 0; - } - - NSFInfo->CurrentSong = NSFInfo->StartingSong; - - return TRUE; -} - -static DECLFR(NSFVectorRead) { - if (((NSFNMIFlags & 1) && SongReload) || (NSFNMIFlags & 2) || doreset) { - if (A == 0xFFFA) { - return (0x00); - } else if (A == 0xFFFB) { - return (0x38); - } else if (A == 0xFFFC) { - return (0x20); - } else if (A == 0xFFFD) { - doreset = 0; - return (0x38); - } - return (X.DB); - } else { - return (CartBR(A)); - } -} - -void NSF_init(void) { - doreset = 1; - -/* NSFInfo->CurrentSong = NSFInfo->StartingSong; */ - SongReload = 0xFF; - NSFNMIFlags = 0; - - ResetExState(0, 0); - ResetCartMapping(); - - SetWriteHandler(0x6000, 0x7FFF, CartBW); - if (NSFInfo->SoundChip & NSFSOUND_FDS) { - SetupCartPRGMapping(0, ExWRAM, FIXED_EXWRAM_SIZE, 1); - setprg32(0x6000, 0); - setprg8(0xE000, 4); - memset(ExWRAM, 0x00, FIXED_EXWRAM_SIZE); - /* SetWriteHandler(0x6000, 0xDFFF, CartBW); */ - SetReadHandler(0x6000, 0xFFFF, CartBR); - } else { - memset(ExWRAM, 0x00, 8192); - SetReadHandler(0x6000, 0x7FFF, CartBR); - /* SetWriteHandler(0x6000, 0x7FFF, CartBW); */ - SetupCartPRGMapping(0, NSFInfo->NSFDATA, ((NSFInfo->NSFMaxBank + 1) * 4096), 0); - SetupCartPRGMapping(1, ExWRAM, 8192, 1); - setprg8r(1, 0x6000, 0); - SetReadHandler(0x8000, 0xFFFF, CartBR); - } - - if (BSon) { - int x; - for (x = 0; x < 8; x++) { - if (NSFInfo->SoundChip & NSFSOUND_FDS && x >= 6) { - BANKSET(0x6000 + (x - 6) * 4096, NSFInfo->BankSwitch[x]); - } - BANKSET(0x8000 + x * 4096, NSFInfo->BankSwitch[x]); - } - } else { - int x; - for (x = (NSFInfo->LoadAddr & 0xF000); x < 0x10000; x += 0x1000) { - BANKSET(x, ((x - (NSFInfo->LoadAddr & 0xF000)) >> 12)); - } - } - - SetReadHandler(0xFFFA, 0xFFFD, NSFVectorRead); - - SetWriteHandler(0x2000, 0x3fef, 0); - SetReadHandler(0x2000, 0x37ff, 0); - SetReadHandler(0x3836, 0x3FFF, 0); - SetReadHandler(0x3800, 0x3835, NSFROMRead); - - SetWriteHandler(0x5ff6, 0x5fff, NSF_write); - - SetWriteHandler(0x3ff0, 0x3fff, NSF_write); - SetReadHandler(0x3ff0, 0x3fff, NSF_read); - - AddExState(StateRegs, ~0, 0, NULL); - AddExState(ExWRAM, FIXED_EXWRAM_SIZE, 0, "ERAM"); - AddExState(&NSFInfo->CurrentSong, 4 | FCEUSTATE_RLSB, 0, "CURS"); - - /* init sound chips */ - - if (NSFInfo->SoundChip & NSFSOUND_VRC6) { - VRC6Sound_ESI(); - SetWriteHandler(0x9000, 0x9003, NSF_write); - SetWriteHandler(0xA000, 0xA002, NSF_write); - SetWriteHandler(0xB000, 0xB002, NSF_write); - } - if (NSFInfo->SoundChip & NSFSOUND_VRC7) { - VRC7Sound_ESI(); - SetWriteHandler(0x9010, 0x9010, NSF_write); - SetWriteHandler(0x9030, 0x9030, NSF_write); - } - if (NSFInfo->SoundChip & NSFSOUND_FDS) { - FDSSoundRegReset(); - FDSSound_SC(); - SetReadHandler(0x4040, 0x407F, NSF_read); - SetReadHandler(0x4090, 0x4090, NSF_read); - SetReadHandler(0x4092, 0x4092, NSF_read); - SetWriteHandler(0x4040, 0x408A, NSF_write); - } - if (NSFInfo->SoundChip & NSFSOUND_MMC5) { - MMC5Sound_ESI(); - SetReadHandler(0x5C00, 0x5fef, NSF_read); - SetReadHandler(0x5205, 0x5206, NSF_read); - SetWriteHandler(0x5000, 0x5015, NSF_write); - SetWriteHandler(0x5205, 0x5206, NSF_write); - SetWriteHandler(0x5C00, 0x5FF5, NSF_write); - if (mmc5_exram) { - FCEU_free(mmc5_exram); - } - mmc5_exram = (uint8 *)FCEU_malloc(1024); - } - if (NSFInfo->SoundChip & NSFSOUND_N163) { - N163Sound_ESI(); - SetReadHandler(0x4800, 0x4FFF, NSF_read); - SetWriteHandler(0x4800, 0x4FFF, NSF_write); - SetWriteHandler(0xF800, 0xFFFF, NSF_write); - } - if (NSFInfo->SoundChip & NSFSOUND_S5B) { - S5BSound_ESI(); - SetWriteHandler(0xC000, 0xCFFF, NSF_write); - SetWriteHandler(0xE000, 0xEFFF, NSF_write); - } - - /* sound chips states */ - - if (NSFInfo->SoundChip & NSFSOUND_VRC6) { - VRC6Sound_AddStateInfo(); - } - if (NSFInfo->SoundChip & NSFSOUND_VRC7) { - VRC7Sound_AddStateInfo(); - } - if (NSFInfo->SoundChip & NSFSOUND_FDS) { - FDSSound_AddStateInfo(); - } - if (NSFInfo->SoundChip & NSFSOUND_MMC5) { - MMC5Sound_AddStateInfo(); - AddExState(mmc5_exram, 1024, 0, "ExRM"); - AddExState(mmc5_mul, 2, 0, "MUL0"); - } - if (NSFInfo->SoundChip & NSFSOUND_N163) { - N163Sound_AddStateInfo(); - } - if (NSFInfo->SoundChip & NSFSOUND_S5B) { - S5BSound_AddStateInfo(); - } -} - -static DECLFW(NSF_write) { - if (NSFInfo->SoundChip & NSFSOUND_VRC6) { - switch (A) { - case 0x9000: - case 0x9001: - case 0x9002: - case 0x9003: - case 0xA000: - case 0xA001: - case 0xA002: - case 0xB000: - case 0xB001: - case 0xB002: - VRC6Sound_Write(A, V); - break; - } - } - - if (NSFInfo->SoundChip & NSFSOUND_VRC7) { - switch (A) { - case 0x9010: - case 0x9030: - VRC7Sound_Write(A, V); - break; - } - } - - if (NSFInfo->SoundChip & NSFSOUND_FDS) { - if ((A >= 0x6000) && (A <= 0xDFFF)){ - /* FIXME: Conflicts in multi chip modes */ - if (!(NSFInfo->SoundChip & (NSFSOUND_VRC6)) && !(A >= 0xA000 && A <= 0xA002)) { - CartBW(A, V); - } - } else if (A >= 0x4040 && A <= 0x407F) { - FDSWaveWrite(A, V); - } else { - switch (A) { - case 0x4080: FDSSReg0Write(A, V); break; - case 0x4082: FDSSReg1Write(A, V); break; - case 0x4083: FDSSReg2Write(A, V); break; - case 0x4084: FDSSReg3Write(A, V); break; - case 0x4085: FDSSReg4Write(A, V); break; - case 0x4086: FDSSReg5Write(A, V); break; - case 0x4087: FDSSReg6Write(A, V); break; - case 0x4088: FDSSReg7Write(A, V); break; - case 0x4089: FDSSReg8Write(A, V); break; - case 0x408A: FDSSReg9Write(A, V); break; - } - } - } - - if (NSFInfo->SoundChip & NSFSOUND_MMC5) { - if ((A >= 0x5000) && (A <= 0x5015)) { - MMC5Sound_Write(A, V); - } else if (A == 0x5205) { - mmc5_mul[0] = V; - } else if (A == 0x5206) { - mmc5_mul[1] = V; - } else if ((A >= 0x5c00) && (A <= 0x5FF5)) { - mmc5_exram[A & 0x3FF] = V; - } - } - - if (NSFInfo->SoundChip & NSFSOUND_N163) { - switch (A & 0xF800) { - case 0xF800: - N163Sound_Write(A, V); - break; - case 0x4800: - N163Sound_Write(A, V); - break; - } - } - - if (NSFInfo->SoundChip & NSFSOUND_S5B) { - switch (A & 0xF000) { - case 0xC000: - case 0xE000: - S5BSound_Write(A, V); - break; - } - } - - switch (A & 0xF000) { - case 0x6000: - case 0x7000: - /* always mapped to ExWRAM */ - CartBW(A, V); - break; - } - - switch (A) { - case 0x3FF3: - NSFNMIFlags |= 1; - break; - case 0x3FF4: - NSFNMIFlags &= ~2; - break; - case 0x3FF5: - NSFNMIFlags |= 2; - break; - - case 0x5FF6: - case 0x5FF7: - if (!(NSFInfo->SoundChip & NSFSOUND_FDS)) { - return; - } - /* fallthrough */ - case 0x5FF8: - case 0x5FF9: - case 0x5FFA: - case 0x5FFB: - case 0x5FFC: - case 0x5FFD: - case 0x5FFE: - case 0x5FFF: - if (!BSon) { - return; - } - A &= 0xF; - BANKSET((A * 4096), V); - break; - } -} - -static DECLFR(NSF_read) { - int x; - - if (NSFInfo->SoundChip & NSFSOUND_FDS) { - if ((A >= 0x4040) && (A <= 0x407F)) { - return FDSWaveRead(A); - } - if (A == 0x4090) { - return FDSEnvVolumeRead(A); - } - if (A == 0x4092) { - return FDSEnvModRead(A); - } - } - - if (NSFInfo->SoundChip & NSFSOUND_MMC5) { - if ((A >= 0x5C00) && (A <= 0x5FEF)) { - return mmc5_exram[A & 0x3FF]; - } - if (A == 0x5205) { - return (uint8)(uint32)(mmc5_mul[0] * mmc5_mul[1]); - } - if (A == 0x5206) { - return (uint8)((uint32)(mmc5_mul[0] * mmc5_mul[1]) >> 8); - } - } - - if (NSFInfo->SoundChip & NSFSOUND_N163) { - if ((A >= 0x4800) && (A <= 0x4FFF)) { - return N163Sound_Read(A); - } - } - - switch (A) { - case 0x3ff0: - x = SongReload; -#ifdef FCEUDEF_DEBUGGER - if (!fceuindbg) -#endif - SongReload = 0; - return x; - case 0x3ff1: -#ifdef FCEUDEF_DEBUGGER - if (!fceuindbg) -#endif - { - for (x = 0; x < 0x800; x++) { - BWrite[x](x, 0); - } - - BWrite[0x4015](0x4015, 0x0); - for (x = 0; x < 0x14; x++) { - BWrite[0x4000 + x](0x4000 + x, 0); - } - BWrite[0x4015](0x4015, 0xF); - - if (NSFInfo->SoundChip & NSFSOUND_FDS) { - BWrite[0x4017](0x4017, 0xC0); /* FDS BIOS writes $C0 */ - BWrite[0x4089](0x4089, 0x80); - BWrite[0x408A](0x408A, 0xE8); - } else { - memset(ExWRAM, 0x00, 8192); - BWrite[0x4017](0x4017, 0xC0); - BWrite[0x4017](0x4017, 0xC0); - BWrite[0x4017](0x4017, 0x40); - } - - if (BSon) { - for (x = 0; x < 8; x++) { - BANKSET(0x8000 + x * 4096, NSFInfo->BankSwitch[x]); - } - } - return (NSFInfo->CurrentSong); - } - case 0x3FF3: - return PAL; - } - return X.DB; -} - -void DrawNSF(uint8 *target) { - char snbuf[16]; - int32 *Bufpl; - int32 mul = 0; - int len = GetSoundBuffer(&Bufpl); - int x; - uint8 bgFill = 0; - uint8 textColor = 0x06; - uint8 waveFormColor = 0x03; - - if (vismode == 0) { - return; - } - - memset(target, bgFill, 256 * 240); - memset(XDBuf, 0, 256 * 240); - - if (special == 0) { - if (FSettings.SoundVolume) { - mul = 8192 * 240 / (16384 * FSettings.SoundVolume / 50); - } - for (x = 0; x < 256; x++) { - uint32 y = 142 + ((((int32)(int16)Bufpl[(x * len) >> 8]) * mul) >> 14); - if (y < 240) { - target[x + y * 256] = waveFormColor; - } - } - } else if (special == 1) { - if (FSettings.SoundVolume) { - mul = 8192 * 240 / (8192 * FSettings.SoundVolume / 50); - } - for (x = 0; x < 256; x++) { - double r = (((int32)(int16)Bufpl[(x * len) >> 8]) * mul) >> 14; - uint32 xp = 128 + r * cos(x * M_PI * 2 / 256); - uint32 yp = 120 + r * sin(x * M_PI * 2 / 256); - - xp &= 255; - yp %= 240; - target[xp + yp * 256] = waveFormColor; - } - } else if (special == 2) { - static double theta = 0; - - if (FSettings.SoundVolume) { - mul = 8192 * 240 / (16384 * FSettings.SoundVolume / 50); - } - for (x = 0; x < 128; x++) { - double xc = (double)128 - x; - double yc = 0.0 - ((double)((((int32)(int16)Bufpl[(x * len) >> 8]) * mul) >> 14)); - double t = (M_PI + atan(yc / xc)) + theta; - double r = sqrt(xc * xc + yc * yc); - uint32 m = 128 + r * cos(t); - uint32 n = 120 + r * sin(t); - - if (m < 256 && n < 240) { - target[m + n * 256] = waveFormColor; - } - } - for (x = 128; x < 256; x++) { - double xc = (double)x - 128; - double yc = (double)((((int32)(int16)Bufpl[(x * len) >> 8]) * mul) >> 14); - double t = (atan(yc / xc)) + theta; - double r = sqrt(xc * xc + yc * yc); - uint32 m = 128 + r * cos(t); - uint32 n = 120 + r * sin(t); - - if (m < 256 && n < 240) { - target[m + n * 256] = waveFormColor; - } - } - theta += (double)M_PI / 256; - } - - DrawTextTrans(target + 10 * 256 + 4 + (((31 - strlen((char *)NSFInfo->SongName)) << 2)), 256, (uint8*)NSFInfo->SongName, textColor); - DrawTextTrans(target + 26 * 256 + 4 + (((31 - strlen((char *)NSFInfo->Artist)) << 2)), 256, (uint8*)NSFInfo->Artist, textColor); - DrawTextTrans( target + 42 * 256 + 4 + (((31 - strlen((char *)NSFInfo->Copyright)) << 2)), 256, (uint8*)NSFInfo->Copyright, textColor); - - if (NSFInfo->SongNames[0][0]) { - DrawTextTrans(target + 70 * 256 + 4 + (((31 - strlen((char *)NSFInfo->SongNames[NSFInfo->CurrentSong])) << 2)), 256, (uint8 *)NSFInfo->SongNames[NSFInfo->CurrentSong], textColor); - } else { - DrawTextTrans(target + 70 * 256 + 4 + (((31 - strlen("Song:")) << 2)), 256, (uint8 *)"Song:", textColor); - } - sprintf(snbuf, "<%d/%d>", NSFInfo->CurrentSong + 1, NSFInfo->TotalSongs); - DrawTextTrans(target + 82 * 256 + 4 + (((31 - strlen(snbuf)) << 2)), 256, (uint8 *)snbuf, textColor); -} - -void DoNSFFrame(void) { - uint8 tmp = FCEU_GetJoyJoy(); - - if (((NSFNMIFlags & 1) && SongReload) || (NSFNMIFlags & 2)) { - TriggerNMI(); - } - - if ((tmp & JOY_RIGHT) && !(lastJoy & JOY_RIGHT)) { - if (NSFInfo->CurrentSong < NSFInfo->TotalSongs - 1) { - NSFInfo->CurrentSong++; - } else { - NSFInfo->CurrentSong = NSFInfo->StartingSong; - } - SongReload = 0xFF; - } else if ((tmp & JOY_LEFT) && !(lastJoy & JOY_LEFT)) { - if (NSFInfo->CurrentSong > 0) { - NSFInfo->CurrentSong--; - } else { - NSFInfo->CurrentSong = NSFInfo->TotalSongs - 1; - } - SongReload = 0xFF; - } else if ((tmp & JOY_UP) && !(lastJoy & JOY_UP)) { - uint32 ns = NSFInfo->CurrentSong + (uint32)MIN(NSFInfo->TotalSongs - 1 - NSFInfo->CurrentSong, 10); - if (NSFInfo->CurrentSong != ns) { - NSFInfo->CurrentSong = ns; - SongReload = 0xFF; - } - } else if ((tmp & JOY_DOWN) && !(lastJoy & JOY_DOWN)) { - unsigned ns = NSFInfo->CurrentSong - (uint32)MIN(NSFInfo->CurrentSong, (uint32)10); - - if (NSFInfo->CurrentSong != ns) { - NSFInfo->CurrentSong = ns; - SongReload = 0xFF; - } - } else if ((tmp & JOY_SELECT) && !(lastJoy & JOY_SELECT)) { - NSFInfo->CurrentSong = NSFInfo->StartingSong; - SongReload = 0xFF; - } else if ((tmp & JOY_START) && !(lastJoy & JOY_START)) { - SongReload = 0xFF; - } else if ((tmp & JOY_A) && !(lastJoy & JOY_A)) { - special = (special + 1) % 3; - } - lastJoy = tmp; -} - -void FCEUI_NSFSetVis(int mode) { - vismode = mode; -} - -int FCEUI_NSFChange(int amount) { - NSFInfo->CurrentSong += amount; - if (NSFInfo->CurrentSong < 1) { - NSFInfo->CurrentSong = 1; - } else if (NSFInfo->CurrentSong > NSFInfo->TotalSongs) { - NSFInfo->CurrentSong = NSFInfo->TotalSongs; - } - SongReload = 0xFF; - - return (NSFInfo->CurrentSong); -} - -/* Returns total songs */ -int FCEUI_NSFGetInfo(uint8 *name, uint8 *artist, uint8 *copyright, int maxlen) { - strncpy((char *)name, (const char *)NSFInfo->SongName, (size_t)maxlen); - strncpy((char *)artist, (const char *)NSFInfo->Artist, (size_t)maxlen); - strncpy((char *)copyright, (const char *)NSFInfo->Copyright, (size_t)maxlen); - return (NSFInfo->TotalSongs); -} diff --git a/src/mappers/nsf.h b/src/mappers/nsf.h deleted file mode 100644 index 66f60f6e9..000000000 --- a/src/mappers/nsf.h +++ /dev/null @@ -1,84 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Xodnizel - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _FCEU_NSF_H -#define _FCEU_NSF_H - -#define NSFSOUND_VRC6 0x01 -#define NSFSOUND_VRC7 0x02 -#define NSFSOUND_FDS 0x04 -#define NSFSOUND_MMC5 0x08 -#define NSFSOUND_N163 0x10 -#define NSFSOUND_S5B 0x20 - -typedef struct NSF_HEADER { - char ID[5]; /* NESM^Z */ - uint8 Version; - uint8 TotalSongs; - uint8 StartingSong; - uint8 LoadAddressLow; - uint8 LoadAddressHigh; - uint8 InitAddressLow; - uint8 InitAddressHigh; - uint8 PlayAddressLow; - uint8 PlayAddressHigh; - uint8 GameName[32]; - uint8 Artist[32]; - uint8 Copyright[32]; - uint8 NTSCspeed[2]; /* Unused */ - uint8 BankSwitch[8]; - uint8 PALspeed[2]; /* Unused */ - uint8 VideoSystem; - uint8 SoundChip; - uint8 Expansion[4]; - uint8 reserve[8]; -} NSF_HEADER; - -typedef struct NSFINFO { - char SongName[256]; - char Artist[256]; - char Copyright[256]; - char Dumper[256]; - char SongNames[100][256]; - - uint8 TotalSongs; - uint8 StartingSong; - uint8 CurrentSong; - uint8 VideoSystem; - - uint16 PlayAddr, InitAddr, LoadAddr; - uint8 BankSwitch[8]; - uint8 SoundChip; - - uint8 *NSFDATA; - size_t NSFMaxBank; - size_t NSFSize; -} NSFINFO; - -extern NSFINFO *NSFInfo; - -void NSF_init(void); -void DrawNSF(uint8 *target); -void DoNSFFrame(void); - -/* NSF Expansion Chip Set Write Handler for mappers */ -void NFSSetWriteHandler(int chip, int32 start, int32 end, writefunc func); - -#endif diff --git a/src/mappers/nsfe.c b/src/mappers/nsfe.c deleted file mode 100644 index 922a193db..000000000 --- a/src/mappers/nsfe.c +++ /dev/null @@ -1,283 +0,0 @@ -/* FCEUmm - Multi-system Emulator - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include - -#include -#include - -#include "../fceu.h" -#include "../x6502.h" -#include "../sound.h" -#include "../cart.h" -#include "../fceu-endian.h" -#include "../file.h" -#include "../general.h" - -#include "nsf.h" -#include "nsfe.h" - -typedef struct { - uint8 LoadAddressLow; - uint8 LoadAddressHigh; - uint8 InitAddressLow; - uint8 InitAddressHigh; - uint8 PlayAddressLow; - uint8 PlayAddressHigh; - uint8 VideoSystem; - uint8 SoundChip; - uint8 TotalSongs; - uint8 StartingSong; -} NSFE_INFO; - -typedef struct { - uint32 info; - char ID[4]; -} NSFE_HEADER; - -static NSFE_HEADER nchead; - -static void GetString(FCEUFILE *fp, uint32 *chunk_size, uint8 *str) { - unsigned count = 0; - - while (*chunk_size) { - uint8 c = FCEU_fgetc(fp); - - (*chunk_size)--; - if (!c) { - break; - } - if (c < 0x20) { - c = 0x20; - } - *str++ = c; - count++; - } -} - -static void FreeNFSE(void) { - if (NSFInfo->NSFDATA) { - free(NSFInfo->NSFDATA); - NSFInfo->NSFDATA = NULL; - } -} - -static uint8 nsfe_INFO(FCEUFILE *fp) { - NSFE_INFO nsfe_info; - - if (NSFInfo->TotalSongs) { - FCEU_PrintError("NSFE chunk \"%.4s\" is duplicate.\n", (char *)nchead.ID); - return FALSE; - } - - if (nchead.info < 8) { - FCEU_PrintError("NSFE chunk \"%.4s\" size(%u) is invalid.\n", (char *)nchead.ID, nchead.info); - return FALSE; - } - - if (!FCEU_fread(&nsfe_info, 1, 10, fp)) { - return FALSE; - } - - NSFInfo->TotalSongs = 1; - NSFInfo->StartingSong = 0; - - NSFInfo->LoadAddr = nsfe_info.LoadAddressLow | nsfe_info.LoadAddressHigh << 8; - NSFInfo->InitAddr = nsfe_info.InitAddressLow | nsfe_info.InitAddressHigh << 8; - NSFInfo->PlayAddr = nsfe_info.PlayAddressLow | nsfe_info.PlayAddressHigh << 8; - NSFInfo->VideoSystem = nsfe_info.VideoSystem; - NSFInfo->SoundChip = nsfe_info.SoundChip; - - nchead.info -= 8; - - if (nchead.info) { - NSFInfo->TotalSongs = nsfe_info.TotalSongs; - if (!NSFInfo->TotalSongs) { - NSFInfo->TotalSongs = 255; - } - nchead.info--; - } - - if (nchead.info) { - NSFInfo->StartingSong = nsfe_info.StartingSong; - nchead.info--; - } - - return TRUE; -} - -static uint8 nsfe_DATA(FCEUFILE *fp) { - if (!NSFInfo->TotalSongs) { - FCEU_PrintError("NSFE chunk \"%.4s\" is out of order.\n", (char *)nchead.ID); - return FALSE; - } - - if (NSFInfo->NSFDATA) { - FCEU_PrintError("NSFE chunk \"%.4s\" is duplicate.\n", (char *)nchead.ID); - return FALSE; - } - - NSFInfo->NSFSize = nchead.info; - NSFInfo->NSFMaxBank = uppow2((NSFInfo->NSFSize + (NSFInfo->LoadAddr & 0xfff) + 0xfff) / 0x1000) - 1; - - NSFInfo->NSFDATA = (uint8 *)FCEU_malloc((NSFInfo->NSFMaxBank + 1) * 4096); - if (!NSFInfo->NSFDATA) { - return FALSE; - } - memset(NSFInfo->NSFDATA, 0, (NSFInfo->NSFMaxBank + 1) * 4096); - - if (!FCEU_fread(NSFInfo->NSFDATA + (NSFInfo->LoadAddr & 0xfff), 1, NSFInfo->NSFSize, fp)) { - return FALSE; - } - - nchead.info -= NSFInfo->NSFSize; - - return TRUE; -} - -static uint8 nsfe_BANK(FCEUFILE *fp) { - uint64 tr = (uint64)MIN((uint64)nchead.info, (uint64)8); - - if (!FCEU_fread(NSFInfo->BankSwitch, 1, tr, fp) != 0) { - return FALSE; - } - nchead.info -= 8; - - return TRUE; -} - -static uint8 nsfe_NEND(FCEUFILE *fp) { - if (nchead.info != 0) { - /* chunk size here can be anything */ - } else if (!NSFInfo->NSFDATA) { - FCEU_PrintError("NEND reached without preceding DATA chunk.\n"); - return FALSE; - } - - return TRUE; -} - -static uint8 nsfe_tlbl(FCEUFILE *fp) { - unsigned ws; - - if (!NSFInfo->TotalSongs) { - FCEU_PrintError("NSFE chunk \"%.4s\" is out of order.\n", (char *)nchead.ID); - return FALSE; - } - - for (ws = 0; ws < NSFInfo->TotalSongs && nchead.info > 0; ws++) { - GetString(fp, &nchead.info, (uint8 *)NSFInfo->SongNames[ws]); - } - - return TRUE; -} - -static uint8 nsfe_auth(FCEUFILE *fp) { - unsigned count; - - for (count = 0; count < 4 && nchead.info > 0; count++) { - switch (count) { - case 0: - GetString(fp, &nchead.info, (uint8 *)&NSFInfo->SongName); - break; - case 1: - GetString(fp, &nchead.info, (uint8 *)&NSFInfo->Artist); - break; - case 2: - GetString(fp, &nchead.info, (uint8 *)&NSFInfo->Copyright); - break; - case 3: - GetString(fp, &nchead.info, (uint8 *)&NSFInfo->Dumper); - break; - } - } - return TRUE; -} - -static uint8 nsfe_UNUSED(FCEUFILE *fp) { - /* unused chunk, just move our rom pointer at the end of chunk */ - if (nchead.info) { - if (FCEU_fseek(fp, nchead.info, SEEK_CUR) != 0) { - return FALSE; - } - } - nchead.info = 0; - return TRUE; -} - -int LoadNSFE(FCEUFILE *fp) { - if (FCEU_fseek(fp, 4, SEEK_CUR) != 0) { - return FALSE; - } - - for (;;) { - if (!FCEU_fread(&nchead, 1, 8, fp)) { - FreeNFSE(); - return FALSE; - } - /* FCEU_printf(" Chunk: \"%.4s\" %d\n", nchead.ID, nchead.info); */ - if (!memcmp(nchead.ID, "INFO", 4)) { - if (!nsfe_INFO(fp)) { - FreeNFSE(); - return FALSE; - } - } else if (!memcmp(nchead.ID, "BANK", 4)) { - if (!nsfe_BANK(fp)) { - FreeNFSE(); - return FALSE; - } - } else if (!memcmp(nchead.ID, "auth", 4)) { - if (!nsfe_auth(fp)) { - FreeNFSE(); - return FALSE; - } - } else if (!memcmp(nchead.ID, "tlbl", 4)) { - if (!nsfe_tlbl(fp)) { - FreeNFSE(); - return FALSE; - } - } else if (!memcmp(nchead.ID, "DATA", 4)) { - if (!nsfe_DATA(fp)) { - FreeNFSE(); - return FALSE; - } - } else if (!memcmp(nchead.ID, "NEND", 4)) { - if (!nsfe_NEND(fp)) { - FreeNFSE(); - return FALSE; - } - /* ignore remaining data from this point */ - return TRUE; - } else { - if (!nsfe_UNUSED(fp)) { - FreeNFSE(); - return FALSE; - } - } - if (nchead.info) { - /* this should not happen */ - if (FCEU_fseek(fp, nchead.info, SEEK_CUR) != 0) { - FreeNFSE(); - return FALSE; - } - nchead.info = 0; - } - } - FreeNFSE(); - return FALSE; -} diff --git a/src/mappers/nsfe.h b/src/mappers/nsfe.h deleted file mode 100644 index 739d9f420..000000000 --- a/src/mappers/nsfe.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __FCEU_NES_NSFE_H -#define __FCEU_NES_NSFE_H - -int LoadNSFE(FCEUFILE *fp); - -#endif /* __FCEU_NES_NSFE_H */ diff --git a/src/mappers/sound/dripsound.c b/src/mappers/sound/dripsound.c deleted file mode 100644 index 2dcd7a2d2..000000000 --- a/src/mappers/sound/dripsound.c +++ /dev/null @@ -1,250 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -#define TIMER_SHIFT ((FSettings.soundq >= 1) ? 0 : 17) - -typedef struct DRIPSOUND { - uint8 buffer[256], readPos, writePos; - uint8 bufferFull, bufferEmpty; - uint8 volume; - uint16 freq; - int32 timer; - int16 out; -} DRIPSOUND; - -static DRIPSOUND channel[2]; -static int32 cvbc = 0; - -static void SetOutput(DRIPSOUND *ds, int32 output) { - ds->out = output; -} - -static void ChannelReset(DRIPSOUND *ds) { - memset(ds->buffer, 0, 256); - ds->readPos = 0; - ds->writePos = 0; - ds->bufferFull = FALSE; - ds->bufferEmpty = TRUE; -} - -static uint8 ChannelRead(DRIPSOUND *ds, uint16 A) { - uint8 result = 0; - - if (ds->bufferFull) { - result |= 0x80; - } - - if (ds->bufferEmpty) { - result |= 0x40; - } - - return result; -} - -static void ChannelWrite(DRIPSOUND *ds, uint16 A, uint8 V) { - switch (A & 0x03) { - case 0: - ChannelReset(ds); - SetOutput(ds, 0); - ds->timer = ds->freq << TIMER_SHIFT; - break; - - case 1: - if (ds->readPos == ds->writePos) { - ds->bufferEmpty = FALSE; - SetOutput(ds, V * ds->volume); - ds->timer = ds->freq << TIMER_SHIFT; - } - - ds->buffer[ds->writePos++] = V; - if (ds->readPos == ds->writePos) { - ds->bufferFull = TRUE; - } - break; - - case 2: - ds->freq = (ds->freq & 0xF00) | V; - break; - - case 3: - ds->freq = (ds->freq & 0xFF) | ((V & 0xF) << 8); - ds->volume = (V & 0xF0) >> 4; - if (!ds->bufferEmpty) { - SetOutput(ds, ds->buffer[ds->readPos] * ds->volume); - } - break; - } -} - -static int32 GetSample(void) { - int32 out = 0; - int P; - - for (P = 0; P < 2; P++) { - DRIPSOUND *ds = &channel[P]; - - if (!ds->bufferEmpty) { - ds->timer -= nesincsize; - while (ds->timer <= 0) { - ds->timer += ds->freq << TIMER_SHIFT; - if (ds->readPos == ds->writePos) { - ds->bufferFull = FALSE; - } - - ds->readPos++; - SetOutput(ds, ds->buffer[ds->readPos] * ds->volume); - - if (ds->readPos == ds->writePos) { - ds->bufferEmpty = TRUE; - } - } - } - out += ds->out; - } - return out; -} - -static void DRIPSound(void) { - int P, V; - int start = cvbc; - int end = ((int)SOUNDTS << 16) / soundtsinc; - - if (end <= start) { - return; - } - cvbc = end; - - for (V = start; V < end; V++) { - Wave[V >> 4] += GetSample() >> 4; - } -} - -static int32 GetSampleHQ(void) { - int32 out = 0; - int P; - - for (P = 0; P < 2; P++) { - DRIPSOUND *ds = &channel[P]; - - if (!ds->bufferEmpty) { - ds->timer--; - if (ds->timer <= 0) { - ds->timer = ds->freq << TIMER_SHIFT; - if (ds->readPos == ds->writePos) { - ds->bufferFull = FALSE; - } - - ds->readPos++; - SetOutput(ds, ds->buffer[ds->readPos] * ds->volume); - - if (ds->readPos == ds->writePos) { - ds->bufferEmpty = TRUE; - } - } - } - out += ds->out; - } - return out; -} - -static void DoDRIPSoundHQ(void) { - int P, V; - - for (V = cvbc; V < (int)SOUNDTS; V++) { - WaveHi[V] += GetSampleHQ(); - } - cvbc = SOUNDTS; -} - -static void DoDripSound(int Count) { - DRIPSound(); - cvbc = Count; -} - -static void SyncHQ(int32 ts) { - cvbc = ts; -} - -DECLFR(DRIPSound_Read) { - if (A & 0x800) { - return (ChannelRead(&channel[1], A)); - } - return (ChannelRead(&channel[0], A)); -} - -DECLFW(DRIPSound_Write) { - if (FSettings.SndRate > 0) { - if (FSettings.soundq >= 1) { - DoDRIPSoundHQ(); - } else { - DRIPSound(); - } - } - if (A & 0x04) { - ChannelWrite(&channel[1], A, V); - } else { - ChannelWrite(&channel[0], A, V); - } -} - -static void DRIPSound_SC(void) { - GameExpSound[0].Fill = DoDripSound; - GameExpSound[0].HiSync = SyncHQ; - GameExpSound[0].HiFill = DoDRIPSoundHQ; - GameExpSound[0].RChange = DRIPSound_SC; - channel[0].timer = 0; - channel[1].timer = 0; - cvbc = 0; -} - -void DRIPSound_ESI(void) { - GameExpSound[0].RChange = DRIPSound_SC; - - ChannelReset(&channel[0]); - ChannelReset(&channel[1]); - - DRIPSound_SC(); -} - -void DRIPSound_AddStateInfo(void) { - AddExState(channel[0].buffer, 256, 0, "FF00"); - AddExState(&channel[0].readPos, 1, 0, "RDP0"); - AddExState(&channel[0].writePos, 1, 0, "WRP0"); - AddExState(&channel[0].bufferFull, 1, 0, "FUL0"); - AddExState(&channel[0].bufferEmpty, 1, 0, "EMT0"); - AddExState(&channel[0].freq, 2, 0, "FRQ0"); - AddExState(&channel[0].volume, 1, 0, "VOL0"); - AddExState(&channel[0].timer, 4, 0, "TIM0"); - AddExState(&channel[0].out, 2, 0, "POS0"); - - AddExState(channel[1].buffer, 256, 0, "FF01"); - AddExState(&channel[1].readPos, 1, 0, "RDP1"); - AddExState(&channel[1].writePos, 1, 0, "WRP1"); - AddExState(&channel[1].bufferFull, 1, 0, "FUL1"); - AddExState(&channel[1].bufferEmpty, 1, 0, "EMT1"); - AddExState(&channel[1].freq, 2, 0, "FRQ1"); - AddExState(&channel[1].volume, 1, 0, "VOL1"); - AddExState(&channel[1].timer, 4, 0, "TIM1"); - AddExState(&channel[1].out, 2, 0, "POS1"); - - AddExState(&cvbc, 4, 0, "CVBC"); -} diff --git a/src/mappers/sound/dripsound.h b/src/mappers/sound/dripsound.h deleted file mode 100644 index f5e190a17..000000000 --- a/src/mappers/sound/dripsound.h +++ /dev/null @@ -1,29 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _DRIPSOUND_H -#define _DRIPSOUND_H - -void DRIPSound_ESI(void); -DECLFR(DRIPSound_Read); -DECLFW(DRIPSound_Write); -void DRIPSound_AddStateInfo(void); - -#endif /* _DRIPSOUND_H */ \ No newline at end of file diff --git a/src/mappers/sound/emu2149.c b/src/mappers/sound/emu2149.c deleted file mode 100644 index 0594b7050..000000000 --- a/src/mappers/sound/emu2149.c +++ /dev/null @@ -1,431 +0,0 @@ -/** - * emu2149 v1.41 - * https://github.com/digital-sound-antiques/emu2149 - * Copyright (C) 2001-2022 Mitsutaka Okazaki - * - * This source refers to the following documents. The author would like to thank all the authors who have - * contributed to the writing of them. - * - psg.vhd -- 2000 written by Kazuhiro Tsujikawa. - * - s_fme7.c -- 1999,2000 written by Mamiya (NEZplug). - * - ay8910.c -- 1998-2001 Author unknown (MAME). - * - MSX-Datapack -- 1991 ASCII Corp. - * - AY-3-8910 data sheet - */ -#include -#include -#include "emu2149.h" - -#ifndef INLINE -#if defined(_MSC_VER) -#define INLINE __inline -#elif defined(__GNUC__) -#define INLINE __inline__ -#else -#define INLINE INLINE -#endif -#endif - -static uint32_t voltbl[2][32] = { - /* YM2149 - 32 steps */ - {0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, - 0x0B, 0x0D, 0x0F, 0x12, - 0x16, 0x1A, 0x1F, 0x25, 0x2D, 0x35, 0x3F, 0x4C, 0x5A, 0x6A, 0x7F, 0x97, - 0xB4, 0xD6, 0xFF, 0xFF}, - /* AY-3-8910 - 16 steps */ - {0x00, 0x00, 0x03, 0x03, 0x04, 0x04, 0x06, 0x06, 0x09, 0x09, 0x0D, 0x0D, - 0x12, 0x12, 0x1D, 0x1D, - 0x22, 0x22, 0x37, 0x37, 0x4D, 0x4D, 0x62, 0x62, 0x82, 0x82, 0xA6, 0xA6, - 0xD0, 0xD0, 0xFF, 0xFF} -}; - -static const uint8_t regmsk[16] = { - 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0x1f, 0x3f, - 0x1f, 0x1f, 0x1f, 0xff, 0xff, 0x0f, 0xff, 0xff -}; - -#define GETA_BITS 24 - -static void -internal_refresh (PSG * psg) -{ - uint32_t f_master = psg->clk; - - if (psg->clk_div) - f_master /= 2; - - if (psg->quality) - { - psg->base_incr = 1 << GETA_BITS; - psg->realstep = f_master; - psg->psgstep = psg->rate * 8; - psg->psgtime = 0; - psg->freq_limit = (uint32_t)(f_master / 16 / (psg->rate / 2)); - } - else - { - psg->base_incr = (uint32_t)((double)f_master * (1 << GETA_BITS) / 8 / psg->rate); - psg->freq_limit = 0; - } -} - -void -PSG_setClock(PSG *psg, uint32_t clock) -{ - if (psg->clk != clock) { - psg->clk = clock; - internal_refresh(psg); - } -} - -void -PSG_setClockDivider(PSG *psg, uint8_t enable) -{ - if (psg->clk_div != enable) { - psg->clk_div = enable; - internal_refresh (psg); - } -} - -void -PSG_setRate (PSG * psg, uint32_t rate) -{ - uint32_t r = rate ? rate : 44100; - if (psg->rate != r) { - psg->rate = r; - internal_refresh(psg); - } -} - -void -PSG_setQuality (PSG * psg, uint8_t q) -{ - if (psg->quality != q) { - psg->quality = q; - internal_refresh(psg); - } -} - -PSG * -PSG_new (uint32_t clock, uint32_t rate) -{ - PSG *psg; - - psg = (PSG *) calloc (1, sizeof (PSG)); - if (psg == NULL) - return NULL; - - PSG_setVolumeMode(psg, 0); - psg->clk = clock; - psg->clk_div = 0; - psg->rate = rate ? rate : 44100; - psg->quality = 0; - internal_refresh(psg); - PSG_setMask(psg, 0x00); - return psg; -} - -void -PSG_setVolumeMode (PSG * psg, int type) -{ - switch (type) - { - case 1: - psg->voltbl = voltbl[0]; /* YM2149 */ - break; - case 2: - psg->voltbl = voltbl[1]; /* AY-3-8910 */ - break; - default: - psg->voltbl = voltbl[0]; /* fallback: YM2149 */ - break; - } -} - -uint32_t -PSG_setMask (PSG *psg, uint32_t mask) -{ - uint32_t ret = 0; - if(psg) - { - ret = psg->mask; - psg->mask = mask; - } - return ret; -} - -uint32_t -PSG_toggleMask (PSG *psg, uint32_t mask) -{ - uint32_t ret = 0; - if(psg) - { - ret = psg->mask; - psg->mask ^= mask; - } - return ret; -} - -void -PSG_reset (PSG * psg) -{ - int i; - - psg->base_count = 0; - - for (i = 0; i < 3; i++) - { - psg->count[i] = 0; - psg->freq[i] = 0; - psg->edge[i] = 0; - psg->volume[i] = 0; - psg->ch_out[i] = 0; - } - - psg->mask = 0; - - for (i = 0; i < 16; i++) - psg->reg[i] = 0; - psg->adr = 0; - - psg->noise_seed = 0xffff; - psg->noise_scaler = 0; - psg->noise_count = 0; - psg->noise_freq = 0; - - psg->env_ptr = 0; - psg->env_freq = 0; - psg->env_count = 0; - psg->env_pause = 1; - - psg->out = 0; - -} - -void -PSG_delete (PSG * psg) -{ - free (psg); -} - -uint8_t -PSG_readIO (PSG * psg) -{ - return (uint8_t) (psg->reg[psg->adr]); -} - -uint8_t -PSG_readReg (PSG * psg, uint32_t reg) -{ - return (uint8_t) (psg->reg[reg & 0x1f]); -} - -void -PSG_writeIO (PSG * psg, uint32_t adr, uint32_t val) -{ - if (adr & 1) - PSG_writeReg (psg, psg->adr, val); - else - psg->adr = val & 0x1f; -} - -static INLINE void -update_output (PSG * psg) -{ - - int i, noise; - uint8_t incr; - - psg->base_count += psg->base_incr; - incr = (psg->base_count >> GETA_BITS); - psg->base_count &= (1 << GETA_BITS) - 1; - - /* Envelope */ - psg->env_count += incr; - - if (psg->env_count >= psg->env_freq) - { - if (!psg->env_pause) - { - if(psg->env_face) - psg->env_ptr = (psg->env_ptr + 1) & 0x3f ; - else - psg->env_ptr = (psg->env_ptr + 0x3f) & 0x3f; - } - - if (psg->env_ptr & 0x20) /* if carry or borrow */ - { - if (psg->env_continue) - { - if (psg->env_alternate^psg->env_hold) psg->env_face ^= 1; - if (psg->env_hold) psg->env_pause = 1; - psg->env_ptr = psg->env_face ? 0 : 0x1f; - } - else - { - psg->env_pause = 1; - psg->env_ptr = 0; - } - } - - if (psg->env_freq >= incr) - psg->env_count -= psg->env_freq; - else - psg->env_count = 0; - } - - /* Noise */ - psg->noise_count += incr; - if (psg->noise_count >= psg->noise_freq) - { - psg->noise_scaler ^= 1; - if (psg->noise_scaler) - { - if (psg->noise_seed & 1) - psg->noise_seed ^= 0x24000; - psg->noise_seed >>= 1; - } - - if (psg->noise_freq >= incr) - psg->noise_count -= psg->noise_freq; - else - psg->noise_count = 0; - } - noise = psg->noise_seed & 1; - - /* Tone */ - for (i = 0; i < 3; i++) - { - psg->count[i] += incr; - if (psg->count[i] >= psg->freq[i]) - { - psg->edge[i] = !psg->edge[i]; - - if (psg->freq[i] >= incr) - psg->count[i] -= psg->freq[i]; - else - psg->count[i] = 0; - } - - if (0 < psg->freq_limit && psg->freq[i] <= psg->freq_limit) - { - /* Mute the channel if the pitch is higher than the Nyquist frequency at the current sample rate, - * to prevent aliased or broken tones from being generated. Of course, this logic doesn't exist - * on the actual chip, but practically all tones higher than the Nyquist frequency are usually - * removed by a low-pass circuit somewhere, so we here halt the output. */ - continue; - } - - if (psg->mask & PSG_MASK_CH(i)) - { - psg->ch_out[i] = 0; - continue; - } - - if ((psg->tmask[i]||psg->edge[i]) && (psg->nmask[i]||noise)) - { - if (!(psg->volume[i] & 32)) - psg->ch_out[i] = (psg->voltbl[psg->volume[i] & 31] << 4); - else - psg->ch_out[i] = (psg->voltbl[psg->env_ptr] << 4); - } - else - { - psg->ch_out[i] = 0; - } - } -} - -static INLINE int16_t -mix_output(PSG *psg) -{ - return (int16_t)(psg->ch_out[0] + psg->ch_out[1] + psg->ch_out[2]); -} - -int16_t -PSG_calc (PSG * psg) -{ - if (!psg->quality) - { - update_output(psg); - psg->out = mix_output(psg); - } - else - { - /* Simple rate converter (See README for detail). */ - while (psg->realstep > psg->psgtime) - { - psg->psgtime += psg->psgstep; - update_output(psg); - psg->out += mix_output(psg); - psg->out >>= 1; - } - psg->psgtime -= psg->realstep; - } - return psg->out; -} - -void -PSG_writeReg (PSG * psg, uint32_t reg, uint32_t val) -{ - int c; - - if (reg > 15) return; - - val &= regmsk[reg]; - - psg->reg[reg] = (uint8_t) val; - - switch (reg) - { - case 0: - case 2: - case 4: - case 1: - case 3: - case 5: - c = reg >> 1; - psg->freq[c] = ((psg->reg[c * 2 + 1] & 15) << 8) + psg->reg[c * 2]; - break; - - case 6: - psg->noise_freq = val & 31; - break; - - case 7: - psg->tmask[0] = (val & 1); - psg->tmask[1] = (val & 2); - psg->tmask[2] = (val & 4); - psg->nmask[0] = (val & 8); - psg->nmask[1] = (val & 16); - psg->nmask[2] = (val & 32); - break; - - case 8: - case 9: - case 10: - psg->volume[reg - 8] = val << 1; - break; - - case 11: - case 12: - psg->env_freq = (psg->reg[12] << 8) + psg->reg[11]; - break; - - case 13: - psg->env_continue = (val >> 3) & 1; - psg->env_attack = (val >> 2) & 1; - psg->env_alternate = (val >> 1) & 1; - psg->env_hold = val & 1; - psg->env_face = psg->env_attack; - psg->env_pause = 0; - psg->env_ptr = psg->env_face ? 0 : 0x1f; - break; - - case 14: - case 15: - default: - break; - } - - return; -} \ No newline at end of file diff --git a/src/mappers/sound/emu2149.h b/src/mappers/sound/emu2149.h deleted file mode 100644 index 96daeeb92..000000000 --- a/src/mappers/sound/emu2149.h +++ /dev/null @@ -1,94 +0,0 @@ -/* emu2149.h */ -#ifndef _EMU2149_H_ -#define _EMU2149_H_ - -#include - -#define PSG_MASK_CH(x) (1<<(x)) - -#ifdef __cplusplus -extern "C" -{ -#endif - - typedef struct __PSG - { - - /* Volume Table */ - uint32_t *voltbl; - - uint8_t reg[0x20]; - int32_t out; - - uint32_t clk, rate, base_incr; - uint8_t quality; - uint8_t clk_div; - - uint16_t count[3]; - uint8_t volume[3]; - uint16_t freq[3]; - uint8_t edge[3]; - uint8_t tmask[3]; - uint8_t nmask[3]; - uint32_t mask; - - uint32_t base_count; - - uint8_t env_ptr; - uint8_t env_face; - - uint8_t env_continue; - uint8_t env_attack; - uint8_t env_alternate; - uint8_t env_hold; - uint8_t env_pause; - - uint16_t env_freq; - uint32_t env_count; - - uint32_t noise_seed; - uint8_t noise_scaler; - uint8_t noise_count; - uint8_t noise_freq; - - /* rate converter */ - uint32_t realstep; - uint32_t psgtime; - uint32_t psgstep; - - uint32_t freq_limit; - - /* I/O Ctrl */ - uint8_t adr; - - /* output of channels */ - int16_t ch_out[3]; - - } PSG; - - void PSG_setQuality (PSG * psg, uint8_t q); - void PSG_setClock(PSG *psg, uint32_t clk); - void PSG_setClockDivider(PSG *psg, uint8_t enable); - void PSG_setRate (PSG * psg, uint32_t rate); - PSG *PSG_new (uint32_t clk, uint32_t rate); - void PSG_reset (PSG *); - void PSG_delete (PSG *); - void PSG_writeReg (PSG *, uint32_t reg, uint32_t val); - void PSG_writeIO (PSG * psg, uint32_t adr, uint32_t val); - uint8_t PSG_readReg (PSG * psg, uint32_t reg); - uint8_t PSG_readIO (PSG * psg); - int16_t PSG_calc (PSG *); - void PSG_setVolumeMode (PSG * psg, int type); - uint32_t PSG_setMask (PSG *, uint32_t mask); - uint32_t PSG_toggleMask (PSG *, uint32_t mask); - -#ifdef __cplusplus -} -#endif - -/* deprecated interfaces */ -#define PSG_set_quality PSG_setQuality -#define PSG_set_rate PSG_setRate -#define PSG_set_clock PSG_setClock - -#endif diff --git a/src/mappers/sound/emu2413.c b/src/mappers/sound/emu2413.c deleted file mode 100644 index 447e27d5d..000000000 --- a/src/mappers/sound/emu2413.c +++ /dev/null @@ -1,1507 +0,0 @@ -/** - * emu2413 v1.5.9 - * https://github.com/digital-sound-antiques/emu2413 - * Copyright (C) 2020 Mitsutaka Okazaki - * - * This source refers to the following documents. The author would like to thank all the authors who have - * contributed to the writing of them. - * - [YM2413 notes](http://www.smspower.org/Development/YM2413) by andete - * - ymf262.c by Jarek Burczynski - * - [VRC7 presets](https://siliconpr0n.org/archive/doku.php?id=vendor:yamaha:opl2#opll_vrc7_patch_format) by Nuke.YKT - * - YMF281B presets by Chabin - */ -#include "emu2413.h" -#include -#include -#include -#include - -#ifndef INLINE -#if defined(_MSC_VER) -#define INLINE __inline -#elif defined(__GNUC__) -#define INLINE __inline__ -#else -#define INLINE inline -#endif -#endif - -#define _PI_ 3.14159265358979323846264338327950288 - -#define OPLL_TONE_NUM 3 -/* clang-format off */ -static uint8_t default_inst[OPLL_TONE_NUM][(16 + 3) * 8] = {{ -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0: User */ -0x71,0x61,0x1e,0x17,0xd0,0x78,0x00,0x17, /* 1: Violin */ -0x13,0x41,0x1a,0x0d,0xd8,0xf7,0x23,0x13, /* 2: Guitar */ -0x13,0x01,0x99,0x00,0xf2,0xc4,0x21,0x23, /* 3: Piano */ -0x11,0x61,0x0e,0x07,0x8d,0x64,0x70,0x27, /* 4: Flute */ -0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28, /* 5: Clarinet */ -0x31,0x22,0x16,0x05,0xe0,0x71,0x00,0x18, /* 6: Oboe */ -0x21,0x61,0x1d,0x07,0x82,0x81,0x11,0x07, /* 7: Trumpet */ -0x33,0x21,0x2d,0x13,0xb0,0x70,0x00,0x07, /* 8: Organ */ -0x61,0x61,0x1b,0x06,0x64,0x65,0x10,0x17, /* 9: Horn */ -0x41,0x61,0x0b,0x18,0x85,0xf0,0x81,0x07, /* A: Synthesizer */ -0x33,0x01,0x83,0x11,0xea,0xef,0x10,0x04, /* B: Harpsichord */ -0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, /* C: Vibraphone */ -0x61,0x50,0x0c,0x05,0xd2,0xf5,0x40,0x42, /* D: Synthsizer Bass */ -0x01,0x01,0x55,0x03,0xe9,0x90,0x03,0x02, /* E: Acoustic Bass */ -0x41,0x41,0x89,0x03,0xf1,0xe4,0xc0,0x13, /* F: Electric Guitar */ -0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, /* R: Bass Drum (from VRC7) */ -0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68, /* R: High-Hat(M) / Snare Drum(C) (from VRC7) */ -0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, /* R: Tom-tom(M) / Top Cymbal(C) (from VRC7) */ -},{ -/* VRC7 presets from Nuke.YKT */ -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -0x03,0x21,0x05,0x06,0xe8,0x81,0x42,0x27, -0x13,0x41,0x14,0x0d,0xd8,0xf6,0x23,0x12, -0x11,0x11,0x08,0x08,0xfa,0xb2,0x20,0x12, -0x31,0x61,0x0c,0x07,0xa8,0x64,0x61,0x27, -0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28, -0x02,0x01,0x06,0x00,0xa3,0xe2,0xf4,0xf4, -0x21,0x61,0x1d,0x07,0x82,0x81,0x11,0x07, -0x23,0x21,0x22,0x17,0xa2,0x72,0x01,0x17, -0x35,0x11,0x25,0x00,0x40,0x73,0x72,0x01, -0xb5,0x01,0x0f,0x0F,0xa8,0xa5,0x51,0x02, -0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, -0x71,0x23,0x11,0x06,0x65,0x74,0x18,0x16, -0x01,0x02,0xd3,0x05,0xc9,0x95,0x03,0x02, -0x61,0x63,0x0c,0x00,0x94,0xC0,0x33,0xf6, -0x21,0x72,0x0d,0x00,0xc1,0xd5,0x56,0x06, -0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, -0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68, -0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, -},{ -/* YMF281B presets */ -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0: User */ -0x62,0x21,0x1a,0x07,0xf0,0x6f,0x00,0x16, /* 1: Electric Strings (form Chabin's patch) */ -0x40,0x10,0x45,0x00,0xf6,0x83,0x73,0x63, /* 2: Bow Wow (based on plgDavid's patch, KSL fixed) */ -0x13,0x01,0x99,0x00,0xf2,0xc3,0x21,0x23, /* 3: Electric Guitar (similar to YM2413 but different DR(C)) */ -0x01,0x61,0x0b,0x0f,0xf9,0x64,0x70,0x17, /* 4: Organ (based on Chabin, TL/DR fixed) */ -0x32,0x21,0x1e,0x06,0xe1,0x76,0x01,0x28, /* 5: Clarinet (identical to YM2413) */ -0x60,0x01,0x82,0x0e,0xf9,0x61,0x20,0x27, /* 6: Saxophone (based on plgDavid, PM/EG fixed) */ -0x21,0x61,0x1c,0x07,0x84,0x81,0x11,0x07, /* 7: Trumpet (similar to YM2413 but different TL/DR(M)) */ -0x37,0x32,0xc9,0x01,0x66,0x64,0x40,0x28, /* 8: Street Organ (from Chabin) */ -0x01,0x21,0x07,0x03,0xa5,0x71,0x51,0x07, /* 9: Synth Brass (based on Chabin, TL fixed) */ -0x06,0x01,0x5e,0x07,0xf3,0xf3,0xf6,0x13, /* A: Electric Piano (based on Chabin, DR/RR/KR fixed) */ -0x00,0x00,0x18,0x06,0xf5,0xf3,0x20,0x23, /* B: Bass (based on Chabin, EG fixed) */ -0x17,0xc1,0x24,0x07,0xf8,0xf8,0x22,0x12, /* C: Vibraphone (identical to YM2413) */ -0x35,0x64,0x00,0x00,0xff,0xf3,0x77,0xf5, /* D: Chimes (from plgDavid) */ -0x11,0x31,0x00,0x07,0xdd,0xf3,0xff,0xfb, /* E: Tom Tom II (from plgDavid) */ -0x3a,0x21,0x00,0x07,0x80,0x84,0x0f,0xf5, /* F: Noise (based on plgDavid, AR fixed) */ -0x01,0x01,0x18,0x0f,0xdf,0xf8,0x6a,0x6d, /* R: Bass Drum (identical to YM2413) */ -0x01,0x01,0x00,0x00,0xc8,0xd8,0xa7,0x68, /* R: High-Hat(M) / Snare Drum(C) (identical to YM2413) */ -0x05,0x01,0x00,0x00,0xf8,0xaa,0x59,0x55, /* R: Tom-tom(M) / Top Cymbal(C) (identical to YM2413) */ -}}; -/* clang-format on */ - -/* phase increment counter */ -#define DP_BITS 19 -#define DP_WIDTH (1 << DP_BITS) -#define DP_BASE_BITS (DP_BITS - PG_BITS) - -/* dynamic range of envelope output */ -#define EG_STEP 0.375 -#define EG_BITS 7 -#define EG_MUTE ((1 << EG_BITS) - 1) -#define EG_MAX (EG_MUTE - 4) - -/* dynamic range of total level */ -#define TL_STEP 0.75 -#define TL_BITS 6 - -/* dynamic range of sustine level */ -#define SL_STEP 3.0 -#define SL_BITS 4 - -/* damper speed before key-on. key-scale affects. */ -#define DAMPER_RATE 12 - -#define TL2EG(d) ((d) << 1) - -/* sine table */ -#define PG_BITS 10 /* 2^10 = 1024 length sine table */ -#define PG_WIDTH (1 << PG_BITS) - -/* clang-format off */ -/* exp_table[x] = round((exp2((double)x / 256.0) - 1) * 1024) */ -static uint16_t exp_table[256] = { -0, 3, 6, 8, 11, 14, 17, 20, 22, 25, 28, 31, 34, 37, 40, 42, -45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, -93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 130, 133, 136, 139, -142, 145, 148, 152, 155, 158, 161, 164, 168, 171, 174, 177, 181, 184, 187, 190, -194, 197, 200, 204, 207, 210, 214, 217, 220, 224, 227, 231, 234, 237, 241, 244, -248, 251, 255, 258, 262, 265, 268, 272, 276, 279, 283, 286, 290, 293, 297, 300, -304, 308, 311, 315, 318, 322, 326, 329, 333, 337, 340, 344, 348, 352, 355, 359, -363, 367, 370, 374, 378, 382, 385, 389, 393, 397, 401, 405, 409, 412, 416, 420, -424, 428, 432, 436, 440, 444, 448, 452, 456, 460, 464, 468, 472, 476, 480, 484, -488, 492, 496, 501, 505, 509, 513, 517, 521, 526, 530, 534, 538, 542, 547, 551, -555, 560, 564, 568, 572, 577, 581, 585, 590, 594, 599, 603, 607, 612, 616, 621, -625, 630, 634, 639, 643, 648, 652, 657, 661, 666, 670, 675, 680, 684, 689, 693, -698, 703, 708, 712, 717, 722, 726, 731, 736, 741, 745, 750, 755, 760, 765, 770, -774, 779, 784, 789, 794, 799, 804, 809, 814, 819, 824, 829, 834, 839, 844, 849, -854, 859, 864, 869, 874, 880, 885, 890, 895, 900, 906, 911, 916, 921, 927, 932, -937, 942, 948, 953, 959, 964, 969, 975, 980, 986, 991, 996, 1002, 1007, 1013, 1018 -}; -/* fullsin_table[x] = round(-log2(sin((x + 0.5) * PI / (PG_WIDTH / 4) / 2)) * 256) */ -static uint16_t fullsin_table[PG_WIDTH] = { -2137, 1731, 1543, 1419, 1326, 1252, 1190, 1137, 1091, 1050, 1013, 979, 949, 920, 894, 869, -846, 825, 804, 785, 767, 749, 732, 717, 701, 687, 672, 659, 646, 633, 621, 609, -598, 587, 576, 566, 556, 546, 536, 527, 518, 509, 501, 492, 484, 476, 468, 461, -453, 446, 439, 432, 425, 418, 411, 405, 399, 392, 386, 380, 375, 369, 363, 358, -352, 347, 341, 336, 331, 326, 321, 316, 311, 307, 302, 297, 293, 289, 284, 280, -276, 271, 267, 263, 259, 255, 251, 248, 244, 240, 236, 233, 229, 226, 222, 219, -215, 212, 209, 205, 202, 199, 196, 193, 190, 187, 184, 181, 178, 175, 172, 169, -167, 164, 161, 159, 156, 153, 151, 148, 146, 143, 141, 138, 136, 134, 131, 129, -127, 125, 122, 120, 118, 116, 114, 112, 110, 108, 106, 104, 102, 100, 98, 96, -94, 92, 91, 89, 87, 85, 83, 82, 80, 78, 77, 75, 74, 72, 70, 69, -67, 66, 64, 63, 62, 60, 59, 57, 56, 55, 53, 52, 51, 49, 48, 47, -46, 45, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, -29, 28, 27, 26, 25, 24, 23, 23, 22, 21, 20, 20, 19, 18, 17, 17, -16, 15, 15, 14, 13, 13, 12, 12, 11, 10, 10, 9, 9, 8, 8, 7, -7, 7, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, -2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -}; -/* clang-format on */ - -static uint16_t halfsin_table[PG_WIDTH]; -static uint16_t *wave_table_map[2] = {fullsin_table, halfsin_table}; - -/* pitch modulator */ -/* offset to fnum, rough approximation of 14 cents depth. */ -static int8_t pm_table[8][8] = { - {0, 0, 0, 0, 0, 0, 0, 0}, /* fnum = 000xxxxxx */ - {0, 0, 1, 0, 0, 0, -1, 0}, /* fnum = 001xxxxxx */ - {0, 1, 2, 1, 0, -1, -2, -1}, /* fnum = 010xxxxxx */ - {0, 1, 3, 1, 0, -1, -3, -1}, /* fnum = 011xxxxxx */ - {0, 2, 4, 2, 0, -2, -4, -2}, /* fnum = 100xxxxxx */ - {0, 2, 5, 2, 0, -2, -5, -2}, /* fnum = 101xxxxxx */ - {0, 3, 6, 3, 0, -3, -6, -3}, /* fnum = 110xxxxxx */ - {0, 3, 7, 3, 0, -3, -7, -3}, /* fnum = 111xxxxxx */ -}; - -/* amplitude lfo table */ -/* The following envelop pattern is verified on real YM2413. */ -/* each element repeates 64 cycles */ -static uint8_t am_table[210] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* */ - 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* */ - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, /* */ - 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, /* */ - 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, /* */ - 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, /* */ - 12, 12, 12, 12, 12, 12, 12, 12, /* */ - 13, 13, 13, /* */ - 12, 12, 12, 12, 12, 12, 12, 12, /* */ - 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, /* */ - 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, /* */ - 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, /* */ - 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* */ - 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, /* */ - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 -}; - -/* envelope decay increment step table */ -/* based on andete's research */ -static uint8_t eg_step_tables[4][8] = { - {0, 1, 0, 1, 0, 1, 0, 1}, - {0, 1, 0, 1, 1, 1, 0, 1}, - {0, 1, 1, 1, 0, 1, 1, 1}, - {0, 1, 1, 1, 1, 1, 1, 1}, -}; - -enum __OPLL_EG_STATE { ATTACK, DECAY, SUSTAIN, RELEASE, DAMP, UNKNOWN }; - -static uint32_t ml_table[16] = {1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, - 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2}; - -#define dB2(x) ((x)*2) -static double kl_table[16] = {dB2(0.000), dB2(9.000), dB2(12.000), dB2(13.875), dB2(15.000), dB2(16.125), - dB2(16.875), dB2(17.625), dB2(18.000), dB2(18.750), dB2(19.125), dB2(19.500), - dB2(19.875), dB2(20.250), dB2(20.625), dB2(21.000)}; - -static uint32_t tll_table[8 * 16][1 << TL_BITS][4]; -static int32_t rks_table[8 * 2][2]; - -static OPLL_PATCH null_patch = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -static OPLL_PATCH default_patch[OPLL_TONE_NUM][(16 + 3) * 2]; - -/* don't forget min/max is defined as a macro in stdlib.h of Visual C. */ -#ifndef min -static INLINE int min(int i, int j) { return (i < j) ? i : j; } -#endif -#ifndef max -static INLINE int max(int i, int j) { return (i > j) ? i : j; } -#endif - -/*************************************************** - - Internal Sample Rate Converter - -****************************************************/ -/* Note: to disable internal rate converter, set clock/72 to output sampling rate. */ - -/* - * LW is truncate length of sinc(x) calculation. - * Lower LW is faster, higher LW results better quality. - * LW must be a non-zero positive even number, no upper limit. - * LW=16 or greater is recommended when upsampling. - * LW=8 is practically okay for downsampling. - */ -#define LW 16 - -/* resolution of sinc(x) table. sinc(x) where 0.0<=x<1.0 corresponds to sinc_table[0...SINC_RESO-1] */ -#define SINC_RESO 256 -#define SINC_AMP_BITS 12 - -/* double hamming(double x) { return 0.54 - 0.46 * cos(2 * PI * x); } */ -static double blackman(double x) { return 0.42 - 0.5 * cos(2 * _PI_ * x) + 0.08 * cos(4 * _PI_ * x); } -static double sinc(double x) { return (x == 0.0 ? 1.0 : sin(_PI_ * x) / (_PI_ * x)); } -static double windowed_sinc(double x) { return blackman(0.5 + 0.5 * x / (LW / 2)) * sinc(x); } - -/* f_inp: input frequency. f_out: output frequencey, ch: number of channels */ -OPLL_RateConv *OPLL_RateConv_new(double f_inp, double f_out, int ch) { - OPLL_RateConv *conv = malloc(sizeof(OPLL_RateConv)); - int i; - - conv->ch = ch; - conv->f_ratio = f_inp / f_out; - conv->buf = malloc(sizeof(void *) * ch); - for (i = 0; i < ch; i++) { - conv->buf[i] = malloc(sizeof(conv->buf[0][0]) * LW); - } - - /* create sinc_table for positive 0 <= x < LW/2 */ - conv->sinc_table = malloc(sizeof(conv->sinc_table[0]) * SINC_RESO * LW / 2); - for (i = 0; i < SINC_RESO * LW / 2; i++) { - const double x = (double)i / SINC_RESO; - if (f_out < f_inp) { - /* for downsampling */ - conv->sinc_table[i] = (int16_t)((1 << SINC_AMP_BITS) * windowed_sinc(x / conv->f_ratio) / conv->f_ratio); - } else { - /* for upsampling */ - conv->sinc_table[i] = (int16_t)((1 << SINC_AMP_BITS) * windowed_sinc(x)); - } - } - - return conv; -} - -static INLINE int16_t lookup_sinc_table(int16_t *table, double x) { - int16_t index = (int16_t)(x * SINC_RESO); - if (index < 0) - index = -index; - return table[min(SINC_RESO * LW / 2 - 1, index)]; -} - -void OPLL_RateConv_reset(OPLL_RateConv *conv) { - int i; - conv->timer = 0; - for (i = 0; i < conv->ch; i++) { - memset(conv->buf[i], 0, sizeof(conv->buf[i][0]) * LW); - } -} - -/* put original data to this converter at f_inp. */ -void OPLL_RateConv_putData(OPLL_RateConv *conv, int ch, int16_t data) { - int16_t *buf = conv->buf[ch]; - int i; - for (i = 0; i < LW - 1; i++) { - buf[i] = buf[i + 1]; - } - buf[LW - 1] = data; -} - -/* get resampled data from this converter at f_out. */ -/* this function must be called f_out / f_inp times per one putData call. */ -int16_t OPLL_RateConv_getData(OPLL_RateConv *conv, int ch) { - int16_t *buf = conv->buf[ch]; - int32_t sum = 0; - int k; - double dn; - conv->timer += conv->f_ratio; - dn = conv->timer - floor(conv->timer); - conv->timer = dn; - - for (k = 0; k < LW; k++) { - double x = ((double)k - (LW / 2 - 1)) - dn; - sum += buf[k] * lookup_sinc_table(conv->sinc_table, x); - } - return sum >> SINC_AMP_BITS; -} - -void OPLL_RateConv_delete(OPLL_RateConv *conv) { - int i; - for (i = 0; i < conv->ch; i++) { - free(conv->buf[i]); - } - free(conv->buf); - free(conv->sinc_table); - free(conv); -} - -/*************************************************** - - Create tables - -****************************************************/ - -static void makeSinTable(void) { - int x; - - for (x = 0; x < PG_WIDTH / 4; x++) { - fullsin_table[PG_WIDTH / 4 + x] = fullsin_table[PG_WIDTH / 4 - x - 1]; - } - - for (x = 0; x < PG_WIDTH / 2; x++) { - fullsin_table[PG_WIDTH / 2 + x] = 0x8000 | fullsin_table[x]; - } - - for (x = 0; x < PG_WIDTH / 2; x++) - halfsin_table[x] = fullsin_table[x]; - - for (x = PG_WIDTH / 2; x < PG_WIDTH; x++) - halfsin_table[x] = 0xfff; -} - -static void makeTllTable(void) { - - int32_t tmp; - int32_t fnum, block, TL, KL; - - for (fnum = 0; fnum < 16; fnum++) { - for (block = 0; block < 8; block++) { - for (TL = 0; TL < 64; TL++) { - for (KL = 0; KL < 4; KL++) { - if (KL == 0) { - tll_table[(block << 4) | fnum][TL][KL] = TL2EG(TL); - } else { - tmp = (int32_t)(kl_table[fnum] - dB2(3.000) * (7 - block)); - if (tmp <= 0) - tll_table[(block << 4) | fnum][TL][KL] = TL2EG(TL); - else - tll_table[(block << 4) | fnum][TL][KL] = (uint32_t)((tmp >> (3 - KL)) / EG_STEP) + TL2EG(TL); - } - } - } - } - } -} - -static void makeRksTable(void) { - int fnum8, block; - for (fnum8 = 0; fnum8 < 2; fnum8++) - for (block = 0; block < 8; block++) { - rks_table[(block << 1) | fnum8][1] = (block << 1) + fnum8; - rks_table[(block << 1) | fnum8][0] = block >> 1; - } -} - -static void makeDefaultPatch(void) { - int i, j; - for (i = 0; i < OPLL_TONE_NUM; i++) - for (j = 0; j < 19; j++) - OPLL_getDefaultPatch(i, j, &default_patch[i][j * 2]); -} - -static uint8_t table_initialized = 0; - -static void initializeTables(void) { - makeTllTable(); - makeRksTable(); - makeSinTable(); - makeDefaultPatch(); - table_initialized = 1; -} - -/********************************************************* - - Synthesizing - -*********************************************************/ -#define SLOT_BD1 12 -#define SLOT_BD2 13 -#define SLOT_HH 14 -#define SLOT_SD 15 -#define SLOT_TOM 16 -#define SLOT_CYM 17 - -/* utility macros */ -#define MOD(o, x) (&(o)->slot[(x) << 1]) -#define CAR(o, x) (&(o)->slot[((x) << 1) | 1]) -#define BIT(s, b) (((s) >> (b)) & 1) - -#if OPLL_DEBUG -static void _debug_print_patch(OPLL_SLOT *slot) { - OPLL_PATCH *p = slot->patch; - printf("[slot#%d am:%d pm:%d eg:%d kr:%d ml:%d kl:%d tl:%d ws:%d fb:%d A:%d D:%d S:%d R:%d]\n", slot->number, // - p->AM, p->PM, p->EG, p->KR, p->ML, // - p->KL, p->TL, p->WS, p->FB, // - p->AR, p->DR, p->SL, p->RR); -} - -static char *_debug_eg_state_name(OPLL_SLOT *slot) { - switch (slot->eg_state) { - case ATTACK: - return "attack"; - case DECAY: - return "decay"; - case SUSTAIN: - return "sustain"; - case RELEASE: - return "release"; - case DAMP: - return "damp"; - default: - return "unknown"; - } -} - -static INLINE void _debug_print_slot_info(OPLL_SLOT *slot) { - char *name = _debug_eg_state_name(slot); - printf("[slot#%d state:%s fnum:%03x rate:%d-%d]\n", slot->number, name, slot->blk_fnum, slot->eg_rate_h, - slot->eg_rate_l); - _debug_print_patch(slot); - fflush(stdout); -} -#endif - -static INLINE int get_parameter_rate(OPLL_SLOT *slot) { - - if ((slot->type & 1) == 0 && slot->key_flag == 0) { - return 0; - } - - switch (slot->eg_state) { - case ATTACK: - return slot->patch->AR; - case DECAY: - return slot->patch->DR; - case SUSTAIN: - return slot->patch->EG ? 0 : slot->patch->RR; - case RELEASE: - if (slot->sus_flag) { - return 5; - } else if (slot->patch->EG) { - return slot->patch->RR; - } else { - return 7; - } - case DAMP: - return DAMPER_RATE; - default: - return 0; - } -} - -enum SLOT_UPDATE_FLAG { - UPDATE_WS = 1, - UPDATE_TLL = 2, - UPDATE_RKS = 4, - UPDATE_EG = 8, - UPDATE_ALL = 255 -}; - -static INLINE void request_update(OPLL_SLOT *slot, int flag) { slot->update_requests |= flag; } - -static void commit_slot_update(OPLL_SLOT *slot) { - -#if OPLL_DEBUG - if (slot->last_eg_state != slot->eg_state) { - _debug_print_slot_info(slot); - slot->last_eg_state = slot->eg_state; - } -#endif - - if (slot->update_requests & UPDATE_WS) { - slot->wave_table = wave_table_map[slot->patch->WS]; - } - - if (slot->update_requests & UPDATE_TLL) { - if ((slot->type & 1) == 0) { - slot->tll = tll_table[slot->blk_fnum >> 5][slot->patch->TL][slot->patch->KL]; - } else { - slot->tll = tll_table[slot->blk_fnum >> 5][slot->volume][slot->patch->KL]; - } - } - - if (slot->update_requests & UPDATE_RKS) { - slot->rks = rks_table[slot->blk_fnum >> 8][slot->patch->KR]; - } - - if (slot->update_requests & (UPDATE_RKS | UPDATE_EG)) { - int p_rate = get_parameter_rate(slot); - - if (p_rate == 0) { - slot->eg_shift = 0; - slot->eg_rate_h = 0; - slot->eg_rate_l = 0; - return; - } - - slot->eg_rate_h = min(15, p_rate + (slot->rks >> 2)); - slot->eg_rate_l = slot->rks & 3; - if (slot->eg_state == ATTACK) { - slot->eg_shift = (0 < slot->eg_rate_h && slot->eg_rate_h < 12) ? (13 - slot->eg_rate_h) : 0; - } else { - slot->eg_shift = (slot->eg_rate_h < 13) ? (13 - slot->eg_rate_h) : 0; - } - } - - slot->update_requests = 0; -} - -static void reset_slot(OPLL_SLOT *slot, int number) { - slot->number = number; - slot->type = number % 2; - slot->pg_keep = 0; - slot->wave_table = wave_table_map[0]; - slot->pg_phase = 0; - slot->output[0] = 0; - slot->output[1] = 0; - slot->eg_state = RELEASE; - slot->eg_shift = 0; - slot->rks = 0; - slot->tll = 0; - slot->key_flag = 0; - slot->sus_flag = 0; - slot->blk_fnum = 0; - slot->blk = 0; - slot->fnum = 0; - slot->volume = 0; - slot->pg_out = 0; - slot->eg_out = EG_MUTE; - slot->patch = &null_patch; -} - -static INLINE void slotOn(OPLL *opll, int i) { - OPLL_SLOT *slot = &opll->slot[i]; - slot->key_flag = 1; - slot->eg_state = DAMP; - request_update(slot, UPDATE_EG); -} - -static INLINE void slotOff(OPLL *opll, int i) { - OPLL_SLOT *slot = &opll->slot[i]; - slot->key_flag = 0; - if (slot->type & 1) { - slot->eg_state = RELEASE; - request_update(slot, UPDATE_EG); - } -} - -static INLINE void update_key_status(OPLL *opll) { - const uint8_t r14 = opll->reg[0x0e]; - const uint8_t rhythm_mode = BIT(r14, 5); - uint32_t new_slot_key_status = 0; - uint32_t updated_status; - int ch; - - for (ch = 0; ch < 9; ch++) - if (opll->reg[0x20 + ch] & 0x10) - new_slot_key_status |= 3 << (ch * 2); - - if (rhythm_mode) { - if (r14 & 0x10) - new_slot_key_status |= 3 << SLOT_BD1; - - if (r14 & 0x01) - new_slot_key_status |= 1 << SLOT_HH; - - if (r14 & 0x08) - new_slot_key_status |= 1 << SLOT_SD; - - if (r14 & 0x04) - new_slot_key_status |= 1 << SLOT_TOM; - - if (r14 & 0x02) - new_slot_key_status |= 1 << SLOT_CYM; - } - - updated_status = opll->slot_key_status ^ new_slot_key_status; - - if (updated_status) { - int i; - for (i = 0; i < 18; i++) - if (BIT(updated_status, i)) { - if (BIT(new_slot_key_status, i)) { - slotOn(opll, i); - } else { - slotOff(opll, i); - } - } - } - - opll->slot_key_status = new_slot_key_status; -} - -static INLINE void set_patch(OPLL *opll, int32_t ch, int32_t num) { - opll->patch_number[ch] = num; - MOD(opll, ch)->patch = &opll->patch[num * 2 + 0]; - CAR(opll, ch)->patch = &opll->patch[num * 2 + 1]; - request_update(MOD(opll, ch), UPDATE_ALL); - request_update(CAR(opll, ch), UPDATE_ALL); -} - -static INLINE void set_sus_flag(OPLL *opll, int ch, int flag) { - CAR(opll, ch)->sus_flag = flag; - request_update(CAR(opll, ch), UPDATE_EG); - if (MOD(opll, ch)->type & 1) { - MOD(opll, ch)->sus_flag = flag; - request_update(MOD(opll, ch), UPDATE_EG); - } -} - -/* set volume ( volume : 6bit, register value << 2 ) */ -static INLINE void set_volume(OPLL *opll, int ch, int volume) { - CAR(opll, ch)->volume = volume; - request_update(CAR(opll, ch), UPDATE_TLL); -} - -static INLINE void set_slot_volume(OPLL_SLOT *slot, int volume) { - slot->volume = volume; - request_update(slot, UPDATE_TLL); -} - -/* set f-Nnmber ( fnum : 9bit ) */ -static INLINE void set_fnumber(OPLL *opll, int ch, int fnum) { - OPLL_SLOT *car = CAR(opll, ch); - OPLL_SLOT *mod = MOD(opll, ch); - car->fnum = fnum; - car->blk_fnum = (car->blk_fnum & 0xe00) | (fnum & 0x1ff); - mod->fnum = fnum; - mod->blk_fnum = (mod->blk_fnum & 0xe00) | (fnum & 0x1ff); - request_update(car, UPDATE_EG | UPDATE_RKS | UPDATE_TLL); - request_update(mod, UPDATE_EG | UPDATE_RKS | UPDATE_TLL); -} - -/* set block data (blk : 3bit ) */ -static INLINE void set_block(OPLL *opll, int ch, int blk) { - OPLL_SLOT *car = CAR(opll, ch); - OPLL_SLOT *mod = MOD(opll, ch); - car->blk = blk; - car->blk_fnum = ((blk & 7) << 9) | (car->blk_fnum & 0x1ff); - mod->blk = blk; - mod->blk_fnum = ((blk & 7) << 9) | (mod->blk_fnum & 0x1ff); - request_update(car, UPDATE_EG | UPDATE_RKS | UPDATE_TLL); - request_update(mod, UPDATE_EG | UPDATE_RKS | UPDATE_TLL); -} - -static INLINE void update_rhythm_mode(OPLL *opll) { - const uint8_t new_rhythm_mode = (opll->reg[0x0e] >> 5) & 1; - - if (opll->rhythm_mode != new_rhythm_mode) { - - if (new_rhythm_mode) { - opll->slot[SLOT_HH].type = 3; - opll->slot[SLOT_HH].pg_keep = 1; - opll->slot[SLOT_SD].type = 3; - opll->slot[SLOT_TOM].type = 3; - opll->slot[SLOT_CYM].type = 3; - opll->slot[SLOT_CYM].pg_keep = 1; - set_patch(opll, 6, 16); - set_patch(opll, 7, 17); - set_patch(opll, 8, 18); - set_slot_volume(&opll->slot[SLOT_HH], ((opll->reg[0x37] >> 4) & 15) << 2); - set_slot_volume(&opll->slot[SLOT_TOM], ((opll->reg[0x38] >> 4) & 15) << 2); - } else { - opll->slot[SLOT_HH].type = 0; - opll->slot[SLOT_HH].pg_keep = 0; - opll->slot[SLOT_SD].type = 1; - opll->slot[SLOT_TOM].type = 0; - opll->slot[SLOT_CYM].type = 1; - opll->slot[SLOT_CYM].pg_keep = 0; - set_patch(opll, 6, opll->reg[0x36] >> 4); - set_patch(opll, 7, opll->reg[0x37] >> 4); - set_patch(opll, 8, opll->reg[0x38] >> 4); - } - } - - opll->rhythm_mode = new_rhythm_mode; -} - -static void update_ampm(OPLL *opll) { - if (opll->test_flag & 2) { - opll->pm_phase = 0; - opll->am_phase = 0; - } else { - opll->pm_phase += (opll->test_flag & 8) ? 1024 : 1; - opll->am_phase += (opll->test_flag & 8) ? 64 : 1; - } - opll->lfo_am = am_table[(opll->am_phase >> 6) % sizeof(am_table)]; -} - -static void update_noise(OPLL *opll, int cycle) { - int i; - for (i = 0; i < cycle; i++) { - if (opll->noise & 1) { - opll->noise ^= 0x800200; - } - opll->noise >>= 1; - } -} - -static void update_short_noise(OPLL *opll) { - const uint32_t pg_hh = opll->slot[SLOT_HH].pg_out; - const uint32_t pg_cym = opll->slot[SLOT_CYM].pg_out; - - const uint8_t h_bit2 = BIT(pg_hh, PG_BITS - 8); - const uint8_t h_bit7 = BIT(pg_hh, PG_BITS - 3); - const uint8_t h_bit3 = BIT(pg_hh, PG_BITS - 7); - - const uint8_t c_bit3 = BIT(pg_cym, PG_BITS - 7); - const uint8_t c_bit5 = BIT(pg_cym, PG_BITS - 5); - - opll->short_noise = (h_bit2 ^ h_bit7) | (h_bit3 ^ c_bit5) | (c_bit3 ^ c_bit5); -} - -static INLINE void calc_phase(OPLL_SLOT *slot, int32_t pm_phase, uint8_t reset) { - const int8_t pm = slot->patch->PM ? pm_table[(slot->fnum >> 6) & 7][(pm_phase >> 10) & 7] : 0; - if (reset) { - slot->pg_phase = 0; - } - slot->pg_phase += (((slot->fnum & 0x1ff) * 2 + pm) * ml_table[slot->patch->ML]) << slot->blk >> 2; - slot->pg_phase &= (DP_WIDTH - 1); - slot->pg_out = slot->pg_phase >> DP_BASE_BITS; -} - -static INLINE uint8_t lookup_attack_step(OPLL_SLOT *slot, uint32_t counter) { - int index; - - switch (slot->eg_rate_h) { - case 12: - index = (counter & 0xc) >> 1; - return 4 - eg_step_tables[slot->eg_rate_l][index]; - case 13: - index = (counter & 0xc) >> 1; - return 3 - eg_step_tables[slot->eg_rate_l][index]; - case 14: - index = (counter & 0xc) >> 1; - return 2 - eg_step_tables[slot->eg_rate_l][index]; - case 0: - case 15: - return 0; - default: - index = counter >> slot->eg_shift; - return eg_step_tables[slot->eg_rate_l][index & 7] ? 4 : 0; - } -} - -static INLINE uint8_t lookup_decay_step(OPLL_SLOT *slot, uint32_t counter) { - int index; - - switch (slot->eg_rate_h) { - case 0: - return 0; - case 13: - index = ((counter & 0xc) >> 1) | (counter & 1); - return eg_step_tables[slot->eg_rate_l][index]; - case 14: - index = ((counter & 0xc) >> 1); - return eg_step_tables[slot->eg_rate_l][index] + 1; - case 15: - return 2; - default: - index = counter >> slot->eg_shift; - return eg_step_tables[slot->eg_rate_l][index & 7]; - } -} - -static INLINE void start_envelope(OPLL_SLOT *slot) { - if (min(15, slot->patch->AR + (slot->rks >> 2)) == 15) { - slot->eg_state = DECAY; - slot->eg_out = 0; - } else { - slot->eg_state = ATTACK; - } - request_update(slot, UPDATE_EG); -} - -static INLINE void calc_envelope(OPLL_SLOT *slot, OPLL_SLOT *buddy, uint16_t eg_counter, uint8_t test) { - - uint32_t mask = (1 << slot->eg_shift) - 1; - uint8_t s; - - if (slot->eg_state == ATTACK) { - if (0 < slot->eg_out && 0 < slot->eg_rate_h && (eg_counter & mask & ~3) == 0) { - s = lookup_attack_step(slot, eg_counter); - if (0 < s) { - slot->eg_out = max(0, ((int)slot->eg_out - (slot->eg_out >> s) - 1)); - } - } - } else { - if (slot->eg_rate_h > 0 && (eg_counter & mask) == 0) { - slot->eg_out = min(EG_MUTE, slot->eg_out + lookup_decay_step(slot, eg_counter)); - } - } - - switch (slot->eg_state) { - case DAMP: - /* DAMP to ATTACK transition is occured when the envelope reaches EG_MAX (max attenuation but it's not mute). - Do not forget to check (eg_counter & mask) == 0 to synchronize it with the progress of the envelope. */ - if (slot->eg_out >= EG_MAX && (eg_counter & mask) == 0) { - start_envelope(slot); - if (slot->type & 1) { - if (!slot->pg_keep) { - slot->pg_phase = 0; - } - if (buddy && !buddy->pg_keep) { - buddy->pg_phase = 0; - } - } - } - break; - - case ATTACK: - if (slot->eg_out == 0) { - slot->eg_state = DECAY; - request_update(slot, UPDATE_EG); - } - break; - - case DECAY: - /* DECAY to SUSTAIN transition must be checked at every cycle regardless of the conditions of the envelope rate and - counter. i.e. the transition is not synchronized with the progress of the envelope. */ - if ((slot->eg_out >> 3) == slot->patch->SL) { - slot->eg_state = SUSTAIN; - request_update(slot, UPDATE_EG); - } - break; - - case SUSTAIN: - case RELEASE: - default: - break; - } - - if (test) { - slot->eg_out = 0; - } -} - -static void update_slots(OPLL *opll) { - int i; - opll->eg_counter++; - - for (i = 0; i < 18; i++) { - OPLL_SLOT *slot = &opll->slot[i]; - OPLL_SLOT *buddy = NULL; - if (slot->type == 0) { - buddy = &opll->slot[i + 1]; - } - if (slot->type == 1) { - buddy = &opll->slot[i - 1]; - } - if (slot->update_requests) { - commit_slot_update(slot); - } - calc_envelope(slot, buddy, opll->eg_counter, opll->test_flag & 1); - calc_phase(slot, opll->pm_phase, opll->test_flag & 4); - } -} - -/* output: -4095...4095 */ -static INLINE int16_t lookup_exp_table(uint16_t i) { - /* from andete's expression */ - int16_t t = (exp_table[(i & 0xff) ^ 0xff] + 1024); - int16_t res = t >> ((i & 0x7f00) >> 8); - return ((i & 0x8000) ? ~res : res) << 1; -} - -static INLINE int16_t to_linear(uint16_t h, OPLL_SLOT *slot, int16_t am) { - uint16_t att; - if (slot->eg_out > EG_MAX) - return 0; - - att = min(EG_MUTE, (slot->eg_out + slot->tll + am)) << 4; - return lookup_exp_table(h + att); -} - -static INLINE int16_t calc_slot_car(OPLL *opll, int ch, int16_t fm) { - OPLL_SLOT *slot = CAR(opll, ch); - - uint8_t am = slot->patch->AM ? opll->lfo_am : 0; - - slot->output[1] = slot->output[0]; - slot->output[0] = to_linear(slot->wave_table[(slot->pg_out + 2 * (fm >> 1)) & (PG_WIDTH - 1)], slot, am); - - return slot->output[0]; -} - -static INLINE int16_t calc_slot_mod(OPLL *opll, int ch) { - OPLL_SLOT *slot = MOD(opll, ch); - - int16_t fm = slot->patch->FB > 0 ? (slot->output[1] + slot->output[0]) >> (9 - slot->patch->FB) : 0; - uint8_t am = slot->patch->AM ? opll->lfo_am : 0; - - slot->output[1] = slot->output[0]; - slot->output[0] = to_linear(slot->wave_table[(slot->pg_out + fm) & (PG_WIDTH - 1)], slot, am); - - return slot->output[0]; -} - -static INLINE int16_t calc_slot_tom(OPLL *opll) { - OPLL_SLOT *slot = MOD(opll, 8); - - return to_linear(slot->wave_table[slot->pg_out], slot, 0); -} - -/* Specify phase offset directly based on 10-bit (1024-length) sine table */ -#define _PD(phase) ((PG_BITS < 10) ? (phase >> (10 - PG_BITS)) : (phase << (PG_BITS - 10))) - -static INLINE int16_t calc_slot_snare(OPLL *opll) { - OPLL_SLOT *slot = CAR(opll, 7); - - uint32_t phase; - - if (BIT(slot->pg_out, PG_BITS - 2)) - phase = (opll->noise & 1) ? _PD(0x300) : _PD(0x200); - else - phase = (opll->noise & 1) ? _PD(0x0) : _PD(0x100); - - return to_linear(slot->wave_table[phase], slot, 0); -} - -static INLINE int16_t calc_slot_cym(OPLL *opll) { - OPLL_SLOT *slot = CAR(opll, 8); - - uint32_t phase = opll->short_noise ? _PD(0x300) : _PD(0x100); - - return to_linear(slot->wave_table[phase], slot, 0); -} - -static INLINE int16_t calc_slot_hat(OPLL *opll) { - OPLL_SLOT *slot = MOD(opll, 7); - - uint32_t phase; - - if (opll->short_noise) - phase = (opll->noise & 1) ? _PD(0x2d0) : _PD(0x234); - else - phase = (opll->noise & 1) ? _PD(0x34) : _PD(0xd0); - - return to_linear(slot->wave_table[phase], slot, 0); -} - -#define _MO(x) (-(x) >> 1) -#define _RO(x) (x) - -static void update_output(OPLL *opll) { - int16_t *out; - int i; - - update_ampm(opll); - update_short_noise(opll); - update_slots(opll); - - out = opll->ch_out; - - /* CH1-6 */ - for (i = 0; i < 6; i++) { - if (!(opll->mask & OPLL_MASK_CH(i))) { - out[i] = _MO(calc_slot_car(opll, i, calc_slot_mod(opll, i))); - } - } - - /* CH7 */ - if (!opll->rhythm_mode) { - if (!(opll->mask & OPLL_MASK_CH(6))) { - out[6] = _MO(calc_slot_car(opll, 6, calc_slot_mod(opll, 6))); - } - } else { - if (!(opll->mask & OPLL_MASK_BD)) { - out[9] = _RO(calc_slot_car(opll, 6, calc_slot_mod(opll, 6))); - } - } - update_noise(opll, 14); - - /* CH8 */ - if (!opll->rhythm_mode) { - if (!(opll->mask & OPLL_MASK_CH(7))) { - out[7] = _MO(calc_slot_car(opll, 7, calc_slot_mod(opll, 7))); - } - } else { - if (!(opll->mask & OPLL_MASK_HH)) { - out[10] = _RO(calc_slot_hat(opll)); - } - if (!(opll->mask & OPLL_MASK_SD)) { - out[11] = _RO(calc_slot_snare(opll)); - } - } - update_noise(opll, 2); - - /* CH9 */ - if (!opll->rhythm_mode) { - if (!(opll->mask & OPLL_MASK_CH(8))) { - out[8] = _MO(calc_slot_car(opll, 8, calc_slot_mod(opll, 8))); - } - } else { - if (!(opll->mask & OPLL_MASK_TOM)) { - out[12] = _RO(calc_slot_tom(opll)); - } - if (!(opll->mask & OPLL_MASK_CYM)) { - out[13] = _RO(calc_slot_cym(opll)); - } - } - update_noise(opll, 2); -} - -INLINE static void mix_output(OPLL *opll) { - int16_t out = 0; - int i; - for (i = 0; i < 14; i++) { - out += opll->ch_out[i]; - } - if (opll->conv) { - OPLL_RateConv_putData(opll->conv, 0, out); - } else { - opll->mix_out[0] = out; - } -} - -INLINE static void mix_output_stereo(OPLL *opll) { - int16_t *out = opll->mix_out; - int i; - out[0] = out[1] = 0; - for (i = 0; i < 14; i++) { - if (opll->pan[i] & 2) - out[0] += (int16_t)(opll->ch_out[i] * opll->pan_fine[i][0]); - if (opll->pan[i] & 1) - out[1] += (int16_t)(opll->ch_out[i] * opll->pan_fine[i][1]); - } - if (opll->conv) { - OPLL_RateConv_putData(opll->conv, 0, out[0]); - OPLL_RateConv_putData(opll->conv, 1, out[1]); - } -} - -/*********************************************************** - - External Interfaces - -***********************************************************/ - -OPLL *OPLL_new(uint32_t clk, uint32_t rate) { - OPLL *opll; - int i; - - if (!table_initialized) { - initializeTables(); - } - - opll = (OPLL *)calloc(sizeof(OPLL), 1); - if (opll == NULL) - return NULL; - - for (i = 0; i < 19 * 2; i++) - memcpy(&opll->patch[i], &null_patch, sizeof(OPLL_PATCH)); - - opll->clk = clk; - opll->rate = rate; - opll->mask = 0; - opll->conv = NULL; - opll->mix_out[0] = 0; - opll->mix_out[1] = 0; - - OPLL_reset(opll); - OPLL_setChipType(opll, 0); - OPLL_resetPatch(opll, 0); - return opll; -} - -void OPLL_delete(OPLL *opll) { - if (opll->conv) { - OPLL_RateConv_delete(opll->conv); - opll->conv = NULL; - } - free(opll); -} - -static void reset_rate_conversion_params(OPLL *opll) { - const double f_out = opll->rate; - const double f_inp = opll->clk / 72.0; - - opll->out_time = 0; - opll->out_step = f_inp; - opll->inp_step = f_out; - - if (opll->conv) { - OPLL_RateConv_delete(opll->conv); - opll->conv = NULL; - } - - if (floor(f_inp) != f_out && floor(f_inp + 0.5) != f_out) { - opll->conv = OPLL_RateConv_new(f_inp, f_out, 2); - } - - if (opll->conv) { - OPLL_RateConv_reset(opll->conv); - } -} - -void OPLL_reset(OPLL *opll) { - int i; - - if (!opll) - return; - - opll->adr = 0; - - opll->pm_phase = 0; - opll->am_phase = 0; - - opll->noise = 0x1; - opll->mask = 0; - - opll->rhythm_mode = 0; - opll->slot_key_status = 0; - opll->eg_counter = 0; - - reset_rate_conversion_params(opll); - - for (i = 0; i < 18; i++) - reset_slot(&opll->slot[i], i); - - for (i = 0; i < 9; i++) { - set_patch(opll, i, 0); - } - - for (i = 0; i < 0x40; i++) - OPLL_writeReg(opll, i, 0); - - for (i = 0; i < 15; i++) { - opll->pan[i] = 3; - opll->pan_fine[i][1] = opll->pan_fine[i][0] = 1.0f; - } - - for (i = 0; i < 14; i++) { - opll->ch_out[i] = 0; - } -} - -void OPLL_forceRefresh(OPLL *opll) { - int i; - - if (opll == NULL) - return; - - for (i = 0; i < 9; i++) { - set_patch(opll, i, opll->patch_number[i]); - } - - for (i = 0; i < 18; i++) { - request_update(&opll->slot[i], UPDATE_ALL); - } -} - -void OPLL_setRate(OPLL *opll, uint32_t rate) { - opll->rate = rate; - reset_rate_conversion_params(opll); -} - -void OPLL_setQuality(OPLL *opll, uint8_t q) {} - -void OPLL_setChipType(OPLL *opll, uint8_t type) { opll->chip_type = type; } - -void OPLL_writeReg(OPLL *opll, uint32_t reg, uint8_t data) { - int ch, i; - - if (reg >= 0x40) - return; - - /* mirror registers */ - if ((0x19 <= reg && reg <= 0x1f) || (0x29 <= reg && reg <= 0x2f) || (0x39 <= reg && reg <= 0x3f)) { - reg -= 9; - } - - opll->reg[reg] = (uint8_t)data; - - switch (reg) { - case 0x00: - opll->patch[0].AM = (data >> 7) & 1; - opll->patch[0].PM = (data >> 6) & 1; - opll->patch[0].EG = (data >> 5) & 1; - opll->patch[0].KR = (data >> 4) & 1; - opll->patch[0].ML = (data)&15; - for (i = 0; i < 9; i++) { - if (opll->patch_number[i] == 0) { - request_update(MOD(opll, i), UPDATE_RKS | UPDATE_EG); - } - } - break; - - case 0x01: - opll->patch[1].AM = (data >> 7) & 1; - opll->patch[1].PM = (data >> 6) & 1; - opll->patch[1].EG = (data >> 5) & 1; - opll->patch[1].KR = (data >> 4) & 1; - opll->patch[1].ML = (data)&15; - for (i = 0; i < 9; i++) { - if (opll->patch_number[i] == 0) { - request_update(CAR(opll, i), UPDATE_RKS | UPDATE_EG); - } - } - break; - - case 0x02: - opll->patch[0].KL = (data >> 6) & 3; - opll->patch[0].TL = (data)&63; - for (i = 0; i < 9; i++) { - if (opll->patch_number[i] == 0) { - request_update(MOD(opll, i), UPDATE_TLL); - } - } - break; - - case 0x03: - opll->patch[1].KL = (data >> 6) & 3; - opll->patch[1].WS = (data >> 4) & 1; - opll->patch[0].WS = (data >> 3) & 1; - opll->patch[0].FB = (data)&7; - for (i = 0; i < 9; i++) { - if (opll->patch_number[i] == 0) { - request_update(MOD(opll, i), UPDATE_WS); - request_update(CAR(opll, i), UPDATE_WS | UPDATE_TLL); - } - } - break; - - case 0x04: - opll->patch[0].AR = (data >> 4) & 15; - opll->patch[0].DR = (data)&15; - for (i = 0; i < 9; i++) { - if (opll->patch_number[i] == 0) { - request_update(MOD(opll, i), UPDATE_EG); - } - } - break; - - case 0x05: - opll->patch[1].AR = (data >> 4) & 15; - opll->patch[1].DR = (data)&15; - for (i = 0; i < 9; i++) { - if (opll->patch_number[i] == 0) { - request_update(CAR(opll, i), UPDATE_EG); - } - } - break; - - case 0x06: - opll->patch[0].SL = (data >> 4) & 15; - opll->patch[0].RR = (data)&15; - for (i = 0; i < 9; i++) { - if (opll->patch_number[i] == 0) { - request_update(MOD(opll, i), UPDATE_EG); - } - } - break; - - case 0x07: - opll->patch[1].SL = (data >> 4) & 15; - opll->patch[1].RR = (data)&15; - for (i = 0; i < 9; i++) { - if (opll->patch_number[i] == 0) { - request_update(CAR(opll, i), UPDATE_EG); - } - } - break; - - case 0x0e: - if (opll->chip_type == 1) - break; - update_rhythm_mode(opll); - update_key_status(opll); - break; - - case 0x0f: - opll->test_flag = data; - break; - - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - ch = reg - 0x10; - set_fnumber(opll, ch, data + ((opll->reg[0x20 + ch] & 1) << 8)); - break; - - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - ch = reg - 0x20; - set_fnumber(opll, ch, ((data & 1) << 8) + opll->reg[0x10 + ch]); - set_block(opll, ch, (data >> 1) & 7); - set_sus_flag(opll, ch, (data >> 5) & 1); - update_key_status(opll); - break; - - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - if ((opll->reg[0x0e] & 32) && (reg >= 0x36)) { - switch (reg) { - case 0x37: - set_slot_volume(MOD(opll, 7), ((data >> 4) & 15) << 2); - break; - case 0x38: - set_slot_volume(MOD(opll, 8), ((data >> 4) & 15) << 2); - break; - default: - break; - } - } else { - set_patch(opll, reg - 0x30, (data >> 4) & 15); - } - set_volume(opll, reg - 0x30, (data & 15) << 2); - break; - - default: - break; - } -} - -void OPLL_writeIO(OPLL *opll, uint32_t adr, uint8_t val) { - if (adr & 1) - OPLL_writeReg(opll, opll->adr, val); - else - opll->adr = val; -} - -void OPLL_setPan(OPLL *opll, uint32_t ch, uint8_t pan) { opll->pan[ch & 15] = pan; } - -void OPLL_setPanFine(OPLL *opll, uint32_t ch, float pan[2]) { - opll->pan_fine[ch & 15][0] = pan[0]; - opll->pan_fine[ch & 15][1] = pan[1]; -} - -void OPLL_dumpToPatch(const uint8_t *dump, OPLL_PATCH *patch) { - patch[0].AM = (dump[0] >> 7) & 1; - patch[1].AM = (dump[1] >> 7) & 1; - patch[0].PM = (dump[0] >> 6) & 1; - patch[1].PM = (dump[1] >> 6) & 1; - patch[0].EG = (dump[0] >> 5) & 1; - patch[1].EG = (dump[1] >> 5) & 1; - patch[0].KR = (dump[0] >> 4) & 1; - patch[1].KR = (dump[1] >> 4) & 1; - patch[0].ML = (dump[0]) & 15; - patch[1].ML = (dump[1]) & 15; - patch[0].KL = (dump[2] >> 6) & 3; - patch[1].KL = (dump[3] >> 6) & 3; - patch[0].TL = (dump[2]) & 63; - patch[1].TL = 0; - patch[0].FB = (dump[3]) & 7; - patch[1].FB = 0; - patch[0].WS = (dump[3] >> 3) & 1; - patch[1].WS = (dump[3] >> 4) & 1; - patch[0].AR = (dump[4] >> 4) & 15; - patch[1].AR = (dump[5] >> 4) & 15; - patch[0].DR = (dump[4]) & 15; - patch[1].DR = (dump[5]) & 15; - patch[0].SL = (dump[6] >> 4) & 15; - patch[1].SL = (dump[7] >> 4) & 15; - patch[0].RR = (dump[6]) & 15; - patch[1].RR = (dump[7]) & 15; -} - -void OPLL_getDefaultPatch(int32_t type, int32_t num, OPLL_PATCH *patch) { - OPLL_dumpToPatch(default_inst[type] + num * 8, patch); -} - -void OPLL_setPatch(OPLL *opll, const uint8_t *dump) { - OPLL_PATCH patch[2]; - int i; - for (i = 0; i < 19; i++) { - OPLL_dumpToPatch(dump + i * 8, patch); - memcpy(&opll->patch[i * 2 + 0], &patch[0], sizeof(OPLL_PATCH)); - memcpy(&opll->patch[i * 2 + 1], &patch[1], sizeof(OPLL_PATCH)); - } -} - -void OPLL_patchToDump(const OPLL_PATCH *patch, uint8_t *dump) { - dump[0] = (uint8_t)((patch[0].AM << 7) + (patch[0].PM << 6) + (patch[0].EG << 5) + (patch[0].KR << 4) + patch[0].ML); - dump[1] = (uint8_t)((patch[1].AM << 7) + (patch[1].PM << 6) + (patch[1].EG << 5) + (patch[1].KR << 4) + patch[1].ML); - dump[2] = (uint8_t)((patch[0].KL << 6) + patch[0].TL); - dump[3] = (uint8_t)((patch[1].KL << 6) + (patch[1].WS << 4) + (patch[0].WS << 3) + patch[0].FB); - dump[4] = (uint8_t)((patch[0].AR << 4) + patch[0].DR); - dump[5] = (uint8_t)((patch[1].AR << 4) + patch[1].DR); - dump[6] = (uint8_t)((patch[0].SL << 4) + patch[0].RR); - dump[7] = (uint8_t)((patch[1].SL << 4) + patch[1].RR); -} - -void OPLL_copyPatch(OPLL *opll, int32_t num, OPLL_PATCH *patch) { - memcpy(&opll->patch[num], patch, sizeof(OPLL_PATCH)); -} - -void OPLL_resetPatch(OPLL *opll, uint8_t type) { - int i; - for (i = 0; i < 19 * 2; i++) - OPLL_copyPatch(opll, i, &default_patch[type % OPLL_TONE_NUM][i]); -} - -int16_t OPLL_calc(OPLL *opll) { - while (opll->out_step > opll->out_time) { - opll->out_time += opll->inp_step; - update_output(opll); - mix_output(opll); - } - opll->out_time -= opll->out_step; - if (opll->conv) { - opll->mix_out[0] = OPLL_RateConv_getData(opll->conv, 0); - } - return opll->mix_out[0]; -} - -void OPLL_calcStereo(OPLL *opll, int32_t out[2]) { - while (opll->out_step > opll->out_time) { - opll->out_time += opll->inp_step; - update_output(opll); - mix_output_stereo(opll); - } - opll->out_time -= opll->out_step; - if (opll->conv) { - out[0] = OPLL_RateConv_getData(opll->conv, 0); - out[1] = OPLL_RateConv_getData(opll->conv, 1); - } else { - out[0] = opll->mix_out[0]; - out[1] = opll->mix_out[1]; - } -} - -uint32_t OPLL_setMask(OPLL *opll, uint32_t mask) { - uint32_t ret; - - if (opll) { - ret = opll->mask; - opll->mask = mask; - return ret; - } else - return 0; -} - -uint32_t OPLL_toggleMask(OPLL *opll, uint32_t mask) { - uint32_t ret; - - if (opll) { - ret = opll->mask; - opll->mask ^= mask; - return ret; - } else - return 0; -} diff --git a/src/mappers/sound/emu2413.h b/src/mappers/sound/emu2413.h deleted file mode 100644 index dbc0af1d9..000000000 --- a/src/mappers/sound/emu2413.h +++ /dev/null @@ -1,237 +0,0 @@ -#ifndef _EMU2413_H_ -#define _EMU2413_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define OPLL_DEBUG 0 - -enum OPLL_TONE_ENUM { OPLL_2413_TONE = 0, OPLL_VRC7_TONE = 1, OPLL_281B_TONE = 2 }; - -/* voice data */ -typedef struct __OPLL_PATCH { - uint32_t TL, FB, EG, ML, AR, DR, SL, RR, KR, KL, AM, PM, WS; -} OPLL_PATCH; - -/* slot */ -typedef struct __OPLL_SLOT { - uint8_t number; - - /* type flags: - * 000000SM - * |+-- M: 0:modulator 1:carrier - * +--- S: 0:normal 1:single slot mode (sd, tom, hh or cym) - */ - uint8_t type; - - OPLL_PATCH *patch; /* voice parameter */ - - /* slot output */ - int32_t output[2]; /* output value, latest and previous. */ - - /* phase generator (pg) */ - uint16_t *wave_table; /* wave table */ - uint32_t pg_phase; /* pg phase */ - uint32_t pg_out; /* pg output, as index of wave table */ - uint8_t pg_keep; /* if 1, pg_phase is preserved when key-on */ - uint16_t blk_fnum; /* (block << 9) | f-number */ - uint16_t fnum; /* f-number (9 bits) */ - uint8_t blk; /* block (3 bits) */ - - /* envelope generator (eg) */ - uint8_t eg_state; /* current state */ - int32_t volume; /* current volume */ - uint8_t key_flag; /* key-on flag 1:on 0:off */ - uint8_t sus_flag; /* key-sus option 1:on 0:off */ - uint16_t tll; /* total level + key scale level*/ - uint8_t rks; /* key scale offset (rks) for eg speed */ - uint8_t eg_rate_h; /* eg speed rate high 4bits */ - uint8_t eg_rate_l; /* eg speed rate low 2bits */ - uint32_t eg_shift; /* shift for eg global counter, controls envelope speed */ - uint32_t eg_out; /* eg output */ - - uint32_t update_requests; /* flags to debounce update */ - -#if OPLL_DEBUG - uint8_t last_eg_state; -#endif -} OPLL_SLOT; - -/* mask */ -#define OPLL_MASK_CH(x) (1 << (x)) -#define OPLL_MASK_HH (1 << (9)) -#define OPLL_MASK_CYM (1 << (10)) -#define OPLL_MASK_TOM (1 << (11)) -#define OPLL_MASK_SD (1 << (12)) -#define OPLL_MASK_BD (1 << (13)) -#define OPLL_MASK_RHYTHM (OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD) - -/* rate conveter */ -typedef struct __OPLL_RateConv { - int ch; - double timer; - double f_ratio; - int16_t *sinc_table; - int16_t **buf; -} OPLL_RateConv; - -OPLL_RateConv *OPLL_RateConv_new(double f_inp, double f_out, int ch); -void OPLL_RateConv_reset(OPLL_RateConv *conv); -void OPLL_RateConv_putData(OPLL_RateConv *conv, int ch, int16_t data); -int16_t OPLL_RateConv_getData(OPLL_RateConv *conv, int ch); -void OPLL_RateConv_delete(OPLL_RateConv *conv); - -typedef struct __OPLL { - uint32_t clk; - uint32_t rate; - - uint8_t chip_type; - - uint32_t adr; - - double inp_step; - double out_step; - double out_time; - - uint8_t reg[0x40]; - uint8_t test_flag; - uint32_t slot_key_status; - uint8_t rhythm_mode; - - uint32_t eg_counter; - - uint32_t pm_phase; - int32_t am_phase; - - uint8_t lfo_am; - - uint32_t noise; - uint8_t short_noise; - - int32_t patch_number[9]; - OPLL_SLOT slot[18]; - OPLL_PATCH patch[19 * 2]; - - uint8_t pan[16]; - float pan_fine[16][2]; - - uint32_t mask; - - /* channel output */ - /* 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym */ - int16_t ch_out[14]; - - int16_t mix_out[2]; - - OPLL_RateConv *conv; -} OPLL; - -OPLL *OPLL_new(uint32_t clk, uint32_t rate); -void OPLL_delete(OPLL *); - -void OPLL_reset(OPLL *); -void OPLL_resetPatch(OPLL *, uint8_t); - -/** - * Set output wave sampling rate. - * @param rate sampling rate. If clock / 72 (typically 49716 or 49715 at 3.58MHz) is set, the internal rate converter is - * disabled. - */ -void OPLL_setRate(OPLL *opll, uint32_t rate); - -/** - * Set internal calcuration quality. Currently no effects, just for compatibility. - * >= v1.0.0 always synthesizes internal output at clock/72 Hz. - */ -void OPLL_setQuality(OPLL *opll, uint8_t q); - -/** - * Set pan pot (extra function - not YM2413 chip feature) - * @param ch 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym 14,15:reserved - * @param pan 0:mute 1:right 2:left 3:center - * ``` - * pan: 76543210 - * |+- bit 1: enable Left output - * +-- bit 0: enable Right output - * ``` - */ -void OPLL_setPan(OPLL *opll, uint32_t ch, uint8_t pan); - -/** - * Set fine-grained panning - * @param ch 0..8:tone 9:bd 10:hh 11:sd 12:tom 13:cym 14,15:reserved - * @param pan output strength of left/right channel. - * pan[0]: left, pan[1]: right. pan[0]=pan[1]=1.0f for center. - */ -void OPLL_setPanFine(OPLL *opll, uint32_t ch, float pan[2]); - -/** - * Set chip type. If vrc7 is selected, r#14 is ignored. - * This method not change the current ROM patch set. - * To change ROM patch set, use OPLL_resetPatch. - * @param type 0:YM2413 1:VRC7 - */ -void OPLL_setChipType(OPLL *opll, uint8_t type); - -void OPLL_writeIO(OPLL *opll, uint32_t reg, uint8_t val); -void OPLL_writeReg(OPLL *opll, uint32_t reg, uint8_t val); - -/** - * Calculate one sample - */ -int16_t OPLL_calc(OPLL *opll); - -/** - * Calulate stereo sample - */ -void OPLL_calcStereo(OPLL *opll, int32_t out[2]); - -void OPLL_setPatch(OPLL *, const uint8_t *dump); -void OPLL_copyPatch(OPLL *, int32_t, OPLL_PATCH *); - -/** - * Force to refresh. - * External program should call this function after updating patch parameters. - */ -void OPLL_forceRefresh(OPLL *); - -void OPLL_dumpToPatch(const uint8_t *dump, OPLL_PATCH *patch); -void OPLL_patchToDump(const OPLL_PATCH *patch, uint8_t *dump); -void OPLL_getDefaultPatch(int32_t type, int32_t num, OPLL_PATCH *); - -/** - * Set channel mask - * @param mask mask flag: OPLL_MASK_* can be used. - * - bit 0..8: mask for ch 1 to 9 (OPLL_MASK_CH(i)) - * - bit 9: mask for Hi-Hat (OPLL_MASK_HH) - * - bit 10: mask for Top-Cym (OPLL_MASK_CYM) - * - bit 11: mask for Tom (OPLL_MASK_TOM) - * - bit 12: mask for Snare Drum (OPLL_MASK_SD) - * - bit 13: mask for Bass Drum (OPLL_MASK_BD) - */ -uint32_t OPLL_setMask(OPLL *, uint32_t mask); - -/** - * Toggler channel mask flag - */ -uint32_t OPLL_toggleMask(OPLL *, uint32_t mask); - -/* for compatibility */ -#define OPLL_set_rate OPLL_setRate -#define OPLL_set_quality OPLL_setQuality -#define OPLL_set_pan OPLL_setPan -#define OPLL_set_pan_fine OPLL_setPanFine -#define OPLL_calc_stereo OPLL_calcStereo -#define OPLL_reset_patch OPLL_resetPatch -#define OPLL_dump2patch OPLL_dumpToPatch -#define OPLL_patch2dump OPLL_patchToDump -#define OPLL_setChipMode OPLL_setChipType - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/mappers/sound/fdssound.c b/src/mappers/sound/fdssound.c deleted file mode 100644 index 9bfc045f0..000000000 --- a/src/mappers/sound/fdssound.c +++ /dev/null @@ -1,417 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* FDSSound rewrite based on MDFN NES fds sound implementation, modifed for fceumm's use. */ -/* WIP as some crackling sounds can be annoyingly heard and other issues. */ - -#include "mapinc.h" -#include "fdssound.h" - -static void RenderSoundHQ(void); -static void RenderSound(void); - -static const int32 mod_bias_tab[8] = { 0, 1, 2, 4, 0, -4, -2, -1 }; - -static FDSSOUND fdso = { 0 }; -static int32 FBC = 0; - -void FDSSound_AddStateInfo(void) { - AddExState(&fdso.EnvUnits[EVOL].speed, 1, 0, "SPD0"); - AddExState(&fdso.EnvUnits[EVOL].control, 1, 0, "CTL0"); - AddExState(&fdso.EnvUnits[EVOL].volume, 1, 0, "VOL0"); - AddExState(&fdso.EnvUnits[EVOL].counter, 1, 0, "CNT0"); - - AddExState(&fdso.EnvUnits[EMOD].speed, 1, 0, "SPD1"); - AddExState(&fdso.EnvUnits[EMOD].control, 1, 0, "CTL1"); - AddExState(&fdso.EnvUnits[EMOD].volume, 1, 0, "VOL1"); - AddExState(&fdso.EnvUnits[EMOD].counter, 1, 0, "CNT1"); - - AddExState(fdso.cwave, 64, 0, "WAVE"); - AddExState(fdso.mwave, 32, 0, "MWAV"); - - AddExState(&fdso.cwave_freq, 2, 0, "WFRQ"); - AddExState(&fdso.cwave_pos, 4, 0, "WPOS"); - AddExState(&fdso.cwave_control, 1, 0, "WCTL"); - - AddExState(&fdso.mod_freq, 2, 0, "MFRQ"); - AddExState(&fdso.mod_pos, 4, 0, "MPOS"); - AddExState(&fdso.mod_control, 1, 0, "MCTL"); - - AddExState(&fdso.sweep_bias, 4, 0, "SWBS"); - - AddExState(&fdso.master_control, 1, 0, "MCTL"); - AddExState(&fdso.master_env_speed, 1, 0, "MSPD"); - - AddExState(&fdso.envcount, 2, 0, "EDIV"); -} - -static void FDSSoundUpdate(void) { - if (FSettings.SndRate) { - if (FSettings.soundq >= 1) { - RenderSoundHQ(); - } else { - RenderSound(); - } - } -} - -DECLFR(FDSWaveRead) { - if (fdso.master_control & WAVE_WRITE_MODE) { - return (FDS_OPENBUS | fdso.cwave[A & 0x3F]); - } - return (FDS_OPENBUS | fdso.cwave[(fdso.cwave_pos >> 21) & 0x3F]); -} - -DECLFW(FDSWaveWrite) { - if (fdso.master_control & WAVE_WRITE_MODE) { - fdso.cwave[A & 0x3f] = V & 0x3F; - } -} - -DECLFW(FDSSReg0Write) { - FDSSoundUpdate(); - - fdso.EnvUnits[EVOL].speed = V & 0x3F; - fdso.EnvUnits[EVOL].control = V & 0xC0; - - fdso.EnvUnits[EVOL].counter = fdso.EnvUnits[EVOL].speed + 1; - - if (fdso.EnvUnits[EVOL].control & ENV_CTRL_DISABLE) { - fdso.EnvUnits[EVOL].volume = fdso.EnvUnits[EVOL].speed; - } -} - -DECLFW(FDSSReg1Write) { - FDSSoundUpdate(); - - fdso.cwave_freq &= 0x0F00; - fdso.cwave_freq |= V; -} - -DECLFW(FDSSReg2Write) { - FDSSoundUpdate(); - - fdso.cwave_freq &= 0x00FF; - fdso.cwave_freq |= (V & 0x0F) << 8; - - fdso.cwave_control = V & 0xC0; - - if ((fdso.cwave_control & WAVE_DISABLE)) { - fdso.cwave_pos = 0; - } -} - -DECLFW(FDSSReg3Write) { - FDSSoundUpdate(); - - fdso.EnvUnits[EMOD].speed = V & 0x3F; - fdso.EnvUnits[EMOD].control = V & 0xC0; - - fdso.EnvUnits[EMOD].counter = fdso.EnvUnits[EMOD].speed + 1; - - if (fdso.EnvUnits[EMOD].control & ENV_CTRL_DISABLE) { - fdso.EnvUnits[EMOD].volume = fdso.EnvUnits[EMOD].speed; - } -} - -DECLFW(FDSSReg4Write) { - FDSSoundUpdate(); - - fdso.sweep_bias = (V & 0x7F) << 4; - fdso.mod_pos = 0; -} - -DECLFW(FDSSReg5Write) { - FDSSoundUpdate(); - - fdso.mod_freq &= 0x0F00; - fdso.mod_freq |= V; -} - -DECLFW(FDSSReg6Write) { - FDSSoundUpdate(); - - fdso.mod_freq &= 0x00FF; - fdso.mod_freq |= (V & 0x0F) << 8; - - fdso.mod_control = V & 0xC0; - - if (fdso.mod_control & MOD_WRITE_MODE) { - fdso.mod_pos = 0; - } -} - -DECLFW(FDSSReg7Write) { - FDSSoundUpdate(); - - if (fdso.mod_control & MOD_WRITE_MODE) { - int i; - for (i = 0; i < 31; i++) { - fdso.mwave[i] = fdso.mwave[i + 1]; - } - fdso.mwave[0x1F] = mod_bias_tab[V & 0x07]; - if ((V & 0x07) == 0x04) { - fdso.mwave[0x1F] = 0x10; - } - } -} - -DECLFW(FDSSReg8Write) { - FDSSoundUpdate(); - - fdso.master_control = V; -} - -DECLFW(FDSSReg9Write) { - FDSSoundUpdate(); - - fdso.master_env_speed = V; -} - -DECLFR(FDSEnvVolumeRead) { - FDSSoundUpdate(); - return (FDS_OPENBUS | fdso.EnvUnits[EVOL].volume); -} - -DECLFR(FDSEnvModRead) { - FDSSoundUpdate(); - return (FDS_OPENBUS | fdso.EnvUnits[EMOD].volume); -} - -#define sign_x_to_s32(n, v) ((int32)((uint32)(v) << (32 - (n))) >> (32 - (n))) - -static INLINE int32 FDSDoSound(void) { - uint32 prev_cwave_pos = fdso.cwave_pos; - static int32 temp; - - fdso.count += fdso.cycles; - if (fdso.count >= ((int64)1 << 40)) { -dogk: - fdso.count -= (int64)1 << 40; - - if (!(fdso.cwave_control & ENVELOPES_DISABLE) && fdso.master_env_speed) { - if (fdso.envcount) { - fdso.envcount--; - } else { - fdso.envcount = fdso.master_env_speed * 3; - if (!(fdso.EnvUnits[EVOL].control & ENV_CTRL_DISABLE)) { - if (fdso.EnvUnits[EVOL].counter) { - fdso.EnvUnits[EVOL].counter--; - } else { - fdso.EnvUnits[EVOL].counter = fdso.EnvUnits[EVOL].speed + 1; - if ((fdso.EnvUnits[EVOL].control & ENV_CTRL_INCREASE)) { - if (fdso.EnvUnits[EVOL].volume < 0x20) { - fdso.EnvUnits[EVOL].volume++; - } - } else { - if (fdso.EnvUnits[EVOL].volume > 0) { - fdso.EnvUnits[EVOL].volume--; - } - } - } - } - - if (!(fdso.EnvUnits[EMOD].control & ENV_CTRL_DISABLE)) { - if (fdso.EnvUnits[EMOD].counter) { - fdso.EnvUnits[EMOD].counter--; - } else { - fdso.EnvUnits[EMOD].counter = fdso.EnvUnits[EMOD].speed + 1; - if ((fdso.EnvUnits[EMOD].control & ENV_CTRL_INCREASE)) { - if (fdso.EnvUnits[EMOD].volume < 0x20) { - fdso.EnvUnits[EMOD].volume++; - } - } else { - if (fdso.EnvUnits[EMOD].volume > 0) { - fdso.EnvUnits[EMOD].volume--; - } - } - } - } - } - } - - if (!(fdso.mod_control & MOD_WRITE_MODE)) { - uint32 prev_mod_pos = fdso.mod_pos; - - fdso.mod_pos += fdso.mod_freq; - if ((fdso.mod_pos & (0x3F << 11)) != - (prev_mod_pos & (0x3F << 11))) { - const int32 mw = fdso.mwave[((fdso.mod_pos >> 16) & 0x1F)]; - - fdso.sweep_bias = (fdso.sweep_bias + mw) & 0x7FF; - if (mw == 0x10) { - fdso.sweep_bias = 0; - } - } - - temp = sign_x_to_s32(11, fdso.sweep_bias) * - ((fdso.EnvUnits[EMOD].volume > 0x20) ? 0x20 : fdso.EnvUnits[EMOD].volume); - - if (temp & 0x0F0) { - temp /= 256; - if (fdso.sweep_bias & 0x400) { - temp--; - } else { - temp += 2; - } - } else { - temp /= 256; - } - - if (temp >= 192) { - temp -= 256; - } - if (temp < -64) { - temp += 256; - } - } - - if (!(fdso.cwave_control & WAVE_DISABLE)) { - int32 cur_cwave_freq = (int32)(fdso.cwave_freq << 6); - - if (!(fdso.mod_control & MOD_WRITE_MODE)) { - cur_cwave_freq += (int32)fdso.cwave_freq * temp; - if (cur_cwave_freq < 0) { - cur_cwave_freq = 0; - } - } - fdso.cwave_pos = (fdso.cwave_pos + cur_cwave_freq) & 0x7FFFFFF; - } - } - if (fdso.count >= 32768) { - goto dogk; - } - - /* Might need to emulate applying the amplitude to the waveform a bit better... */ - { - int k = fdso.EnvUnits[EVOL].volume; - if (k > 0x20) { - k = 0x20; - } - return (fdso.cwave[fdso.cwave_pos >> 21] * FSettings.ExpSoundVolume[SND_FDS] * k * 4 / ((fdso.master_control & MASTER_VOLUME) + 2)) >> 8; - } -} - -static void RenderSound(void) { - int32 end, start; - int32 x; - - start = FBC; - end = (SOUNDTS << 16) / soundtsinc; - if (end <= start) { - return; - } - FBC = end; - - if (!(fdso.master_control & WAVE_WRITE_MODE)) { - for (x = start; x < end; x++) { - uint32 t = FDSDoSound(); - t += t >> 1; - t >>= 4; - Wave[x >> 4] += t; /* (t>>2)-(t>>3); */ /* >>3; */ - } - } -} - -static void RenderSoundHQ(void) { - uint32 x; - - if (!(fdso.master_control & WAVE_WRITE_MODE)) { - for (x = FBC; x < SOUNDTS; x++) { - uint32 t = FDSDoSound(); - t += t >> 1; - WaveHi[x] += t; /* (t<<2)-(t<<1); */ - } - } - FBC = SOUNDTS; -} - -static void HQSync(int32 ts) { - FBC = ts; -} - -static void FDSSound(int c) { - RenderSound(); - FBC = c; -} - -void FDSSound_SC(void) { - GameExpSound[SND_FDS].HiSync = HQSync; - GameExpSound[SND_FDS].HiFill = RenderSoundHQ; - GameExpSound[SND_FDS].Fill = FDSSound; - GameExpSound[SND_FDS].RChange = FDSSound_SC; - - if (FSettings.SndRate) { - if (FSettings.soundq >= 1) { - fdso.cycles = (int64)1 << 39; - } else { - fdso.cycles = ((int64)1 << 40) * FDSClock; - fdso.cycles /= FSettings.SndRate * 16; - } - } -} - -void FDSSoundRegReset(void) { - memset(&fdso, 0, sizeof(fdso)); - - /* https://github.com/bbbradsmith/nsfplay/blob/f563b9fe32df9ef0a94944026642d8ce5144c000/xgm/devices/Sound/nes_fds.cpp#L109 */ - - /* NOTE: the FDS BIOS reset only does the following related to audio: */ - /* $4023 = $00 - * $4023 = $83 enables master_io - * $4080 = $80 output volume = 0, envelope disabled - * $408A = $E8 master envelope speed - * $4023 = $00 - * $4023 = $83 */ - FDSSReg0Write(0x4080, 0x80); - FDSSReg9Write(0x408A, 0xE8); - - /* reset other stuff */ - FDSSReg1Write(0x4082, 0x00); /* wav freq 0 */ - FDSSReg2Write(0x4083, 0x80); /* wav disable */ - FDSSReg3Write(0x4084, 0x80); /* mod strength 0 */ - FDSSReg4Write(0x4085, 0x00); /* mod position 0 */ - FDSSReg5Write(0x4086, 0x00); /* mod freq 0 */ - FDSSReg6Write(0x4087, 0x80); /* mod disable */ - FDSSReg8Write(0x4089, 0x00); /* wav write disable, max global volume} */ -} - -/* callback for bootleg mappers */ - -void FDSSound_Power(void) { - FDSSoundRegReset(); - FDSSound_SC(); - - SetReadHandler(0x4040, 0x407F, FDSWaveRead); - SetReadHandler(0x4090, 0x4090, FDSEnvVolumeRead); - SetReadHandler(0x4092, 0x4092, FDSEnvModRead); - - SetWriteHandler(0x4040, 0x407F, FDSWaveWrite); - SetWriteHandler(0x4080, 0x4080, FDSSReg0Write); - SetWriteHandler(0x4082, 0x4082, FDSSReg1Write); - SetWriteHandler(0x4083, 0x4083, FDSSReg2Write); - SetWriteHandler(0x4084, 0x4084, FDSSReg3Write); - SetWriteHandler(0x4085, 0x4085, FDSSReg4Write); - SetWriteHandler(0x4086, 0x4086, FDSSReg5Write); - SetWriteHandler(0x4087, 0x4087, FDSSReg6Write); - SetWriteHandler(0x4088, 0x4088, FDSSReg7Write); - SetWriteHandler(0x4089, 0x4089, FDSSReg8Write); - SetWriteHandler(0x408A, 0x408A, FDSSReg9Write); -} diff --git a/src/mappers/sound/fdssound.h b/src/mappers/sound/fdssound.h deleted file mode 100644 index 8f6f266a9..000000000 --- a/src/mappers/sound/fdssound.h +++ /dev/null @@ -1,96 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _FDS_APU_H -#define _FDS_APU_H - -#define FDSClock (NTSC_CLOCK_SPEED / 2) - -enum { FDS_OPENBUS = 0x40 }; -enum { EVOL = 0, EMOD }; -enum { - ENV_CTRL_INCREASE = 0x40, - ENV_CTRL_DISABLE = 0x80, - ENVELOPES_DISABLE = 0x40, - WAVE_DISABLE = 0x80, - MOD_WRITE_MODE = 0x80, - MASTER_VOLUME = 0x03, - WAVE_WRITE_MODE = 0x80 -}; - -typedef struct __FDSENVUNIT { - uint8 speed; - uint8 volume; /* Current volumes. */ - uint8 control; /* $4080/$4084 with low 6bits masked */ - uint8 counter; /**/ -} FDSENVUNIT; - -typedef struct __FDSSOUND { - int64 cycles; /* fds cycles to run */ - int64 count; /* current cycle count */ - - FDSENVUNIT EnvUnits[2]; - - uint16 envcount; /* Main envelope clock divider. */ - - uint16 cwave_freq; /* $4082 and lower 4 bits of $4083 */ - uint32 cwave_pos; /* main phase */ - uint8 cwave_control; /* $4083 with low 6bits masked */ - - uint16 mod_freq; /* $4086 and lower 4 bits of $4087 */ - uint32 mod_pos; /* Should be named "mwave_pos", but "mod_pos" distinguishes it more. */ - uint8 mod_control; /* $4087 bit7 */ - - uint8 master_control; /* $4089 with lower 6 bits masked */ - uint8 master_env_speed; /* Master envelope speed controller($408A). */ - - int32 mwave[0x20]; /* Modulation waveform. Stored in expanded(after LUT) */ - /* form. Set to 0x10 if the original value is */ - /* 0x4(reset sweep bias accumulator). */ - uint8 cwave[0x40]; /* Game-defined waveform(carrier) */ - uint32 sweep_bias; -} FDSSOUND; - -DECLFR(FDSWaveRead); -DECLFW(FDSWaveWrite); -DECLFW(FDSSReg0Write); -DECLFW(FDSSReg1Write); -DECLFW(FDSSReg2Write); -DECLFW(FDSSReg3Write); -DECLFW(FDSSReg4Write); -DECLFW(FDSSReg5Write); -DECLFW(FDSSReg6Write); -DECLFW(FDSSReg7Write); -DECLFW(FDSSReg8Write); -DECLFW(FDSSReg9Write); -DECLFR(FDSEnvVolumeRead); -DECLFR(FDSEnvModRead); - -void FDSSound_SC(void); -void FDSSound_Reset(void); -void FDSSoundRegReset(void); -void FDSSound_AddStateInfo(void); - -/* For mappers utilizing FDS expansion audio */ -void FDSSound_Power(void); -DECLFR(FDSSound_Read); /* $4040-$4092 */ -DECLFW(FDSSound_Write); /* $4040-$408A */ - -#endif /* _FDS_APU_H */ diff --git a/src/mappers/sound/mmc5sound.c b/src/mappers/sound/mmc5sound.c deleted file mode 100644 index 0fd26a4c9..000000000 --- a/src/mappers/sound/mmc5sound.c +++ /dev/null @@ -1,301 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "mmc5sound.h" - -typedef struct __MMC5SQUARE { - /* regs */ - uint8 volume; - uint8 duty; - uint8 enabled; - int16 freq; - - /* timers */ - uint8 dcount; - int32 vcount; - int32 cvbc; -} MMC5SQUARE; - -typedef struct __MMC5PCM { - uint8 rawdata; - uint8 control; - int32 cvbc; -} MMC5PCM; - -typedef struct __MMC5SOUND { - MMC5SQUARE square[2]; - MMC5PCM pcm; -} MMC5SOUND; - -static MMC5SOUND MMC5Sound; - -static void (*sfun)(MMC5SQUARE *channel); -static void (*psfun)(void); - -static void Do5PCM(void) { - int32 V; - int32 start, end; - - start = MMC5Sound.pcm.cvbc; - end = (SOUNDTS << 16) / soundtsinc; - if (end <= start) { - return; - } - MMC5Sound.pcm.cvbc = end; - - if (!(MMC5Sound.pcm.control & 0x40) && MMC5Sound.pcm.rawdata) { - int32 amp = GetOutput(SND_MMC5, MMC5Sound.pcm.rawdata << 1); - - for (V = start; V < end; V++) { - Wave[V >> 4] += amp; - } - } -} - -static void Do5PCMHQ(void) { - int32 V; - - if (!(MMC5Sound.pcm.control & 0x40) && MMC5Sound.pcm.rawdata) { - int32 amp = GetOutput(SND_MMC5, MMC5Sound.pcm.rawdata << 5); - - for (V = MMC5Sound.pcm.cvbc; V < SOUNDTS; V++) { - WaveHi[V] += amp; - } - } - MMC5Sound.pcm.cvbc = SOUNDTS; -} - -static void Do5SQ(MMC5SQUARE *channel) { - static int tal[4] = { 1, 2, 4, 6 }; - int32 V, amp, duty, freq; - int32 start, end; - - start = channel->cvbc; - end = (SOUNDTS << 16) / soundtsinc; - if (end <= start) { - return; - } - channel->cvbc = end; - - freq = channel->freq + 1; - amp = GetOutput(SND_MMC5, channel->volume << 4); - duty = tal[channel->duty]; - - if ((freq >= 8) && channel->enabled) { - int32 dc, vc; - - freq <<= 18; - dc = channel->dcount; - vc = channel->vcount; - - for (V = start; V < end; V++) { - if (dc < duty) { - Wave[V >> 4] += amp; - } - vc -= nesincsize; - while (vc <= 0) { - vc += freq; - dc = (dc + 1) & 0x07; - } - } - channel->dcount = dc; - channel->vcount = vc; - } -} - -static void Do5SQHQ(MMC5SQUARE *channel) { - static int tal[4] = { 1, 2, 4, 6 }; - int V, amp, duty, freq; - - freq = channel->freq + 1; - amp = GetOutput(SND_MMC5, channel->volume << 8); - duty = tal[channel->duty]; - - if ((freq >= 8) && channel->enabled) { - int dc, vc; - - freq <<= 1; - - dc = channel->dcount; - vc = channel->vcount; - - for (V = channel->cvbc; V < SOUNDTS; V++) { - if (dc < duty) { - WaveHi[V] += amp; - } - vc--; - if (vc <= 0) { /* Less than zero when first started. */ - vc = freq; - dc = (dc + 1) & 0x07; - } - } - channel->dcount = dc; - channel->vcount = vc; - } - channel->cvbc = SOUNDTS; -} - -static void MMC5RunSoundHQ(void) { - Do5SQHQ(&MMC5Sound.square[0]); - Do5SQHQ(&MMC5Sound.square[1]); - Do5PCMHQ(); -} - -static void MMC5HiSync(int32 ts) { - MMC5Sound.square[0].cvbc = ts; - MMC5Sound.square[1].cvbc = ts; - MMC5Sound.pcm.cvbc = ts; -} - -static void MMC5RunSound(int Count) { - Do5SQ(&MMC5Sound.square[0]); - Do5SQ(&MMC5Sound.square[1]); - Do5PCM(); - MMC5Sound.square[0].cvbc = Count; - MMC5Sound.square[1].cvbc = Count; - MMC5Sound.pcm.cvbc = Count; -} - -static void MMC5Square_Write(MMC5SQUARE *channel, uint8 reg, uint8 V) { - switch (reg) { - case 0: - channel->volume = V & 0x0F; - channel->duty = (V & 0xC0) >> 6; - break; - - case 1: - break; - - case 2: - channel->freq = (channel->freq & ~0x00FF) | V; - break; - - case 3: - channel->freq = (channel->freq & ~0x0700) | ((V & 0x07) << 8); - break; - - case 4: - channel->enabled = (V != 0); - break; - } -} - -DECLFW(MMC5Sound_Write) { - GameExpSound[SND_MMC5].Fill = MMC5RunSound; - GameExpSound[SND_MMC5].HiFill = MMC5RunSoundHQ; - - switch (A) { - case 0x5010: - if (psfun) { - psfun(); - } - MMC5Sound.pcm.control = V; - break; - - case 0x5011: - if (psfun) { - psfun(); - } - MMC5Sound.pcm.rawdata = V; - break; - - case 0x5000: - case 0x5001: - case 0x5002: - case 0x5003: - if (sfun) { - sfun(&MMC5Sound.square[0]); - } - MMC5Square_Write(&MMC5Sound.square[0], A & 0x03, V); - break; - - case 0x5004: - case 0x5005: - case 0x5006: - case 0x5007: - if (sfun) { - sfun(&MMC5Sound.square[1]); - } - MMC5Square_Write(&MMC5Sound.square[1], A & 0x03, V); - break; - - case 0x5015: - if (sfun) { - sfun(&MMC5Sound.square[0]); - sfun(&MMC5Sound.square[1]); - } - MMC5Square_Write(&MMC5Sound.square[0], 4, V & 0x01); - MMC5Square_Write(&MMC5Sound.square[1], 4, V & 0x02); - break; - } -} - -static void MMC5SC(void) { - GameExpSound[SND_MMC5].HiSync = MMC5HiSync; - - MMC5Sound.square[0].vcount = 0; - MMC5Sound.square[1].vcount = 0; - - MMC5Sound.square[0].cvbc = 0; - MMC5Sound.square[1].cvbc = 0; - MMC5Sound.pcm.cvbc = 0; - - if (FSettings.SndRate) { - if (FSettings.soundq >= 1) { - sfun = Do5SQHQ; - psfun = Do5PCMHQ; - } else { - sfun = Do5SQ; - psfun = Do5PCM; - } - } else { - sfun = 0; - psfun = 0; - } -} - -void MMC5Sound_ESI(void) { - memset(&MMC5Sound, 0, sizeof(MMC5Sound)); - GameExpSound[SND_MMC5].RChange = MMC5SC; - MMC5SC(); -} - -void MMC5Sound_AddStateInfo(void) { - AddExState(&MMC5Sound.square[0].enabled, 1, 0, "S0EN"); - AddExState(&MMC5Sound.square[0].volume, 1, 0, "S0VL"); - AddExState(&MMC5Sound.square[0].freq, 2, 0, "S0FQ"); - AddExState(&MMC5Sound.square[0].duty, 1, 0, "S0DT"); - AddExState(&MMC5Sound.square[0].dcount, 1, 0, "S0DC"); - AddExState(&MMC5Sound.square[0].vcount, 4, 0, "S0VC"); - AddExState(&MMC5Sound.square[0].cvbc, 4, 0, "S0BC"); - - AddExState(&MMC5Sound.square[1].enabled, 1, 0, "S1EN"); - AddExState(&MMC5Sound.square[1].volume, 1, 0, "S1VL"); - AddExState(&MMC5Sound.square[1].freq, 2, 0, "S1FQ"); - AddExState(&MMC5Sound.square[1].duty, 1, 0, "S1DT"); - AddExState(&MMC5Sound.square[1].dcount, 1, 0, "S1DC"); - AddExState(&MMC5Sound.square[1].vcount, 4, 0, "S1VC"); - AddExState(&MMC5Sound.square[1].cvbc, 4, 0, "S1BC"); - - AddExState(&MMC5Sound.pcm.control, 1, 0, "PCTL"); - AddExState(&MMC5Sound.pcm.rawdata, 1, 0, "PRAW"); - AddExState(&MMC5Sound.pcm.cvbc, 4, 0, "PCVB"); -} diff --git a/src/mappers/sound/mmc5sound.h b/src/mappers/sound/mmc5sound.h deleted file mode 100644 index d0ec715b6..000000000 --- a/src/mappers/sound/mmc5sound.h +++ /dev/null @@ -1,28 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _MMC5_AUDIO_H -#define _MMC5_AUDIO_H - -void MMC5Sound_ESI(void); -DECLFW(MMC5Sound_Write); -void MMC5Sound_AddStateInfo(void); - -#endif /* _MMC5_AUDIO_H */ diff --git a/src/mappers/sound/n163sound.c b/src/mappers/sound/n163sound.c deleted file mode 100644 index 2ba0b2142..000000000 --- a/src/mappers/sound/n163sound.c +++ /dev/null @@ -1,326 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* TODO: Things to do: - 1 Read freq low - 2 Read freq mid - 3 Read freq high - 4 Read volume - ...? -*/ - -#include "mapinc.h" -#include "n163sound.h" - -enum SoundReg { - FREQ_L = 0x00, - PHASE_L = 0x01, - FREQ_M = 0x02, - PHASE_M = 0x03, - FREQ_H = 0x04, - WAVELEN = 0x04, - PHASE_H = 0x05, - WAVEADDR = 0x06, - VOLUME = 0x07 -}; - -typedef struct N163Channel { - uint32 PlayIndex; /* should be phase? */ - int32 vcount; - int16 output; -} N163Channel; - -static N163Channel N163Snd[8]; -static uint8 IRAM[128]; -static uint8 ramPos; -static uint8 autoInc; -static int32 CVBC; - -#define VOLADJ (576716) -#define TOINDEX (16 + 1) - -static uint32 GetFrequency(int P) { - uint8 base = 0x40 + P * 0x08; - return ((IRAM[base + FREQ_H] & 0x03) << 16) | - (IRAM[base + FREQ_M] << 8) | - IRAM[base + FREQ_L]; -} - -static uint32 GetPhase(int P) { - uint8 base = 0x40 + P * 0x08; - return (IRAM[base + PHASE_H] << 16) | - (IRAM[base + PHASE_M] << 8) | - IRAM[base + PHASE_L]; -} - -static void SetPhase(int P, uint32 phase) { - uint8 base = 0x40 + P * 0x08; - IRAM[base + PHASE_H] = (phase >> 16) & 0xFF; - IRAM[base + PHASE_M] = (phase >> 8) & 0xFF; - IRAM[base + PHASE_L] = phase & 0xFF; -} - -static uint8 GetWaveAddress(int P) { - uint8 base = 0x40 + P * 0x08; - return IRAM[base + WAVEADDR]; -} - -static uint8 GetWaveLength(int P) { - uint8 base = 0x40 + P * 0x08; - return 256 - (IRAM[base + WAVELEN] & 0xFC); -} - -static uint32 GetVolume(int P) { - uint8 base = 0x40 + P * 0x08; - return (IRAM[base + VOLUME] & 0x0F) * VOLADJ; -} - -static uint8 GetNumberOfChannels() { - return (IRAM[0x7F] >> 4) & 0x07; -} - -static int16 GetSample(uint8 pos, int volume, int outshift) { - int8 sample; - if (pos & 0x01) { - sample = IRAM[pos >> 1] >> 4; - } else { - sample = IRAM[pos >> 1] & 0x0F; - } - return ((sample * volume) >> outshift); -} - -/* 16:15 */ -static void SyncHQ(int32 ts) { - CVBC = ts; -} - -static void DoN163SoundHQ(void) { - int32 cyclesuck = (GetNumberOfChannels() + 1) * 15; - int32 P, V; - - for (P = 7; P >= (7 - GetNumberOfChannels()); P--) { - N163Channel *channel = &N163Snd[P]; - int channelOffset = 0x40 + (P * 8); - - if ((IRAM[FREQ_H + channelOffset] & 0xE0) && (IRAM[VOLUME + channelOffset] & 0xF)) { - int32 vco = channel->vcount; - - uint32 phase = GetPhase(P); - uint32 freq = GetFrequency(P); - uint16 length = GetWaveLength(P); - uint8 offset = GetWaveAddress(P); - uint32 volume = GetVolume(P); - - for (V = CVBC << 1; V < (int)SOUNDTS << 1; V++) { - if (vco == 0) { - vco = cyclesuck; - channel->PlayIndex += freq; - while ((channel->PlayIndex >> TOINDEX) >= length) { - channel->PlayIndex -= length << TOINDEX; - } - channel->output = GetSample((channel->PlayIndex >> TOINDEX) + offset, volume, 16); - } - vco--; - WaveHi[V >> 1] += GetOutput(SND_N163, channel->output); - } - channel->vcount = vco; - } - } - CVBC = SOUNDTS; -} - -static void DoN163Sound(int32 *Wave, int Count) { - int P, V; - - for (P = 7; P >= (7 - GetNumberOfChannels()); P--) { - N163Channel *channel = &N163Snd[P]; - int channelOffset = 0x40 + (P * 8); - - if ((IRAM[FREQ_H + channelOffset] & 0xE0) && (IRAM[VOLUME + channelOffset] & 0xF)) { - int32 vco = channel->vcount; - - uint32 phase = GetPhase(P); - uint32 freq = GetFrequency(P); - uint16 length = GetWaveLength(P); - uint8 offset = GetWaveAddress(P); - uint32 volume = GetVolume(P); - - int32 inc; - - if (!freq) { - continue; - } - - inc = (long double)((int64)FSettings.SndRate << 15) / - ((long double)freq * 21477272 / - ((long double)0x400000 * (GetNumberOfChannels() + 1) * 45)); - - for (V = 0; V < Count * 16; V++) { - if (vco >= inc) { - vco -= inc; - channel->PlayIndex++; - if (channel->PlayIndex >= length) { - channel->PlayIndex = 0; - } - channel->output = GetSample( - channel->PlayIndex + offset, - volume, 19); - } - vco += 0x8000; - Wave[V >> 4] += GetOutput(SND_N163, channel->output); - } - channel->vcount = vco; - } - } -} - -static int dwave = 0; - -static void N163Sound(int Count) { - int32 z, a; - - z = ((SOUNDTS << 16) / soundtsinc) >> 4; - a = z - dwave; - - if (a) { - DoN163Sound(&Wave[dwave], a); - } - - dwave = 0; -} - -static void N163SoundHack(void) { - int32 z, a; - - if (FSettings.soundq >= 1) { - DoN163SoundHQ(); - return; - } - - z = ((SOUNDTS << 16) / soundtsinc) >> 4; - a = z - dwave; - - if (a) { - DoN163Sound(&Wave[dwave], a); - } - - dwave += a; -} - -DECLFR(N163Sound_Read) { - uint8 ret = IRAM[ramPos]; -/* Maybe I should call N163SoundHack() here? */ -#ifdef FCEUDEF_DEBUGGER - if (!fceuindbg) -#endif - ramPos = (ramPos + autoInc) & 0x7F; - return ret; -} - -DECLFW(N163Sound_Write) { - switch (A & 0xF800) { - case 0x4800: - if (ramPos & 0x40) { - if (FSettings.SndRate) { - N163SoundHack(); - GameExpSound[SND_N163].Fill = N163Sound; - GameExpSound[SND_N163].HiFill = DoN163SoundHQ; - GameExpSound[SND_N163].HiSync = SyncHQ; - } - } - IRAM[ramPos] = V; - ramPos = (ramPos + autoInc) & 0x7F; - break; - case 0xF800: - ramPos = V & 0x7F; - autoInc = (V & 0x80) >> 7; - break; - } -} - -uint8 *GetIRAM_ptr(void) { - return IRAM; -} - -uint32 GetIRAM_size(void) { - return sizeof(IRAM); -} - -static void N163SC(void) { - if (FSettings.SndRate) { - int i; - for (i = 0; i < 8; i++) { - memset(&N163Snd[i].vcount, 0, sizeof(N163Snd[i].vcount)); - memset(&N163Snd[i].PlayIndex, 0, sizeof(N163Snd[i].PlayIndex)); - } - CVBC = 0; - ramPos = 0; - } -} - -void N163Sound_ESI(void) { - GameExpSound[SND_N163].RChange = N163SC; - N163SC(); - - if (iNESCart.battery) { - memset(IRAM, 0, sizeof(IRAM)); - } else { - FCEU_MemoryRand(IRAM, sizeof(IRAM)); - } -} - -void N163Sound_AddStateInfo(void) { - AddExState(IRAM, 0x80, 0, "IRAM"); - AddExState(&CVBC, 4, 0, "BC00"); - AddExState(&ramPos, 1, 0, "INDX"); - AddExState(&autoInc, 1, 0, "INCR"); - - AddExState(&N163Snd[0].vcount, 4, 0, "C0VC"); - AddExState(&N163Snd[0].PlayIndex, 4, 0, "C0PI"); - AddExState(&N163Snd[0].output, 2, 0, "C0OP"); - - AddExState(&N163Snd[1].vcount, 4, 0, "C1VC"); - AddExState(&N163Snd[1].PlayIndex, 4, 0, "C1PI"); - AddExState(&N163Snd[1].output, 2, 0, "C1OP"); - - AddExState(&N163Snd[2].vcount, 4, 0, "C2VC"); - AddExState(&N163Snd[2].PlayIndex, 4, 0, "C2PI"); - AddExState(&N163Snd[2].output, 2, 0, "C2OP"); - - AddExState(&N163Snd[3].vcount, 4, 0, "C3VC"); - AddExState(&N163Snd[3].PlayIndex, 4, 0, "C3PI"); - AddExState(&N163Snd[3].output, 2, 0, "C3OP"); - - AddExState(&N163Snd[4].vcount, 4, 0, "C4VC"); - AddExState(&N163Snd[4].PlayIndex, 4, 0, "C4PI"); - AddExState(&N163Snd[4].output, 2, 0, "C4OP"); - - AddExState(&N163Snd[5].vcount, 4, 0, "C5VC"); - AddExState(&N163Snd[5].PlayIndex, 4, 0, "C5PI"); - AddExState(&N163Snd[5].output, 2, 0, "C5OP"); - - AddExState(&N163Snd[6].vcount, 4, 0, "C6VC"); - AddExState(&N163Snd[6].PlayIndex, 4, 0, "C6PI"); - AddExState(&N163Snd[6].output, 2, 0, "C6OP"); - - AddExState(&N163Snd[7].vcount, 4, 0, "C7VC"); - AddExState(&N163Snd[7].PlayIndex, 4, 0, "C7PI"); - AddExState(&N163Snd[7].output, 2, 0, "C7OP"); -} diff --git a/src/mappers/sound/n163sound.h b/src/mappers/sound/n163sound.h deleted file mode 100644 index 3d1cbe02f..000000000 --- a/src/mappers/sound/n163sound.h +++ /dev/null @@ -1,32 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _N163_SOUND_H -#define _N163_SOUND_H - -void N163Sound_ESI(void); -DECLFR(N163Sound_Read); -DECLFW(N163Sound_Write); -void N163Sound_AddStateInfo(void); - -uint8 *GetIRAM_ptr(void); /* pointer to internal RAM */ -uint32 GetIRAM_size(void); - -#endif /* _N163_SOUND_H */ diff --git a/src/mappers/sound/s5bsound.c b/src/mappers/sound/s5bsound.c deleted file mode 100644 index 207fe41f6..000000000 --- a/src/mappers/sound/s5bsound.c +++ /dev/null @@ -1,324 +0,0 @@ - -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* SUNSOFT-5B Sound */ - -#include "mapinc.h" -#include "s5bsound.h" - -#if 0 /* remove comment to use old S5B emulation */ -#define USE_OLD_SB5 -#endif - -#ifndef USE_OLD_SB5 -#define USE_EMU2149 -#endif - -#ifdef USE_EMU2149 -#include "emu2149.h" - -static int32 dwave = 0; -static PSG *psg_chip = NULL; - -static void PSG_fillbuf(PSG *ssg, int32 *buf, int32 len, int shift) { - while (len > 0) { - *buf += (GetOutput(SND_S5B, PSG_calc(psg_chip) << shift)); - buf++; - len--; - } -} - -static void UpdatePSGNEO(int32 *buf, int Count) { - PSG_fillbuf(psg_chip, buf, Count, 4); -} - -static void UpdatePSG(int Count) { - int32 z, a; - z = ((SOUNDTS << 16) / soundtsinc) >> 4; - a = z - dwave; - if (a) { - PSG_fillbuf(psg_chip, &Wave[dwave], a, 1); - } - dwave = 0; -} - -DECLFW(S5BSound_Write) { - if (!psg_chip) { - return; - } - - switch (A & 0xE000) { - case 0xC000: - PSG_writeIO(psg_chip, 0, V); - break; - case 0xE000: - GameExpSound[SND_S5B].Fill = UpdatePSG; - GameExpSound[SND_S5B].NeoFill = UpdatePSGNEO; - PSG_writeIO(psg_chip, 1, V); - break; - } -} - -static void S5BSound_SC(void) { - if (psg_chip) { - PSG_setRate(psg_chip, FSettings.SndRate ? FSettings.SndRate : 44100); - PSG_setVolumeMode(psg_chip, 1); - PSG_reset(psg_chip); - } -} - -static void S5BSound_KILL(void) { - if (psg_chip) { - PSG_delete(psg_chip); - psg_chip = NULL; - } -} - -void S5BSound_ESI(void) { - if (!(psg_chip = PSG_new(3579545 / 4, FSettings.SndRate ? FSettings.SndRate : 44100))) { - return; - } - - GameExpSound[SND_S5B].RChange = S5BSound_SC; - GameExpSound[SND_S5B].Kill = S5BSound_KILL; - - S5BSound_SC(); -} - -void S5BSound_AddStateInfo(void) { - if (!psg_chip) { - return; - } - - /* Sound states */ - AddExState(psg_chip->reg, sizeof(psg_chip->reg), 0, "REG"); - - AddExState(psg_chip->count, sizeof(psg_chip->count), 0, "PCNT"); - AddExState(psg_chip->volume, sizeof(psg_chip->volume), 0, "PVOL"); - AddExState(psg_chip->edge, sizeof(psg_chip->edge), 0, "EDGE"); - AddExState(psg_chip->freq, sizeof(psg_chip->freq), 0, "FREQ"); - AddExState(psg_chip->tmask, sizeof(psg_chip->tmask), 0, "TMSK"); - AddExState(psg_chip->nmask, sizeof(psg_chip->nmask), 0, "NMSK"); - - AddExState(&psg_chip->env_ptr, sizeof(psg_chip->env_ptr), 0, "PTR"); - AddExState(&psg_chip->env_face, sizeof(psg_chip->env_face), 0, "FACE"); - - AddExState(&psg_chip->env_continue, sizeof(psg_chip->env_continue), 0, "CONT"); - AddExState(&psg_chip->env_attack, sizeof(psg_chip->env_attack), 0, "ATTK"); - AddExState(&psg_chip->env_alternate, sizeof(psg_chip->env_alternate), 0, "ALT"); - AddExState(&psg_chip->env_hold, sizeof(psg_chip->env_hold), 0, "HOLD"); - AddExState(&psg_chip->env_pause, sizeof(psg_chip->env_pause), 0, "PAUS"); - - AddExState(&psg_chip->env_freq, sizeof(psg_chip->env_freq), 0, "EFRQ"); - AddExState(&psg_chip->env_count, sizeof(psg_chip->env_count), 0, "ECNT"); - - AddExState(&psg_chip->noise_seed, sizeof(psg_chip->noise_seed), 0, "NSED"); - AddExState(&psg_chip->noise_scaler, sizeof(psg_chip->noise_scaler), 0, "NSCL"); - AddExState(&psg_chip->noise_count, sizeof(psg_chip->noise_count), 0, "NCNT"); - AddExState(&psg_chip->noise_freq, sizeof(psg_chip->noise_freq), 0, "NFRQ"); -} - -#else /* !USE_EMU2149 */ -static void (*sfun[3])(void); -static uint8 sndcmd, sreg[14]; - -static int32 vcount[3]; -static int32 dcount[3]; -static int32 CAYBC[3]; - -static void AYSound(int Count); -static void AYSoundHQ(void); -static void AYHiSync(int ts); -static void DoAYSQ(int x); -static void DoAYSQHQ(int x); - -static void DoAYSQ(int x) { - int32 freq = ((sreg[x << 1] | ((sreg[(x << 1) + 1] & 15) << 8)) + 1) << (4 + 17); - int32 amp = (sreg[0x8 + x] & 15) << 2; - int32 start, end; - int V; - - amp += amp >> 1; - amp = GetOutput(SND_S5B, amp); - - start = CAYBC[x]; - end = (SOUNDTS << 16) / soundtsinc; - if (end <= start) - return; - CAYBC[x] = end; - - if (amp && !(sreg[0x7] & (1 << x))) { - for (V = start; V < end; V++) { - if (dcount[x]) - Wave[V >> 4] += amp; - vcount[x] -= nesincsize; - while (vcount[x] <= 0) { - dcount[x] ^= 1; - vcount[x] += freq; - } - } - } -} - -static void DoAYSQHQ(int x) { - uint32 V; - int32 freq = ((sreg[x << 1] | ((sreg[(x << 1) + 1] & 15) << 8)) + 1) << 4; - int32 amp = (sreg[0x8 + x] & 15) << 6; - - amp += amp >> 1; - amp = GetOutput(SND_S5B, amp); - - if (!(sreg[0x7] & (1 << x))) { - for (V = CAYBC[x]; V < SOUNDTS; V++) { - if (dcount[x]) - WaveHi[V] += amp; - vcount[x]--; - if (vcount[x] <= 0) { - dcount[x] ^= 1; - vcount[x] = freq; - } - } - } - CAYBC[x] = SOUNDTS; -} - -static void DoAYSQ1(void) { - DoAYSQ(0); -} - -static void DoAYSQ2(void) { - DoAYSQ(1); -} - -static void DoAYSQ3(void) { - DoAYSQ(2); -} - -static void DoAYSQ1HQ(void) { - DoAYSQHQ(0); -} - -static void DoAYSQ2HQ(void) { - DoAYSQHQ(1); -} - -static void DoAYSQ3HQ(void) { - DoAYSQHQ(2); -} - -static void AYSound(int Count) { - DoAYSQ1(); - DoAYSQ2(); - DoAYSQ3(); - CAYBC[0] = Count; - CAYBC[1] = Count; - CAYBC[2] = Count; -} - -static void AYSoundHQ(void) { - DoAYSQ1HQ(); - DoAYSQ2HQ(); - DoAYSQ3HQ(); -} - -static void AYHiSync(int32 ts) { - CAYBC[0] = ts; - CAYBC[1] = ts; - CAYBC[2] = ts; -} - -DECLFW(S5BSound_Write) { - switch (A & 0xE000) { - case 0xC000: - sndcmd = V & 0x0F; - break; - case 0xE000: - GameExpSound[SND_S5B].Fill = AYSound; - GameExpSound[SND_S5B].HiFill = AYSoundHQ; - GameExpSound[SND_S5B].HiSync = AYHiSync; - switch (sndcmd) { - case 0: - case 1: - case 8: - if (sfun[0]) { - sfun[0](); - } - break; - case 2: - case 3: - case 9: - if (sfun[1]) { - sfun[1](); - } - break; - case 4: - case 5: - case 10: - if (sfun[2]) { - sfun[2](); - } - break; - case 7: - if (sfun[0]) { - sfun[0](); - } - if (sfun[1]) { - sfun[1](); - } - break; - } - sreg[sndcmd] = V; - break; - } -} - -static void S5BSound_SC(void) { - memset(dcount, 0, sizeof(dcount)); - memset(vcount, 0, sizeof(vcount)); - memset(CAYBC, 0, sizeof(CAYBC)); - if (FSettings.SndRate) { - if (FSettings.soundq >= 1) { - sfun[0] = DoAYSQ1HQ; - sfun[1] = DoAYSQ2HQ; - sfun[2] = DoAYSQ3HQ; - } else { - sfun[0] = DoAYSQ1; - sfun[1] = DoAYSQ2; - sfun[2] = DoAYSQ3; - } - } else { - memset(sfun, 0, sizeof(sfun)); - } -} - -void S5BSound_ESI(void) { - GameExpSound[SND_S5B].RChange = S5BSound_SC; - S5BSound_SC(); -} - -void S5BSound_AddStateInfo(void) { - AddExState(&sndcmd, 1, 0, "SCMD"); - AddExState(sreg, 14, 0, "SREG"); - AddExState(dcount, 12, 0, "DCNT"); - AddExState(vcount, 12, 0, "VCNT"); - AddExState(CAYBC, 12, 0, "BC00"); -} -#endif diff --git a/src/mappers/sound/s5bsound.h b/src/mappers/sound/s5bsound.h deleted file mode 100644 index f6e785568..000000000 --- a/src/mappers/sound/s5bsound.h +++ /dev/null @@ -1,28 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _FME7_SOUND_H -#define _FME7_SOUND_H - -void S5BSound_ESI(void); -DECLFW(S5BSound_Write); -void S5BSound_AddStateInfo(void); - -#endif /* _FME7_SOUND_H */ diff --git a/src/mappers/sound/vrc6sound.c b/src/mappers/sound/vrc6sound.c deleted file mode 100644 index bcba274b4..000000000 --- a/src/mappers/sound/vrc6sound.c +++ /dev/null @@ -1,351 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * VRC-6 Sound - * - */ - -#include "mapinc.h" -#include "vrc6sound.h" - -enum { SQUARE1, SQUARE2, SAW }; - -typedef struct __VRC6SQUARE { - /* regs */ - uint8 volume; - uint8 duty; - uint8 mode; - uint8 enabled; - uint16 freq; - - /* timers */ - uint8 dcount; - int32 vcount; - int32 cvbc; -} VRC6SQUARE; - -typedef struct __VRC6SAW { - /* regs */ - uint8 accumrate; - uint8 enabled; - uint16 freq; - - uint8 phaseacc; - - /* timers */ - uint8 dcount; - int32 vcount; - int32 cvbc; -} VRC6SAW; - -typedef struct __VRC6SOUND { - VRC6SQUARE square[2]; - VRC6SAW saw; - uint8 haltsound; - uint8 freqshift; -} VR6SOUND; - -static VR6SOUND VRC6Sound; - -static void (*sfun[3])(void); - -static INLINE void DoSQV(VRC6SQUARE *channel) { - int32 start, end, V; - - start = channel->cvbc; - end = (SOUNDTS << 16) / soundtsinc; - if (end <= start) { - return; - } - channel->cvbc = end; - - if (!VRC6Sound.haltsound && channel->enabled) { - int32 amp = ((channel->volume << 8) * 6 / 8) >> 4; - int32 out = GetOutput(SND_VRC6, amp); - - for (V = start; V < end; V++) { - channel->vcount -= nesincsize; - while (channel->vcount <= 0) { - channel->dcount = (channel->dcount + 1) & 0x0F; - channel->vcount += ((channel->freq >> VRC6Sound.freqshift) + 1) << 17; - } - if (channel->mode || (channel->dcount <= channel->duty)) { - Wave[V >> 4] += out; - } - } - } -} - -static void DoSQV1(void) { - DoSQV(&VRC6Sound.square[0]); -} - -static void DoSQV2(void) { - DoSQV(&VRC6Sound.square[1]); -} - -static void DoSawV(void) { - int32 start, end, V; - - start = VRC6Sound.saw.cvbc; - end = (SOUNDTS << 16) / soundtsinc; - if (end <= start) { - return; - } - VRC6Sound.saw.cvbc = end; - - if (VRC6Sound.saw.enabled) { - int32 out; - - for (V = start; V < end; V++) { - VRC6Sound.saw.vcount -= nesincsize; - while (VRC6Sound.saw.vcount <= 0) { - VRC6Sound.saw.dcount++; - VRC6Sound.saw.dcount %= 14; - if (VRC6Sound.saw.dcount == 0) { - VRC6Sound.saw.phaseacc = 0; - } else if (!(VRC6Sound.saw.dcount & 0x01)) { - VRC6Sound.saw.phaseacc += VRC6Sound.saw.accumrate; - } - VRC6Sound.saw.vcount += ((VRC6Sound.saw.freq >> VRC6Sound.freqshift) + 1) << 17; - } - out = (((VRC6Sound.saw.phaseacc >> 3) & 0x1F) << 3) * 6 / 8; - Wave[V >> 4] += GetOutput(SND_VRC6, out); - } - } -} - -static INLINE void DoSQVHQ(VRC6SQUARE *channel) { - int32 V; - - if (channel->enabled) { - int32 amp = (channel->volume << 8) * 6 / 8; - int32 out = GetOutput(SND_VRC6, amp); - - for (V = channel->cvbc; V < (int32)SOUNDTS; V++) { - channel->vcount--; - if (channel->vcount <= 0) { - channel->dcount++; - channel->dcount &= 0x0F; - channel->vcount = (channel->freq >> VRC6Sound.freqshift) + 1; - } - if ((channel->mode || (channel->dcount > channel->duty))) { - WaveHi[V] += out; - } - } - } - channel->cvbc = SOUNDTS; -} - -static void DoSQV1HQ(void) { - DoSQVHQ(&VRC6Sound.square[0]); -} - -static void DoSQV2HQ(void) { - DoSQVHQ(&VRC6Sound.square[1]); -} - -static void DoSawVHQ(void) { - int32 V; - - if (VRC6Sound.saw.enabled) { - int32 out = 0; - - for (V = VRC6Sound.saw.cvbc; V < (int32)SOUNDTS; V++) { - VRC6Sound.saw.vcount--; - while (VRC6Sound.saw.vcount <= 0) { - VRC6Sound.saw.dcount++; - VRC6Sound.saw.dcount %= 14; - if (VRC6Sound.saw.dcount == 0) { - VRC6Sound.saw.phaseacc = 0; - } else if (!(VRC6Sound.saw.dcount & 0x01)) { - VRC6Sound.saw.phaseacc += VRC6Sound.saw.accumrate; - } - VRC6Sound.saw.vcount += ((VRC6Sound.saw.freq >> VRC6Sound.freqshift) + 1) << 0; - } - out = (((VRC6Sound.saw.phaseacc >> 3) & 0x1F) << 7) * 6 / 8; - WaveHi[V] += GetOutput(SND_VRC6, out); - } - } - VRC6Sound.saw.cvbc = SOUNDTS; -} - -static void VRC6RunSound(int Count) { - DoSQV1(); - DoSQV2(); - DoSawV(); - VRC6Sound.square[0].cvbc = Count; - VRC6Sound.square[1].cvbc = Count; - VRC6Sound.saw.cvbc = Count; - -} - -static void VRC6RunSoundHQ(void) { - DoSQV1HQ(); - DoSQV2HQ(); - DoSawVHQ(); -} - -static void VRC6SyncHQ(int32 ts) { - VRC6Sound.square[0].cvbc = ts; - VRC6Sound.square[1].cvbc = ts; - VRC6Sound.saw.cvbc = ts; -} - -static void VRC6Square_Write(VRC6SQUARE *channel, uint8 reg, uint8 V) { - switch (reg & 0x03) { - case 0: - channel->volume = V & 0x0F; - channel->duty = (V & 0x70) >> 4; - channel->mode = (V & 0x80) == 0x80; - break; - - case 1: - channel->freq = (channel->freq & 0xF00) | V; - break; - - case 2: - channel->freq = (channel->freq & 0xFF) | ((V & 0x0F) << 8); - channel->enabled = (V & 0x80) == 0x80; - if (!channel->enabled) { - channel->dcount = 0; - } - break; - } -} - -DECLFW(VRC6Sound_Write) { - switch (A & 0xF003) { - case 0x9000: - case 0x9001: - case 0x9002: - VRC6Square_Write(&VRC6Sound.square[0], A & 0x03, V); - if (sfun[SQUARE1]) { - sfun[SQUARE1](); - } - break; - - case 0x9003: - VRC6Sound.haltsound = (V & 0x01) == 0x01; - if (V & 0x04) { - VRC6Sound.freqshift = 8; - } else if (V & 0x02) { - VRC6Sound.freqshift = 4; - } else { - VRC6Sound.freqshift = 0; - } - break; - - case 0xA000: - case 0xA001: - case 0xA002: - VRC6Square_Write(&VRC6Sound.square[1], A & 0x03, V); - if (sfun[SQUARE2]) { - sfun[SQUARE2](); - } - break; - - case 0xB000: - case 0xB001: - case 0xB002: - switch (A & 0x03) { - case 0: - VRC6Sound.saw.accumrate = V & 0x3F; - break; - - case 1: - VRC6Sound.saw.freq = (VRC6Sound.saw.freq & 0xF00) | V; - break; - - case 2: - VRC6Sound.saw.freq = (VRC6Sound.saw.freq & 0xFF) | ((V & 0x0F) << 8); - VRC6Sound.saw.enabled = (V & 0x80) == 0x80; - if (!VRC6Sound.saw.enabled) { - VRC6Sound.saw.dcount = 0; - } - break; - } - if (sfun[SAW]) { - sfun[SAW](); - } - break; - } -} - -static void VRC6Sound_SC(void) { - GameExpSound[SND_VRC6].Fill = VRC6RunSound; - GameExpSound[SND_VRC6].HiFill = VRC6RunSoundHQ; - GameExpSound[SND_VRC6].HiSync = VRC6SyncHQ; - - VRC6Sound.square[0].vcount = 1; - VRC6Sound.square[1].vcount = 1; - VRC6Sound.saw.vcount = 1; - - if (FSettings.SndRate) { - if (FSettings.soundq >= 1) { - sfun[SQUARE1] = DoSQV1HQ; - sfun[SQUARE2] = DoSQV2HQ; - sfun[SAW] = DoSawVHQ; - } else { - sfun[SQUARE1] = DoSQV1; - sfun[SQUARE2] = DoSQV2; - sfun[SAW] = DoSawV; - } - } else { - memset(sfun, 0, sizeof(sfun)); - } -} - -void VRC6Sound_ESI(void) { - memset(&VRC6Sound, 0, sizeof(VRC6Sound)); - GameExpSound[SND_VRC6].RChange = VRC6Sound_SC; - VRC6Sound_SC(); -} - -void VRC6Sound_AddStateInfo(void) { - AddExState(&VRC6Sound.haltsound, 1, 0, "HLTS"); - AddExState(&VRC6Sound.freqshift, 1, 0, "FRSH"); - - AddExState(&VRC6Sound.square[0].enabled, 1, 0, "S0EN"); - AddExState(&VRC6Sound.square[0].volume, 1, 0, "S0VL"); - AddExState(&VRC6Sound.square[0].freq, 2, 0, "S0FQ"); - AddExState(&VRC6Sound.square[0].duty, 1, 0, "S0DT"); - AddExState(&VRC6Sound.square[0].mode, 1, 0, "S0MD"); - AddExState(&VRC6Sound.square[0].dcount, 1, 0, "S0DC"); - AddExState(&VRC6Sound.square[0].vcount, 4, 0, "S0VC"); - AddExState(&VRC6Sound.square[0].cvbc, 4, 0, "S0BC"); - - AddExState(&VRC6Sound.square[1].enabled, 1, 0, "S1EN"); - AddExState(&VRC6Sound.square[1].volume, 1, 0, "S1VL"); - AddExState(&VRC6Sound.square[1].freq, 2, 0, "S1FQ"); - AddExState(&VRC6Sound.square[1].duty, 1, 0, "S1DT"); - AddExState(&VRC6Sound.square[1].mode, 1, 0, "S1MD"); - AddExState(&VRC6Sound.square[1].dcount, 1, 0, "S1DC"); - AddExState(&VRC6Sound.square[1].vcount, 4, 0, "S1VC"); - AddExState(&VRC6Sound.square[1].cvbc, 4, 0, "S1BC"); - - AddExState(&VRC6Sound.saw.enabled, 1, 0, "SWEN"); - AddExState(&VRC6Sound.saw.accumrate, 1, 0, "SWAR"); - AddExState(&VRC6Sound.saw.phaseacc, 1, 0, "SWAC"); - AddExState(&VRC6Sound.saw.freq, 2, 0, "SWFR"); - AddExState(&VRC6Sound.saw.dcount, 1, 0, "SWDC"); - AddExState(&VRC6Sound.saw.vcount, 4, 0, "SWVC"); - AddExState(&VRC6Sound.saw.cvbc, 4, 0, "SWBC"); -} diff --git a/src/mappers/sound/vrc6sound.h b/src/mappers/sound/vrc6sound.h deleted file mode 100644 index 31b7eb7f2..000000000 --- a/src/mappers/sound/vrc6sound.h +++ /dev/null @@ -1,28 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _VRC6_SOUND_H -#define _VRC6_SOUND_H - -void VRC6Sound_ESI(void); -DECLFW(VRC6Sound_Write); -void VRC6Sound_AddStateInfo(void); - -#endif /* _VRC6_SOUND_H */ diff --git a/src/mappers/sound/vrc7sound.c b/src/mappers/sound/vrc7sound.c deleted file mode 100644 index 1a8f07ac9..000000000 --- a/src/mappers/sound/vrc7sound.c +++ /dev/null @@ -1,150 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" -#include "emu2413.h" -#include "vrc7sound.h" - -static int32 dwave = 0; - -static OPLL *chip = NULL; - -static void OPLL_fillbuf(OPLL *opll, int32 *buf, int32 len, int shift) { - while (len > 0) { - *buf += GetOutput(SND_VRC7, (OPLL_calc(chip) + 32768)) << shift; - buf++; - len--; - } -} - -static void UpdateOPLNEO(int32 *buf, int Count) { - OPLL_fillbuf(chip, buf, Count, 4); -} - -static void UpdateOPL(int Count) { - int32 z, a; - z = ((SOUNDTS << 16) / soundtsinc) >> 4; - a = z - dwave; - if (a) { - OPLL_fillbuf(chip, &Wave[dwave], a, 1); - } - dwave = 0; -} - -DECLFW(VRC7Sound_Write) { - if (!chip) { - return; - } - - switch (A & 0xF030) { - case 0x9010: - OPLL_writeIO(chip, 0, V); - break; - case 0x9030: - GameExpSound[SND_VRC7].Fill = UpdateOPL; - GameExpSound[SND_VRC7].NeoFill = UpdateOPLNEO; - OPLL_writeIO(chip, 1, V); - break; - } -} - -static void VRC7SC(void) { - if (chip) { - OPLL_setChipType(chip, OPLL_VRC7_TONE); - OPLL_setRate(chip, FSettings.SndRate ? FSettings.SndRate : 44100); - OPLL_resetPatch(chip, OPLL_VRC7_TONE); - } -} - -static void VRC7SKill(void) { - if (chip) { - OPLL_delete(chip); - chip = NULL; - } -} - -void VRC7Sound_ESI(void) { - if (!(chip = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 44100))) { - return; - } - - GameExpSound[SND_VRC7].RChange = VRC7SC; - GameExpSound[SND_VRC7].Kill = VRC7SKill; - - VRC7SC(); -} - -void VRC7Sound_AddStateInfo(void) { - if (!chip) { - return; - } - - /* Sound states */ - AddExState(&chip->clk, sizeof(chip->clk), 0, "CLK7"); - AddExState(&chip->rate, sizeof(chip->rate), 0, "RATE"); - - AddExState(&chip->chip_type, sizeof(chip->chip_type), 0, "CHIP"); - - AddExState(&chip->adr, sizeof(chip->adr), 0, "ADR7"); - - AddExState(&chip->inp_step, sizeof(chip->inp_step), 0, "ISTP"); - AddExState(&chip->out_step, sizeof(chip->out_step), 0, "OSTP"); - AddExState(&chip->out_time, sizeof(chip->out_time), 0, "OTME"); - - AddExState(chip->reg, sizeof(chip->reg), 0, "REG7"); - AddExState(&chip->test_flag, sizeof(chip->test_flag), 0, "TFLG"); - AddExState(&chip->slot_key_status, sizeof(chip->slot_key_status), 0, "SKST"); - AddExState(&chip->rhythm_mode, sizeof(chip->rhythm_mode), 0, "RMOD"); - - AddExState(&chip->eg_counter, sizeof(chip->eg_counter), 0, "ECTR"); - - AddExState(&chip->pm_phase, sizeof(chip->pm_phase), 0, "PMPH"); - AddExState(&chip->am_phase, sizeof(chip->am_phase), 0, "AMPH"); - - AddExState(&chip->lfo_am, sizeof(chip->lfo_am), 0, "LFO7"); - - AddExState(&chip->noise, sizeof(chip->noise), 0, "NOIS"); - AddExState(&chip->short_noise, sizeof(chip->short_noise), 0, "SNOS"); - - AddExState(chip->patch_number, sizeof(chip->patch_number), 0, "PTNM"); - - /* VRC7 only uses 12 slots */ - AddExState(&chip->slot[0], sizeof(chip->slot[0]), 0, "SL00"); - AddExState(&chip->slot[1], sizeof(chip->slot[1]), 0, "SL01"); - AddExState(&chip->slot[2], sizeof(chip->slot[2]), 0, "SL02"); - AddExState(&chip->slot[3], sizeof(chip->slot[3]), 0, "SL03"); - AddExState(&chip->slot[4], sizeof(chip->slot[4]), 0, "SL04"); - AddExState(&chip->slot[5], sizeof(chip->slot[5]), 0, "SL05"); - AddExState(&chip->slot[6], sizeof(chip->slot[6]), 0, "SL06"); - AddExState(&chip->slot[7], sizeof(chip->slot[7]), 0, "SL07"); - AddExState(&chip->slot[8], sizeof(chip->slot[8]), 0, "SL08"); - AddExState(&chip->slot[9], sizeof(chip->slot[9]), 0, "SL09"); - AddExState(&chip->slot[10], sizeof(chip->slot[10]), 0, "SL10"); - AddExState(&chip->slot[11], sizeof(chip->slot[11]), 0, "SL11"); - - AddExState(&chip->mask, sizeof(chip->mask), 0, "MASK"); - - AddExState(chip->ch_out, sizeof(chip->ch_out), 0, "CHOU"); - AddExState(chip->mix_out, sizeof(chip->mix_out), 0, "MIXO"); - - /* custom patches */ - AddExState(&chip->patch[0], sizeof(chip->patch[0]), 0, "PAT0"); - AddExState(&chip->patch[1], sizeof(chip->patch[1]), 0, "PAT1"); -} diff --git a/src/mappers/sound/vrc7sound.h b/src/mappers/sound/vrc7sound.h deleted file mode 100644 index a28e396a2..000000000 --- a/src/mappers/sound/vrc7sound.h +++ /dev/null @@ -1,28 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef _VRC7_SOUND_H -#define _VRC7_SOUND_H - -void VRC7Sound_ESI(void); -DECLFW(VRC7Sound_Write); -void VRC7Sound_AddStateInfo(void); - -#endif /* _VRC7_SOUND_H */ diff --git a/src/mappers/unif3Dblock.c b/src/mappers/unif3Dblock.c deleted file mode 100644 index 99d1aacbb..000000000 --- a/src/mappers/unif3Dblock.c +++ /dev/null @@ -1,109 +0,0 @@ -/* FCEUmm - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2007 CaH4e3 - * Copyright (C) 2023-2024 negativeExponent - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* NOTE: This only emulates the UNIF variant of 3D-Blocks */ - -#include "mapinc.h" - -static uint8 reg[4], IRQa; -static int16 IRQCount, IRQPause; - -static int16 Count = 0x0000; - -static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, - { &IRQa, 1, "IRQA" }, - { &IRQCount, 2, "IRQC" }, - { 0 } -}; - -static void Sync(void) { - setprg32(0x8000, 0); - setchr8(0); -} - -/* #define Count 0x1800 */ -#define Pause 0x010 - -static DECLFW(UNL3DBlockWrite) { - switch (A) { - /* 4800 32 */ - /* 4900 37 */ - /* 4a00 01 */ - /* 4e00 18 */ - case 0x4800: - reg[0] = V; - break; - case 0x4900: - reg[1] = V; - break; - case 0x4a00: - reg[2] = V; - break; - case 0x4e00: - reg[3] = V; - IRQCount = Count; - IRQPause = Pause; - IRQa = 1; - X6502_IRQEnd(FCEU_IQEXT); - break; - } -} - -static void UNL3DBlockPower(void) { - Sync(); - SetReadHandler(0x8000, 0xFFFF, CartBR); - SetWriteHandler(0x4800, 0x4E00, UNL3DBlockWrite); -} - -static void UNL3DBlockReset(void) { - Count += 0x10; - FCEU_printf("Count=%04x\n", Count); -} - -static void UNL3DBlockIRQHook(int a) { - if (IRQa) { - if (IRQCount > 0) { - IRQCount -= a; - } else { - if (IRQPause > 0) { - IRQPause -= a; - X6502_IRQBegin(FCEU_IQEXT); - } else { - IRQCount = Count; - IRQPause = Pause; - X6502_IRQEnd(FCEU_IQEXT); - } - } - } -} - -static void StateRestore(int version) { - Sync(); -} - -void UNL3DBlock_Init(CartInfo *info) { - info->Power = UNL3DBlockPower; - info->Reset = UNL3DBlockReset; - MapIRQHook = UNL3DBlockIRQHook; - GameStateRestore = StateRestore; - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/unifEt4320.c b/src/mappers/unifEt4320.c deleted file mode 100644 index bc000901f..000000000 --- a/src/mappers/unifEt4320.c +++ /dev/null @@ -1,154 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator -* -* Copyright notice for this file: -* Copyright (C) 2016 Cluster -* http://clusterrr.com -* clusterrr@clusterrr.com -* Copyright (C) 2023 -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* -MMC3-based multicart mapper with CHR RAM, CHR ROM and PRG RAM - -$6000-7FFF: A~[011xxxxx xxMRSBBB] Multicart reg -This register can only be written to if PRG-RAM is enabled and writable (see $A001) -and BBB = 000 (power on state) - -BBB = CHR+PRG block select bits (A19, A18, A17 for both PRG and CHR) -S = PRG block size & mirroring mode (0=128k with normal MMC3, 1=256k with TxSROM-like single-screen mirroring) -R = CHR mode (0=CHR ROM 1=CHR RAM) -M = CHR block size (0=256k 1=128k) -ignored when S is 0 for some reason - -Example Game: --------------------------- -7 in 1 multicart (Amarello, TMNT2, Contra, Ninja Cat, Ninja Crusaders, Rainbow Islands 2) -*/ - -/* NOTE: - * Appears similar to Mapper 327 but with mirroring similar to Mapper 118? - * Cannot find a cart to confirm this though -*/ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reg; - -static void BMC810131C_PW(uint16 A, uint16 V) { - uint16 mask = (reg & 0x08) ? 0x1F : 0x0F; - uint16 base = (reg << 4) & 0x70; - - setprg8(A, (base | (V & mask))); -} - -static void BMC810131C_CW(uint16 A, uint16 V) { - uint16 base = (reg << 7) & 0x380; - - if (reg & 0x10) { - setchr1r(0x10, A, V); - } else if ((reg & 0x20) && (reg & 0x08)) { - setchr1(A, (base | (V & 0xFF))); - } else { - setchr1(A, (base | (V & 0x7F))); - } -} - -static void BMC810131C_SyncMIRR(void) { - if (reg & 0x08) { - if (mmc3.cmd & 0x80) { - setntamem(NTARAM + 0x400 * ((mmc3.reg[2] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[3] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[4] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[5] >> 7) & 0x01), 1, 3); - } else { - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 0); - setntamem(NTARAM + 0x400 * ((mmc3.reg[0] >> 7) & 0x01), 1, 1); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 2); - setntamem(NTARAM + 0x400 * ((mmc3.reg[1] >> 7) & 0x01), 1, 3); - } - } else { - setmirror((mmc3.mirr & 0x01) ^ 0x01); - } -} - -static DECLFW(BMC810131C_Write) { - if (((mmc3.wram & 0xC0) == 0x80) && !(reg & 0x07)) { - reg = A & 0x3F; - MMC3_FixPRG(); - MMC3_FixCHR(); - } else { - CartBW(A, V); - } -} - -static DECLFW(BMC810131C_WriteCMD) { - switch (A & 0xE001) { - case 0x8001: - switch (mmc3.cmd & 0x07) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - mmc3.reg[mmc3.cmd & 0x07] = V; - MMC3_FixCHR(); - MMC3_FixMIR(); - break; - default: - MMC3_CMDWrite(A, V); - break; - } - break; - default: - MMC3_CMDWrite(A, V); - break; - } -} - -static void BMC810131C_Reset(void) { - reg = 0; - MMC3_Reset(); -} - -static void BMC810131C_Power(void) { - reg = 0; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, BMC810131C_Write); - SetWriteHandler(0x8000, 0x9FFF, BMC810131C_WriteCMD); -} - -static void BMC810131C_Close(void) { - MMC3_Close(); -} - -void BMC810131C_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_FixMIR = BMC810131C_SyncMIRR; - MMC3_pwrap = BMC810131C_PW; - MMC3_cwrap = BMC810131C_CW; - info->Power = BMC810131C_Power; - info->Reset = BMC810131C_Reset; - info->Close = BMC810131C_Close; - AddExState(®, 1, 0, "EXPR"); - - CHRRAMSIZE = 8192; - CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); - SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); - AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); -} diff --git a/src/mappers/unifFamicombox.c b/src/mappers/unifFamicombox.c deleted file mode 100644 index e4f78fe23..000000000 --- a/src/mappers/unifFamicombox.c +++ /dev/null @@ -1,115 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "mapinc.h" - -static uint8 regs[8]; - -static SFORMAT StateRegs[] = -{ - { regs, 8, "REGS" }, - { 0 } -}; - -static void Sync(void) { - setprg2r(0x10, 0x0800, 0); - setprg2r(0x10, 0x1000, 1); - setprg2r(0x10, 0x1800, 2); - setprg8r(0x10, 0x6000, 1); - setprg16(0x8000, 0); - setprg16(0xC000, ~0); - setchr8(0); -} - -#if 0 - static DECLFW(SSSNROMWrite) -{ - CartBW(A,V); -} -#endif - -static DECLFW(SSSNROMWrite) { -#if 0 - FCEU_printf("write %04x %02x\n",A,V); - regs[A&7] = V; -#endif -} - -static DECLFR(SSSNROMRead) { -/* FCEU_printf("read %04x\n",A); */ - switch (A & 7) { - case 0: return regs[0] = 0xff; /* clear all exceptions */ - case 2: return 0xc0; /* DIP selftest + freeplay */ - case 3: return 0x00; /* 0, 1 - attract - * 2 - * 4 - menu - * 8 - self check and game casette check - * 10 - lock? - * 20 - game title & count display - */ - case 7: return 0x22; /* TV type, key not turned, relay B */ - default: return 0; - } -} - -static void SSSNROMPower(void) { - regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0; - regs[7] = 0xff; - Sync(); - FCEU_MemoryRand(WRAM, WRAMSIZE); -/* SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite); */ - SetReadHandler(0x0800, 0x1FFF, CartBR); - SetWriteHandler(0x0800, 0x1FFF, CartBW); - SetReadHandler(0x5000, 0x5FFF, SSSNROMRead); - SetWriteHandler(0x5000, 0x5FFF, SSSNROMWrite); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); -} - -static void SSSNROMReset(void) { - regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0; -} - -static void SSSNROMClose(void) { -} - -static void SSSNROMIRQHook(void) { -/* X6502_IRQBegin(FCEU_IQEXT); */ -} - -static void StateRestore(int version) { - Sync(); -} - -void SSSNROM_Init(CartInfo *info) { - info->Reset = SSSNROMReset; - info->Power = SSSNROMPower; - info->Close = SSSNROMClose; - GameHBIRQHook = SSSNROMIRQHook; - GameStateRestore = StateRestore; - - WRAMSIZE = 16384; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); - AddExState(StateRegs, ~0, 0, NULL); -} diff --git a/src/mappers/unifKG256.c b/src/mappers/unifKG256.c deleted file mode 100644 index 70bd2e713..000000000 --- a/src/mappers/unifKG256.c +++ /dev/null @@ -1,111 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * - * Copyright (C) 2008 -2020 dragon2snow,loong2snow from www.nesbbs.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - */ - -#include "mapinc.h" - -static uint8 regs[4]; - -static SFORMAT StateRegs[] = -{ - { regs, 4, "REGS" }, - { 0 } -}; - -static void Sync(void) -{ - uint8 mirr; - int r = 0; - - if ((regs[1]) & 0x20) - r = 1; - if ((regs[1] >> 4) & 0x01) - { - setprg16(0x8000, (regs[1] & 0x07) | (r << 3)); - setprg16(0xC000, (regs[1] & 0x07) | (r << 3)); - setchr8((regs[0] & 0x07) | (r << 3)); - } - else - { - setprg32(0x8000, ((regs[1] >> 1) & 0x03) | (r << 2)); - setchr8((regs[2] & 0x01) | (r << 3)); - } - - mirr = (((regs[0] >> 4) & 0x1)); - - if (mirr) - setmirror(0); - else - setmirror(1); - -} - -static DECLFW(KG256WriteHi) { - regs[2] = V; - Sync(); -} - -static DECLFW(KG256WriteLo) { - regs[A & 0x03] = V; - Sync(); -} - -static void KG256Power(void) { - - regs[0] = 0; - regs[1] = 0; - regs[2] = 0; - regs[3] = 0; - - SetWriteHandler(0x8000, 0xFFFF, KG256WriteHi); - SetWriteHandler(0x6000, 0x7FFF, KG256WriteLo); - SetReadHandler(0x8000, 0xFFFF, CartBR); - - Sync(); - -} - -static void StateRestore(int version) { - Sync(); -} - -static void KG256Reset(void) { - - regs[0] = 0; - regs[1] = 0; - regs[2] = 0; - - Sync(); -} - -void KG256_Init(CartInfo *info) { - - Sync(); - - info->Power = KG256Power; - info->Reset = KG256Reset; - AddExState(StateRegs, ~0, 0, NULL); - GameStateRestore = StateRestore; -} - - - diff --git a/src/mappers/unifT2271.c b/src/mappers/unifT2271.c deleted file mode 100644 index 585e57da3..000000000 --- a/src/mappers/unifT2271.c +++ /dev/null @@ -1,101 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2008 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* T-227-1, 820632, MMC3 based, multimenu, 60000in1 (0010) dip switches */ - -#include "mapinc.h" -#include "mmc3.h" - -static uint8 reset_flag = 0x07; -static uint8 reg; - -static void BMCT2271CW(uint16 A, uint16 V) { - uint32 va = V; - if (reg & 0x20) { - va |= 0x200; - va |= (reg & 0x10) << 4; - } else { - va &= 0x7F; - va |= (reg & 0x18) << 4; - } - setchr1(A, va); -} - -static void BMCT2271PW(uint16 A, uint16 V) { - uint32 va = V & 0x3F; - if (reg & 0x20) { - va &= 0x1F; - va |= 0x40; - va |= (reg & 0x10) << 1; - } else { - va &= 0x0F; - va |= (reg & 0x18) << 1; - } - switch (reg & 3) { - case 0x00: setprg8(A, va); break; - case 0x02: - { - va = (va & 0xFD) | ((reg & 4) >> 1); - if (A < 0xC000) { - setprg16(0x8000, va >> 1); - setprg16(0xC000, va >> 1); - } - break; - } - case 0x01: - case 0x03: if (A < 0xC000) setprg32(0x8000, va >> 2); break; - } -} - -static DECLFW(BMCT2271LoWrite) { - if (!(reg & 0x80)) - reg = A & 0xFF; - MMC3_FixPRG(); - MMC3_FixCHR(); -} - -static DECLFR(BMCT2271HiRead) { - uint32 av = A; - if (reg & 0x40) av = (av & 0xFFF0) | reset_flag; - return CartBR(av); -} - -static void BMCT2271Reset(void) { - reg = 0x00; - reset_flag++; - reset_flag &= 0x0F; - MMC3_Reset(); -} - -static void BMCT2271Power(void) { - reg = 0x00; - MMC3_Power(); - SetWriteHandler(0x6000, 0x7FFF, BMCT2271LoWrite); - SetReadHandler(0x8000, 0xFFFF, BMCT2271HiRead); -} - -void BMCT2271_Init(CartInfo *info) { - MMC3_Init(info, 8, 0); - MMC3_pwrap = BMCT2271PW; - MMC3_cwrap = BMCT2271CW; - info->Power = BMCT2271Power; - info->Reset = BMCT2271Reset; - AddExState(®, 1, 0, "EXPR"); -} diff --git a/src/mappers/unifTransformer.c b/src/mappers/unifTransformer.c deleted file mode 100644 index 257149fd9..000000000 --- a/src/mappers/unifTransformer.c +++ /dev/null @@ -1,103 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2009 CaH4e3 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * All regs access only by READ - * - * 5000 - I/O - when read, 0 goes to tape output - * ---m3210 - * 3210 - lower scancode nibble - * m - tape input bit - * 5001 - I - * ----7654 - * 7654 - higher scancode nibble - * 5002 - I - reset scancode buffer, ready to new input - * 5004 - O - when read, 1 goes to tape output - * - */ - -#include "mapinc.h" - -char *GetKeyboard(void); - -static char *TransformerKeys, oldkeys[256]; -static int TransformerCycleCount, TransformerChar = 0; - -static void TransformerIRQHook(int a) { - TransformerCycleCount += a; - if (TransformerCycleCount >= 1000) { - uint32 i; - TransformerCycleCount -= 1000; - TransformerKeys = GetKeyboard(); - - for (i = 0; i < 256; i++) { - if (oldkeys[i] != TransformerKeys[i]) { - if (oldkeys[i] == 0) - TransformerChar = i; - else - TransformerChar = i | 0x80; - X6502_IRQBegin(FCEU_IQEXT); - memcpy((void*)&oldkeys[0], (void*)TransformerKeys, sizeof(oldkeys)); - break; - } - } - } -} - -static DECLFR(TransformerRead) { - uint8 ret = 0; - switch (A & 3) { - case 0: ret = TransformerChar & 15; break; - case 1: ret = (TransformerChar >> 4); break; - case 2: X6502_IRQEnd(FCEU_IQEXT); break; - case 4: break; - } - return ret; -} - -static void TransformerPower(void) { - setprg8r(0x10, 0x6000, 0); - setprg16(0x8000, 0); - setprg16(0xC000, ~0); - setchr8(0); - - SetReadHandler(0x5000, 0x5004, TransformerRead); - SetReadHandler(0x6000, 0x7FFF, CartBR); - SetWriteHandler(0x6000, 0x7FFF, CartBW); - SetReadHandler(0x8000, 0xFFFF, CartBR); - FCEU_CheatAddRAM(WRAMSIZE >> 10, 0x6000, WRAM); - - MapIRQHook = TransformerIRQHook; -} - -static void TransformerClose(void) { -} - -void Transformer_Init(CartInfo *info) { - info->Power = TransformerPower; - info->Close = TransformerClose; - - WRAMSIZE = 8192; - WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); - SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); - if (info->battery) { - info->SaveGame[0] = WRAM; - info->SaveGameLen[0] = WRAMSIZE; - } - AddExState(WRAM, WRAMSIZE, 0, "WRAM"); -} diff --git a/src/ppu.c b/src/ppu.c index a71cac299..628e56495 100644 --- a/src/ppu.c +++ b/src/ppu.c @@ -92,10 +92,6 @@ static uint8 ppudead = 1; static uint8 kook = 0; int fceuindbg = 0; -uint8 QTAIHack = 0; /* bool */ -uint8 qtaintramreg = 0; -uint8 QTAINTRAM[0x800]; - int MMC5Hack = 0, PEC586Hack = 0; uint32 MMC5HackVROMMask = 0; uint8 *MMC5HackExNTARAMPtr = 0; @@ -139,8 +135,6 @@ uint8 UPALRAM[0x03];/* for 0x4/0x8/0xC addresses in palette, the ones in #define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] #define VRAMADR(V) &VPage[(V) >> 10][(V)] -#if 0 -/* moved to MMC5 */ uint8 * MMC5BGVRAMADR(uint32 V) { if (!Sprite16) { extern uint8 mmc5ABMode; /* A=0, B=1 */ @@ -150,7 +144,6 @@ uint8 * MMC5BGVRAMADR(uint32 V) { return &MMC5BGVPage[(V) >> 10][(V)]; } else return &MMC5BGVPage[(V) >> 10][(V)]; } -#endif static DECLFR(A2002) { uint8 ret; @@ -330,12 +323,8 @@ static DECLFW(B2007) { if (PPUCHRRAM & (1 << (tmp >> 10))) VPage[tmp >> 10][tmp] = V; } else if (tmp < 0x3F00) { - if (QTAIHack && (qtaintramreg & 1)) { - QTAINTRAM[((((tmp & 0xF00) >> 10) >> ((qtaintramreg >> 1)) & 1) << 10) | (tmp & 0x3FF)] = V; - } else { - if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) - vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; - } + if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) + vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; } else { if (!(tmp & 3)) { if (!(tmp & 0xC)) @@ -575,12 +564,6 @@ static void FASTAPASS(1) RefreshLine(int lastpixel) { #include "pputile.h" } #undef PPU_BGFETCH - } else if (QTAIHack) { - #define PPU_VRC5FETCH - for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.h" - } - #undef PPU_VRC5FETCH } else { for (X1 = firsttile; X1 < lasttile; X1++) { #include "pputile.h" diff --git a/src/ppu.h b/src/ppu.h index 6bc6e7caf..e3f6cfd78 100644 --- a/src/ppu.h +++ b/src/ppu.h @@ -23,19 +23,4 @@ void FCEUPPU_LoadState(int version); extern int scanline; extern uint8 PPU[4]; -/* MMC5 specifics */ -#define Sprite16 (PPU[0] & 0x20) /* Sprites 8x16/8x8 */ -#define PPUON (PPU[1] & 0x18) /* PPU should operate */ - -#define ABANKS MMC5SPRVPage -#define BBANKS MMC5BGVPage -#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] -#define VRAMADR(V) &VPage[(V) >> 10][(V)] -uint8 *MMC5BGVRAMADR(uint32 A); - -/* m547 */ -extern uint8 QTAIHack; -extern uint8 qtaintramreg; -extern uint8 QTAINTRAM[0x800]; - #endif diff --git a/src/pputile.h b/src/pputile.h index 0f47e65d7..aca6ae6d2 100644 --- a/src/pputile.h +++ b/src/pputile.h @@ -1,11 +1,6 @@ uint8 *C; uint8 cc; uint32 vadr; -#ifdef PPU_VRC5FETCH -uint8 tmpd; -extern uint8 *VROM; -extern uint32 VROM_size; -#endif #ifndef PPUT_MMC5SP uint8 zz; @@ -47,10 +42,6 @@ if (X1 >= 2) { #else zz = RefreshAddr & 0x1F; C = vnapage[(RefreshAddr >> 10) & 3]; -#ifdef PPU_VRC5FETCH - tmpd = QTAINTRAM[((((RefreshAddr >> 10) & 3) >> ((qtaintramreg >> 1)) & 1) << 10) | (RefreshAddr & 0x3FF)]; - vofs = ((tmpd & 0x3F) << 12) | ((RefreshAddr >> 12) & 7); /* recalculate VROM offset */ -#endif vadr = (C[RefreshAddr & 0x3ff] << 4) + vofs; /* Fetch name table byte. */ #endif @@ -86,19 +77,9 @@ pshift[1] <<= 8; C += (MMC50x5130 & 0x3) << 18; #elif defined(PPUT_MMC5) C = MMC5BGVRAMADR(vadr); - #else - #ifdef PPU_VRC5FETCH - if (tmpd & 0x40) { - if ((VROM_size * 8) == 128) - vadr = ((vadr & 0x07) << 1) | ((vadr & 0x10) >> 4) | ((vadr & 0x3FFE0) >> 1); - C = VROM + vadr; - } else { - C = VRAMADR(vadr); - } #else C = VRAMADR(vadr); #endif - #endif #endif #ifdef PPUT_HOOK @@ -114,16 +95,8 @@ pshift[1] <<= 8; pshift[1] |= C[0]; } #else - #ifdef PPU_VRC5FETCH - pshift[0] |= C[0]; - if (tmpd & 0x40) - pshift[1] |= (tmpd & 0x80) ? 0xFF : 0x00; - else - pshift[1] |= C[8]; - #else pshift[0] |= C[0]; pshift[1] |= C[8]; - #endif #endif if ((RefreshAddr & 0x1f) == 0x1f) diff --git a/src/sound.c b/src/sound.c index 184ba0371..dbf1c8a44 100644 --- a/src/sound.c +++ b/src/sound.c @@ -37,16 +37,7 @@ int32 Wave[2048 + 512]; int32 WaveHi[40000]; int32 WaveFinal[2048 + 512]; -/* FIXME: Very ugly hack and only relevant in multichip NSF playback */ -/* Indexing is based on sound channel enum */ -EXPSOUND GameExpSound[GAMEEXPSOUND_COUNT] = { - { 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0 }, -}; +EXPSOUND GameExpSound = { 0, 0, 0, 0, 0, 0 }; static uint8 TriCount = 0; static uint8 TriMode = 0; @@ -952,7 +943,7 @@ void SetNESSoundMap(void) { static int32 inbuf = 0; int FlushEmulateSound(void) { - int i, x; + int x; int32 end, left; if (!sound_timestamp) return(0); @@ -972,11 +963,7 @@ int FlushEmulateSound(void) { if (FSettings.soundq >= 1) { int32 *tmpo = &WaveHi[soundtsoffs]; - for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { - if (GameExpSound[i].HiFill) { - GameExpSound[i].HiFill(); - } - } + if (GameExpSound.HiFill) GameExpSound.HiFill(); for (x = sound_timestamp; x; x--) { uint32 b = *tmpo; @@ -989,21 +976,13 @@ int FlushEmulateSound(void) { memmove(WaveHi, WaveHi + SOUNDTS - left, left * sizeof(uint32)); memset(WaveHi + left, 0, sizeof(WaveHi) - left * sizeof(uint32)); - for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { - if (GameExpSound[i].HiSync) { - GameExpSound[i].HiSync(left); - } - } - + if (GameExpSound.HiSync) GameExpSound.HiSync(left); for (x = 0; x < 5; x++) ChannelBC[x] = left; } else { end = (SOUNDTS << 16) / soundtsinc; - for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { - if (GameExpSound[i].Fill) { - GameExpSound[i].Fill(end & 0xF); - } - } + if (GameExpSound.Fill) + GameExpSound.Fill(end & 0xF); SexyFilter(Wave, WaveFinal, end >> 4); @@ -1097,7 +1076,7 @@ void FCEUSND_Power(void) { void SetSoundVariables(void) { - int i, x; + int x; fhinc = PAL ? 16626 : 14915; /* *2 CPU clock rate */ fhinc *= 24; @@ -1134,11 +1113,8 @@ void SetSoundVariables(void) { MakeFilters(FSettings.SndRate); - for (i = 0; i < GAMEEXPSOUND_COUNT; i++) { - if (GameExpSound[i].RChange) { - GameExpSound[i].RChange(); - } - } + if (GameExpSound.RChange) + GameExpSound.RChange(); nesincsize = (int64)(((int64)1 << 17) * (double)(PAL ? PAL_CPU : NTSC_CPU) / (FSettings.SndRate * 16)); memset(sqacc, 0, sizeof(sqacc)); @@ -1167,33 +1143,6 @@ void FCEUI_SetSoundVolume(uint32 volume) { FSettings.SoundVolume = volume; } -void FCEUI_SetExpSoundVolume(int ch, uint32 volume) { - if ((ch >= SND_VRC6) && (ch < SND_LAST)) - FSettings.ExpSoundVolume[ch] = volume; -} - -int FCEUI_GetExpSoundVolume(int ch) { - if ((ch >= SND_VRC6) && (ch < SND_LAST)) - return FSettings.ExpSoundVolume[ch]; - return 0; -} - -int32 GetOutput(int ch, int32 in) { - if ((ch >= SND_VRC6) && (ch < SND_LAST)) - { - int mod = FCEUI_GetExpSoundVolume(ch); - - if (in == 0 || mod == 0) - { - return 0; /* silence */ - } - if (mod != 256) - { - return (int32)((in * mod) / 256); - } - } - return in; -} SFORMAT FCEUSND_STATEINFO[] = { { &fhcnt, 4 | FCEUSTATE_RLSB, "FHCN" }, diff --git a/src/sound.h b/src/sound.h index 8af238ced..c4413ccc6 100644 --- a/src/sound.h +++ b/src/sound.h @@ -38,18 +38,7 @@ typedef struct { void (*Kill)(void); } EXPSOUND; -enum EXPSOUNDTYPE { - SND_VRC6 = 0, - SND_VRC7, - SND_FDS, - SND_N163, - SND_S5B, - SND_MMC5, - SND_LAST, -}; - -#define GAMEEXPSOUND_COUNT SND_LAST -extern EXPSOUND GameExpSound[GAMEEXPSOUND_COUNT]; +extern EXPSOUND GameExpSound; extern int32 nesincsize; @@ -75,15 +64,4 @@ void FCEUSND_LoadState(int version); void FASTAPASS(1) FCEU_SoundCPUHook(int); -/* volume levels for mapper-based expansion audio */ -void FCEUI_SetExpSoundVolume(int ch, uint32 volume); -int FCEUI_GetExpSoundVolume(int ch); - -/* Modify channel wave volume based on volume modifiers - * Note: the formulat x = x * y /256 does not yield exact results, - * but is "close enough" and avoids the need for using double values - * or implicit cohersion which are slower (we need speed here) */ -/* TODO: Optimize this. */ -int32 GetOutput(int ch, int32 in); - #endif diff --git a/src/unif.c b/src/unif.c index e28b0692b..a022ec82f 100644 --- a/src/unif.c +++ b/src/unif.c @@ -48,21 +48,12 @@ typedef struct { uint32 info; } UNIF_HEADER; -#if 0 typedef struct { char *name; int ines_mapper; void (*init)(CartInfo *); int flags; } BMAPPING; -#endif -typedef struct { - char *name; - int mapper; - int submapper; - void (*init)(CartInfo *); - int flags; -} BMAPPING; typedef struct { char *name; @@ -420,7 +411,6 @@ static void CheckHashInfo(void) { } -#if 0 #define NO_INES -1 #define BMCFLAG_FORCE4 0x01 #define BMCFLAG_16KCHRR 0x02 @@ -639,237 +629,6 @@ static BMAPPING bmap[] = { { NULL, NO_INES, NULL, 0 } }; -#endif - -#define NO_INES (-1) - -#define BMCFLAG_FORCE4 0x0001 -#define BMCFLAG_16KCHRR 0x0002 -#define BMCFLAG_32KCHRR 0x0004 -#define BMCFLAG_128KCHRR 0x0008 -#define BMCFLAG_256KCHRR 0x0010 -#define BMCFLAG_512KCHRR 0x0020 - -#define BMCFLAG_8KWRAM 0x0020 -#define BMCFLAG_16KWRAM 0x0040 -#define BMCFLAG_32KWRAM 0x0080 - -static BMAPPING bmap[] = { - { "NROM", 0, 0, Mapper000_Init, 0 }, - { "NROM-128", 0, 0, Mapper000_Init, 0 }, - { "NROM-256", 0, 0, Mapper000_Init, 0 }, - { "RROM", 0, 0, Mapper000_Init, 0 }, - { "RROM-128", 0, 0, Mapper000_Init, 0 }, - { "SBROM", 1, 0, Mapper001_Init, 0 }, - { "SCROM", 1, 0, Mapper001_Init, 0 }, - { "SEROM", 1, 0, Mapper001_Init, 0 }, - { "SGROM", 1, 0, Mapper001_Init, 0 }, - { "SL1ROM", 1, 0, Mapper001_Init, 0 }, - { "SLROM", 1, 0, Mapper001_Init, 0 }, - { "SAROM", 1, 0, SAROM_Init, 0 }, - { "SKROM", 1, 0, SKROM_Init, 0 }, - { "SNROM", 1, 0, SNROM_Init, 0 }, - { "SOROM", 1, 0, SOROM_Init, 0 }, - { "UNROM", 2, 0, Mapper002_Init, 0 }, - { "UOROM", 2, 0, Mapper002_Init, 0 }, - { "CNROM", 3, 0, Mapper003_Init, 0 }, - { "HKROM", 4, 0, Mapper004_Init, 0 }, /* 1K WRAM, mapper 004.1 */ - { "TBROM", 4, 0, Mapper004_Init, 0 }, - { "TEROM", 4, 0, Mapper004_Init, 0 }, - { "TFROM", 4, 0, Mapper004_Init, 0 }, - { "TGROM", 4, 0, Mapper004_Init, 0 }, - { "TKROM", 4, 0, Mapper004_Init, 0 }, - { "TLROM", 4, 0, Mapper004_Init, 0 }, - { "TSROM", 4, 0, Mapper004_Init, 0 }, - { "TVROM", 4, 0, Mapper004_Init, BMCFLAG_FORCE4 }, - { "TR1ROM", 4, 0, Mapper004_Init, BMCFLAG_FORCE4 }, - { "EKROM", 5, 0, EKROM_Init, 0 }, - { "ELROM", 5, 0, ELROM_Init, 0 }, - { "ETROM", 5, 0, ETROM_Init, 0 }, - { "EWROM", 5, 0, EWROM_Init, 0 }, - { "ANROM", 7, 0, Mapper007_Init, 0 }, - { "CPROM", 13, 0, Mapper013_Init, BMCFLAG_16KCHRR }, - { "SL1632", 14, 0, Mapper014_Init, 0 }, - { "CC-21", 27, 0, Mapper027_Init, 0 }, - { "RET-CUFROM", 29, 0, Mapper029_Init, BMCFLAG_32KCHRR }, - { "UNROM-512-8", 30, 0, Mapper030_Init, 0 }, - { "UNROM-512-16", 30, 0, Mapper030_Init, BMCFLAG_16KCHRR }, - { "UNROM-512-32", 30, 0, Mapper030_Init, BMCFLAG_32KCHRR }, - { "SC-127", 35, 0, Mapper035_Init, 0 }, - { "AC08", 42, 0, Mapper042_Init, 0 }, - { "SuperHIK8in1", 45, 0, Mapper045_Init, 0 }, - { "STREETFIGTER-GAME4IN1", 49, 0, Mapper049_Init, 0 }, /* mapper 49? submapper 1*/ - { "Supervision16in1", 53, 0, Mapper053_Init, 0 }, - { "MARIO1-MALEE2", 55, 0, Mapper055_Init, 0 }, - { "GK-192", 58, 0, Mapper058_Init, 0 }, - { "D1038", 59, 0, Mapper059_Init, 0 }, - { "T3H53", 59, 0, Mapper059_Init, 0 }, - { "MHROM", 66, 0, Mapper066_Init, 0 }, - { "NTBROM", 68, 0, Mapper068_Init, 0 }, - { "SA-016-1M", 79, 0, Mapper079_Init, 0 }, - { "VRC7", 85, 0, Mapper085_Init, 0 }, - { "TEK90", 90, 0, Mapper090_Init, 0 }, - { "SUNSOFT_UNROM", 93, 0, Mapper093_Init, 0 }, /* fix me, real pcb name, real pcb type */ - { "BB", 108, 0, Mapper108_Init, 0 }, - { "LE05", 108, 0, Mapper108_Init, 0 }, - { "SL12", 116, 0, Mapper116_Init, 0 }, - { "TKSROM", 118, 0, Mapper118_Init, 0 }, - { "TLSROM", 118, 0, Mapper118_Init, 0 }, - { "TQROM", 119, 0, Mapper119_Init, 0 }, - { "H2288", 123, 0, Mapper123_Init, 0 }, - { "LH32", 125, 0, Mapper125_Init, 0 }, - { "22211", 132, 0, Mapper132_Init, 0 }, - { "SA-72008", 133, 0, Mapper133_Init, 0 }, - { "T4A54A", 134, 0, Mapper134_Init, 0 }, - { "WX-KB4K", 134, 0, Mapper134_Init, 0 }, - { "SA-002", 136, 0, Mapper136_Init, 0 }, - { "Sachen-8259D", 137, 0, Mapper137_Init, 0 }, - { "Sachen-8259B", 138, 0, Mapper138_Init, 0 }, - { "Sachen-8259C", 139, 0, Mapper139_Init, 0 }, - { "Sachen-8259A", 141, 0, Mapper141_Init, 0 }, - { "KS7032", 142, 0, Mapper142_Init, 0 }, - { "SA-NROM", 143, 0, Mapper143_Init, 0 }, - { "SA-72007", 145, 0, Mapper145_Init, 0 }, - { "TC-U01-1.5M", 147, 0, Mapper147_Init, 0 }, - { "SA-0037", 148, 0, Mapper148_Init, 0 }, - { "SA-0036", 149, 0, Mapper149_Init, 0 }, - { "Sachen-74LS374N", 150, 0, Mapper150_Init, 0 }, - { "Sachen-74LS374NA", 150, 0, Mapper150_Init, 0 }, /* seems to be custom mapper */ - /* { "SA-009", 160, 0, Mapper160_Init, 0 }, */ - { "FS304", 162, 0, Mapper162_Init, 0 }, - { "FK23C", 176, 0, BMCFK23C_Init, BMCFLAG_256KCHRR }, - { "FK23CA", 176, 0, BMCFK23CA_Init, BMCFLAG_256KCHRR }, - { "Super24in1SC03", 176, 0, Super24_Init, 0 }, - { "WAIXING-FS005", 176, 0, WAIXINGFS005_Init, 0 }, - { "NovelDiamond9999999in1", 201, 0, Mapper201_Init, 0 }, - { "JC-016-2", 205, 0, Mapper205_Init, 0 }, - { "8237", 215, 0, Mapper215_Init, 0 }, - { "8237A", 215, 0, Mapper215_Init, 0 }, /* m215 sub 1*/ - { "N625092", 221, 0, Mapper221_Init, 0 }, - { "Ghostbusters63in1", 226, 0, Mapper226_Init, 0 }, - { "G631", 226, 0, Mapper226_Init, 0 }, /* duplicate, probably wrong name */ - { "WAIXING-FW01", 227, 0, Mapper227_Init, 0 }, - { "42in1ResetSwitch", 233, 0, Mapper233_Init, 0 }, - { "70in1", 236, 0, Mapper236_Init, 0 }, - { "70in1B", 236, 0, Mapper236_Init, 0 }, - { "603-5052", 238, 0, Mapper238_Init, 0 }, - { "43272", 242, 0, Mapper242_Init, 0 }, - { "DANCE", 256, 0, Mapper256_Init, 0 }, - { "OneBus", 256, 0, Mapper256_Init, 0 }, - { "PEC-586", 257, 0, Mapper257_Init, 0 }, - { "158B", 258, 0, Mapper215_Init, 0 }, - { "F-15", 259, 0, Mapper259_Init, 0 }, - { "HPxx", 260, 0, Mapper260_Init, 0 }, - { "HP2018-A", 260, 0, Mapper260_Init, 0 }, - { "810544-C-A1", 261, 0, Mapper261_Init, 0 }, - { "SHERO", 262, 0, Mapper262_Init, BMCFLAG_FORCE4 }, - { "KOF97", 263, 0, Mapper263_Init, 0 }, - { "YOKO", 264, 0, Mapper264_Init, 0 }, - { "T-262", 265, 0, Mapper265_Init, 0 }, - { "CITYFIGHT", 266, 0, Mapper266_Init, 0 }, - { "COOLBOY", 268, 0, COOLBOY_Init, BMCFLAG_256KCHRR }, - { "MINDKIDS", 224, 0, MINDKIDS_Init, BMCFLAG_256KCHRR }, - { "22026", 271, 0, Mapper271_Init, 0 }, - { "80013-B", 274, 0, Mapper274_Init, 0 }, - { "GS-2004", 283, 0, Mapper283_Init, 0 }, - { "DRIPGAME", 284, 0, Mapper284_Init, 0 }, - { "GS-2013", 283, 0, Mapper283_Init, 0 }, - { "A65AS", 285, 0, Mapper285_Init, 0 }, - { "BS-5", 286, 0, Mapper286_Init, 0 }, - { "411120-C", 287, 0, Mapper287_Init, 0 }, - { "K-3088", 287, 0, Mapper287_Init, 0 }, - { "60311C", 289, 0, Mapper289_Init, 0 }, - { "NTD-03", 290, 0, Mapper290_Init, 0 }, - { "DRAGONFIGHTER", 292, 0, Mapper292_Init, 0 }, - { "13in1JY110", 295, 0, Mapper295_Init, 0 }, - { "TF1201", 298, 0, Mapper298_Init, 0 }, - { "11160", 299, 0, Mapper299_Init, 0 }, - { "190in1", 300, 0, Mapper300_Init, 0 }, - { "8157", 301, 0, Mapper301_Init, 0 }, - { "KS7057", 302, 0, Mapper302_Init, 0 }, - { "KS7017", 303, 0, Mapper303_Init, 0 }, - { "SMB2J", 304, 0, Mapper304_Init, 0 }, - { "KS7031", 305, 0, Mapper305_Init, 0 }, - { "KS7016", 306, 0, Mapper306_Init, 0 }, - { "KS7037", 307, 0, Mapper307_Init, 0 }, - { "TH2131-1", 308, 0, Mapper308_Init, 0 }, - { "LH51", 309, 0, Mapper309_Init, 0 }, - { "KS7013B", 312, 0, Mapper312_Init, 0 }, - { "RESET-TXROM", 313, 0, Mapper313_Init, 0 }, - { "64in1NoRepeat", 314, 0, Mapper314_Init, 0 }, - { "830134C", 315, 0, Mapper315_Init, 0 }, - { "HP898F", 319, 0, Mapper319_Init, 0 }, /* UNIF implementation of mapper 319 */ - { "830425C-4391T", 320, 0, Mapper320_Init, 0 }, - { "K-3033", 322, 0, Mapper322_Init, 0 }, - { "FARID_SLROM_8-IN-1", 323, 0, Mapper323_Init, 0 }, - { "FARID_UNROM_8-IN-1", 324, 0, Mapper324_Init, 0 }, - { "MALISB", 325, 0, Mapper325_Init, 0 }, - { "10-24-C-A1", 327, 0, Mapper327_Init, 0 }, - { "RT-01", 328, 0, Mapper328_Init, 0 }, - { "EDU2000", 329, 0, Mapper329_Init, 0 }, - { "12-IN-1", 331, 0, Mapper331_Init, 0 }, - { "WS", 332, 0, Mapper332_Init, 0 }, - { "8-IN-1", 333, 0, Mapper333_Init, 0 }, - { "NEWSTAR-GRM070-8IN1", 333, 0, Mapper333_Init, 0 }, - { "CTC-09", 335, 0, Mapper335_Init, 0 }, - { "K-3046", 336, 0, Mapper336_Init, 0 }, - { "CTC-12IN1", 337, 0, Mapper337_Init, 0 }, - { "SA005-A", 338, 0, Mapper338_Init, 0 }, - { "K-3006", 339, 0, Mapper339_Init, 0 }, - { "K-3036", 340, 0, Mapper340_Init, 0 }, - { "TJ-03", 341, 0, Mapper341_Init, 0 }, - { "COOLGIRL", 342, 0, Mapper342_Init, BMCFLAG_512KCHRR }, - { "RESETNROM-XIN1", 343, 0, Mapper343_Init, 0 }, - { "GN-26", 344, 0, Mapper344_Init, 0 }, - { "L6IN1", 345, 0, Mapper345_Init, 0 }, - { "KS7012", 346, 0, Mapper346_Init, 0 }, - { "KS7030", 347, 0, Mapper347_Init, 0 }, - { "830118C", 348, 0, Mapper348_Init, 0 }, - { "G-146", 349, 0, Mapper349_Init, 0 }, - { "891227", 350, 0, Mapper350_Init, 0 }, - { "KS106C", 352, 0, Mapper352_Init, 0 }, - { "3D-BLOCK", 355, 0, UNL3DBlock_Init, 0 }, - { "SB-5013", 359, 0, Mapper359_Init, 0 }, - { "N49C-300", 369, 0, Mapper369_Init, 0 }, - { "830752C", 396, 0, Mapper396_Init, 0 }, - { "GOLDEN-16IN1-SPC001", 396, 0, Mapper396_Init, 0 }, - { "BS-400R", 422, 0, Mapper422_Init, 0 }, - { "BS-4040R", 422, 0, Mapper422_Init, 0 }, - { "AB-G1L", 428, 0, Mapper428_Init, 0 }, - { "WELL-NO-DG450", 428, 0, Mapper428_Init, 0 }, - { "TF2740", 428, 0, Mapper428_Init, 0 }, - { "S-2009", 434, 0, Mapper434_Init, 0 }, - { "K-3010", 438, 0, Mapper438_Init, 0 }, - { "K-3071", 438, 0, Mapper438_Init, 0 }, - { "DS-07", 439, 0, Mapper439_Init, 0 }, - { "K86B", 439, 0, Mapper439_Init, 0 }, - { "BS-110", 444, 0, Mapper444_Init, 0 }, /* Due to a mix-up, UNIF MAPR BMC-BS-110 is actually the NC7000M PCB and refers to NES 2.0 Mapper 444 instead. */ - { "DG574B", 445, 0, Mapper445_Init, 0 }, - { "SA-9602B", 513, 0, Mapper513_Init, BMCFLAG_32KCHRR }, - { "DANCE2000", 518, 0, Mapper518_Init, 0 }, - { "EH8813A", 519, 0, Mapper519_Init, 0 }, - { "DREAMTECH01", 521, 0, Mapper521_Init, 0 }, - { "LH10", 522, 0, Mapper522_Init, 0 }, - { "900218", 524, 0, Mapper524_Init, 0 }, - { "KS7021A", 525, 0, Mapper525_Init, 0 }, - { "BJ-56", 526, 0, Mapper526_Init, 0 }, - { "AX-40G", 527, 0, Mapper527_Init, 0 }, - { "831128C", 528, 0, Mapper528_Init, 0 }, - { "T-230", 529, 0, Mapper529_Init, 0 }, - { "AX5705", 530, 0, Mapper530_Init, 0 }, - { "LH53", 535, 0, Mapper535_Init, 0 }, - { "82112C", 540, 0, Mapper540_Init, 0 }, - { "KONAMI-QTAI", 547, 0, Mapper547_Init, 0 }, - - { "SSS-NROM-256", NO_INES, 0, SSSNROM_Init, 0 }, /* famicombox - cant find similar cart */ - { "T-227-1", NO_INES, 0, BMCT2271_Init, 0 }, /* cant find similar cart */ - { "Transformer", NO_INES, 0, Transformer_Init, 0 }, - { "81-01-31-C", NO_INES, 0, BMC810131C_Init, 0 }, /* might be mapper 327 with m118-like mirroring */ - { "KG256", NO_INES, 0, KG256_Init, 0 }, /* cant find similar cart */ - { "CHINA_ER_SAN2", NO_INES, 0, Mapper019_Init, 0 }, /* Needs more than just what mapper 19 can handle */ - - { NULL, NO_INES, 0, NULL, 0 } -}; static BFMAPPING bfunc[] = { { "CTRL", CTRL }, @@ -944,7 +703,7 @@ static int InitializeBoard(void) { mirrortodo = 4; MooMirroring(); - UNIFCart.mapper = bmap[x].mapper; + UNIFCart.mapper = bmap[x].ines_mapper; UNIFCart.submapper = submapper; GameInfo->cspecial = cspecial; diff --git a/src/unif.h b/src/unif.h index 927a647d8..353235aa6 100644 --- a/src/unif.h +++ b/src/unif.h @@ -99,7 +99,7 @@ void TQROM_Init(CartInfo *info); void TQROM_Init(CartInfo *info); void TSROM_Init(CartInfo *info); void Transformer_Init(CartInfo *info); -/* void UNL22211_Init(CartInfo *info); m132 */ +void UNL22211_Init(CartInfo *info); void UNL3DBlock_Init(CartInfo *info); void UNL43272_Init(CartInfo *info); void UNL6035052_Init(CartInfo *info); diff --git a/src/x6502.c b/src/x6502.c index 8d21d8659..b8bf2d95d 100644 --- a/src/x6502.c +++ b/src/x6502.c @@ -393,25 +393,8 @@ void FCEUI_GetIVectors(uint16 *reset, uint16 *irq, uint16 *nmi) { static int debugmode; #endif -void X6502_SetNewPC(uint16 newPC) { - X.newPC = newPC; -} - void X6502_Reset(void) { -#ifdef FCEUDEF_DEBUGGER -#define RdMem RdMemHook -#else -#define RdMem RdMemNorm -#endif - _S--; - _S--; - _S--; - _jammed = 0; - _P |= I_FLAG; - _PI = X.P; - _PC = RdMem(0xFFFC); - _PC |= RdMem(0xFFFD) << 8; -#undef RdMem + _IRQlow = FCEU_IQRESET; } void X6502_Init(void) { @@ -432,13 +415,9 @@ void X6502_Init(void) { void X6502_Power(void) { _count = _tcount = _IRQlow = _PC = _A = _X = _Y = _P = _PI = _DB = _jammed = 0; - /*_S = 0xFD;*/ - _P = 0x34; + _S = 0xFD; timestamp = sound_timestamp = 0; X6502_Reset(); - if (X.newPC) { - _PC = X.newPC; - } } #ifdef FCEUDEF_DEBUGGER diff --git a/src/x6502.h b/src/x6502.h index 703b5006c..f4805440f 100644 --- a/src/x6502.h +++ b/src/x6502.h @@ -48,24 +48,15 @@ extern X6502 X; extern void FP_FASTAPASS(1) (*MapIRQHook)(int a); -/* 21.47~ MHz ÷ 12 = 1.789773 MHz */ -#define NTSC_CLOCK_SPEED 1789772.7272727272727272 - -/* 26.60~ MHz ÷ 16 = 1.662607 MHz */ -#define PAL_CLOCK_SPEED 1662607.125 - -/* 26.60~ MHz ÷ 15 = 1.773448 MHz */ -#define DENDY_CLOCK_SPEED 1773447.467 - -#define NTSC_CPU (dendy ? DENDY_CLOCK_SPEED : NTSC_CLOCK_SPEED) -#define PAL_CPU PAL_CLOCK_SPEED +#define NTSC_CPU (dendy ? 1773447.467 : 1789772.7272727272727272) +#define PAL_CPU 1662607.125 #define FCEU_IQEXT 0x001 #define FCEU_IQEXT2 0x002 /* ... */ #define FCEU_IQRESET 0x020 -#define FCEU_IQNMI2 0x040 /* Delayed NMI, gets converted to *_IQNMI */ -#define FCEU_IQNMI 0x080 +#define FCEU_IQNMI2 0x040 /* Delayed NMI, gets converted to *_IQNMI */ +#define FCEU_IQNMI 0x080 #define FCEU_IQDPCM 0x100 #define FCEU_IQFCOUNT 0x200 #define FCEU_IQTEMP 0x800 @@ -83,6 +74,4 @@ void FASTAPASS(2) X6502_DMW(uint32 A, uint8 V); void FASTAPASS(1) X6502_IRQBegin(int w); void FASTAPASS(1) X6502_IRQEnd(int w); -void X6502_SetNewPC(uint16 newPC); - #endif diff --git a/src/x6502struct.h b/src/x6502struct.h index cacb899ee..fec30032f 100644 --- a/src/x6502struct.h +++ b/src/x6502struct.h @@ -6,7 +6,6 @@ typedef struct __X6502 { uint16 PC; /* I'll change this to uint32 later... */ /* I'll need to AND PC after increments to 0xFFFF */ /* when I do, though. Perhaps an IPC() macro? */ - uint16 newPC; /* used to override PC after at power on */ uint8 A, X, Y, S, P, mooPI; uint8 jammed;