map009.c
1 /* 2 ** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com) 3 ** 4 ** 5 ** This program is free software; you can redistribute it and/or 6 ** modify it under the terms of version 2 of the GNU Library General 7 ** Public License as published by the Free Software Foundation. 8 ** 9 ** This program is distributed in the hope that it will be useful, 10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 ** Library General Public License for more details. To obtain a 13 ** copy of the GNU Library General Public License, write to the Free 14 ** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 15 ** 16 ** Any permitted reproduction of these routines, in whole or in part, 17 ** must bear this legend. 18 ** 19 ** 20 ** map9.c 21 ** 22 ** mapper 9 interface 23 ** $Id: map009.c,v 1.2 2001/04/27 14:37:11 neil Exp $ 24 */ 25 26 #include <string.h> 27 #include "noftypes.h" 28 #include "nes_mmc.h" 29 #include "nes_ppu.h" 30 #include "libsnss.h" 31 32 static uint8 latch[2]; 33 static uint8 regs[4]; 34 35 /* Used when tile $FD/$FE is accessed */ 36 static void mmc9_latchfunc(uint32 address, uint8 value) 37 { 38 if (0xFD == value || 0xFE == value) 39 { 40 int reg; 41 42 if (address) 43 { 44 latch[1] = value; 45 reg = 2 + (value - 0xFD); 46 } 47 else 48 { 49 latch[0] = value; 50 reg = value - 0xFD; 51 } 52 53 mmc_bankvrom(4, address, regs[reg]); 54 } 55 } 56 57 /* mapper 9: MMC2 */ 58 /* MMC2: Punch-Out! */ 59 static void map9_write(uint32 address, uint8 value) 60 { 61 switch ((address & 0xF000) >> 12) 62 { 63 case 0xA: 64 mmc_bankrom(8, 0x8000, value); 65 break; 66 67 case 0xB: 68 regs[0] = value; 69 if (0xFD == latch[0]) 70 mmc_bankvrom(4, 0x0000, value); 71 break; 72 73 case 0xC: 74 regs[1] = value; 75 if (0xFE == latch[0]) 76 mmc_bankvrom(4, 0x0000, value); 77 break; 78 79 case 0xD: 80 regs[2] = value; 81 if (0xFD == latch[1]) 82 mmc_bankvrom(4, 0x1000, value); 83 break; 84 85 case 0xE: 86 regs[3] = value; 87 if (0xFE == latch[1]) 88 mmc_bankvrom(4, 0x1000, value); 89 break; 90 91 case 0xF: 92 if (value & 1) 93 ppu_mirror(0, 0, 1, 1); /* horizontal */ 94 else 95 ppu_mirror(0, 1, 0, 1); /* vertical */ 96 break; 97 98 default: 99 break; 100 } 101 } 102 103 static void map9_init(void) 104 { 105 memset(regs, 0, sizeof(regs)); 106 107 mmc_bankrom(8, 0x8000, 0); 108 mmc_bankrom(8, 0xA000, (mmc_getinfo()->rom_banks * 2) - 3); 109 mmc_bankrom(8, 0xC000, (mmc_getinfo()->rom_banks * 2) - 2); 110 mmc_bankrom(8, 0xE000, (mmc_getinfo()->rom_banks * 2) - 1); 111 112 latch[0] = 0xFE; 113 latch[1] = 0xFE; 114 115 ppu_setlatchfunc(mmc9_latchfunc); 116 } 117 118 static void map9_getstate(SnssMapperBlock *state) 119 { 120 state->extraData.mapper9.latch[0] = latch[0]; 121 state->extraData.mapper9.latch[1] = latch[1]; 122 state->extraData.mapper9.lastB000Write = regs[0]; 123 state->extraData.mapper9.lastC000Write = regs[1]; 124 state->extraData.mapper9.lastD000Write = regs[2]; 125 state->extraData.mapper9.lastE000Write = regs[3]; 126 } 127 128 static void map9_setstate(SnssMapperBlock *state) 129 { 130 latch[0] = state->extraData.mapper9.latch[0]; 131 latch[1] = state->extraData.mapper9.latch[1]; 132 regs[0] = state->extraData.mapper9.lastB000Write; 133 regs[1] = state->extraData.mapper9.lastC000Write; 134 regs[2] = state->extraData.mapper9.lastD000Write; 135 regs[3] = state->extraData.mapper9.lastE000Write; 136 } 137 138 static map_memwrite map9_memwrite[] = 139 { 140 { 0x8000, 0xFFFF, map9_write }, 141 { -1, -1, NULL } 142 }; 143 144 const mapintf_t map9_intf = 145 { 146 9, /* mapper number */ 147 "MMC2", /* mapper name */ 148 map9_init, /* init routine */ 149 NULL, /* vblank callback */ 150 NULL, /* hblank callback */ 151 map9_getstate, /* get state (snss) */ 152 map9_setstate, /* set state (snss) */ 153 NULL, /* memory read structure */ 154 map9_memwrite, /* memory write structure */ 155 NULL /* external sound device */ 156 }; 157 158 /* 159 ** $Log: map009.c,v $ 160 ** Revision 1.2 2001/04/27 14:37:11 neil 161 ** wheeee 162 ** 163 ** Revision 1.1 2001/04/27 12:54:40 neil 164 ** blah 165 ** 166 ** Revision 1.1.1.1 2001/04/27 07:03:54 neil 167 ** initial 168 ** 169 ** Revision 1.1 2000/10/24 12:19:33 matt 170 ** changed directory structure 171 ** 172 ** Revision 1.9 2000/10/22 19:17:46 matt 173 ** mapper cleanups galore 174 ** 175 ** Revision 1.8 2000/10/22 15:03:14 matt 176 ** simplified mirroring 177 ** 178 ** Revision 1.7 2000/10/21 19:33:38 matt 179 ** many more cleanups 180 ** 181 ** Revision 1.6 2000/07/17 05:11:35 matt 182 ** minor update from making PPU code less filthy 183 ** 184 ** Revision 1.5 2000/07/15 23:52:19 matt 185 ** rounded out a bunch more mapper interfaces 186 ** 187 ** Revision 1.4 2000/07/10 05:29:03 matt 188 ** cleaned up some mirroring issues 189 ** 190 ** Revision 1.3 2000/07/06 02:48:43 matt 191 ** clearly labelled structure members 192 ** 193 ** Revision 1.2 2000/07/05 22:50:33 matt 194 ** fixed punchout -- works 100% now 195 ** 196 ** Revision 1.1 2000/07/05 05:05:18 matt 197 ** initial revision 198 ** 199 */