map018.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 ** map18.c 21 ** 22 ** mapper 18 interface 23 ** $Id: map018.c,v 1.2 2001/04/27 14:37:11 neil Exp $ 24 */ 25 26 #include "noftypes.h" 27 #include "nes_mmc.h" 28 #include "nes_ppu.h" 29 30 /* mapper 18: Jaleco SS8806 */ 31 #define VRC_PBANK(bank, value, high) \ 32 do { \ 33 if ((high)) \ 34 highprgnybbles[(bank)] = (value) & 0x0F; \ 35 else \ 36 lowprgnybbles[(bank)] = (value) & 0x0F; \ 37 mmc_bankrom(8, 0x8000 + ((bank) << 13), (highprgnybbles[(bank)] << 4)+lowprgnybbles[(bank)]); \ 38 } while (0) 39 40 #define VRC_VBANK(bank, value, high) \ 41 { \ 42 if ((high)) \ 43 highnybbles[(bank)] = (value) & 0x0F; \ 44 else \ 45 lownybbles[(bank)] = (value) & 0x0F; \ 46 mmc_bankvrom(1, (bank) << 10, (highnybbles[(bank)] << 4)+lownybbles[(bank)]); \ 47 } 48 49 static struct 50 { 51 int counter, enabled; 52 uint8 nybbles[4]; 53 int clockticks; 54 } irq; 55 56 static void map18_init(void) 57 { 58 irq.counter = irq.enabled = 0; 59 } 60 61 static uint8 lownybbles[8]; 62 static uint8 highnybbles[8]; 63 static uint8 lowprgnybbles[3]; 64 static uint8 highprgnybbles[3]; 65 66 67 static void map18_write(uint32 address, uint8 value) 68 { 69 switch (address) 70 { 71 case 0x8000: VRC_PBANK(0, value, 0); break; 72 case 0x8001: VRC_PBANK(0, value, 1); break; 73 case 0x8002: VRC_PBANK(1, value, 0); break; 74 case 0x8003: VRC_PBANK(1, value, 1); break; 75 case 0x9000: VRC_PBANK(2, value, 0); break; 76 case 0x9001: VRC_PBANK(2, value, 1); break; 77 case 0xA000: VRC_VBANK(0, value, 0); break; 78 case 0xA001: VRC_VBANK(0, value, 1); break; 79 case 0xA002: VRC_VBANK(1, value, 0); break; 80 case 0xA003: VRC_VBANK(1, value, 1); break; 81 case 0xB000: VRC_VBANK(2, value, 0); break; 82 case 0xB001: VRC_VBANK(2, value, 1); break; 83 case 0xB002: VRC_VBANK(3, value, 0); break; 84 case 0xB003: VRC_VBANK(3, value, 1); break; 85 case 0xC000: VRC_VBANK(4, value, 0); break; 86 case 0xC001: VRC_VBANK(4, value, 1); break; 87 case 0xC002: VRC_VBANK(5, value, 0); break; 88 case 0xC003: VRC_VBANK(5, value, 1); break; 89 case 0xD000: VRC_VBANK(6, value, 0); break; 90 case 0xD001: VRC_VBANK(6, value, 1); break; 91 case 0xD002: VRC_VBANK(7, value, 0); break; 92 case 0xD003: VRC_VBANK(7, value, 1); break; 93 case 0xE000: 94 irq.nybbles[0]=value&0x0F; 95 irq.clockticks= (irq.nybbles[0]) | (irq.nybbles[1]<<4) | 96 (irq.nybbles[2]<<8) | (irq.nybbles[3]<<12); 97 irq.counter=(uint8)(irq.clockticks/114); 98 if(irq.counter>15) irq.counter-=16; 99 break; 100 case 0xE001: 101 irq.nybbles[1]=value&0x0F; 102 irq.clockticks= (irq.nybbles[0]) | (irq.nybbles[1]<<4) | 103 (irq.nybbles[2]<<8) | (irq.nybbles[3]<<12); 104 irq.counter=(uint8)(irq.clockticks/114); 105 if(irq.counter>15) irq.counter-=16; 106 break; 107 case 0xE002: 108 irq.nybbles[2]=value&0x0F; 109 irq.clockticks= (irq.nybbles[0]) | (irq.nybbles[1]<<4) | 110 (irq.nybbles[2]<<8) | (irq.nybbles[3]<<12); 111 irq.counter=(uint8)(irq.clockticks/114); 112 if(irq.counter>15) irq.counter-=16; 113 break; 114 case 0xE003: 115 irq.nybbles[3]=value&0x0F; 116 irq.clockticks= (irq.nybbles[0]) | (irq.nybbles[1]<<4) | 117 (irq.nybbles[2]<<8) | (irq.nybbles[3]<<12); 118 irq.counter=(uint8)(irq.clockticks/114); 119 if(irq.counter>15) irq.counter-=16; 120 break; 121 case 0xF000: 122 if(value&0x01) irq.enabled=true; 123 break; 124 case 0xF001: 125 irq.enabled=value&0x01; 126 break; 127 case 0xF002: 128 switch(value&0x03) 129 { 130 case 0: ppu_mirror(0, 0, 1, 1); break; 131 case 1: ppu_mirror(0, 1, 0, 1); break; 132 case 2: ppu_mirror(1,1,1,1);break; 133 case 3: ppu_mirror(1,1,1,1);break; // should this be zero? 134 default: break; 135 } 136 break; 137 default: 138 break; 139 } 140 } 141 142 143 static const map_memwrite map18_memwrite[] = 144 { 145 { 0x8000, 0xFFFF, map18_write }, 146 { -1, -1, NULL } 147 }; 148 149 static void map18_getstate(SnssMapperBlock *state) 150 { 151 state->extraData.mapper18.irqCounterLowByte = irq.counter & 0xFF; 152 state->extraData.mapper18.irqCounterHighByte = irq.counter >> 8; 153 state->extraData.mapper18.irqCounterEnabled = irq.enabled; 154 } 155 156 static void map18_setstate(SnssMapperBlock *state) 157 { 158 irq.counter = (state->extraData.mapper18.irqCounterHighByte << 8) 159 | state->extraData.mapper18.irqCounterLowByte; 160 irq.enabled = state->extraData.mapper18.irqCounterEnabled; 161 } 162 163 const mapintf_t map18_intf = 164 { 165 18, /* mapper number */ 166 "Jaleco SS8806", /* mapper name */ 167 map18_init, /* init routine */ 168 NULL, /* vblank callback */ 169 NULL, /* hblank callback */ 170 map18_getstate, /* get state (snss) */ 171 map18_setstate, /* set state (snss) */ 172 NULL, /* memory read structure */ 173 map18_memwrite, /* memory write structure */ 174 NULL /* external sound device */ 175 }; 176 177 /* 178 ** $Log: map018.c,v $ 179 ** Revision 1.2 2001/04/27 14:37:11 neil 180 ** wheeee 181 ** 182 ** Revision 1.1 2001/04/27 12:54:40 neil 183 ** blah 184 ** 185 ** Revision 1.1.1.1 2001/04/27 07:03:54 neil 186 ** initial 187 ** 188 ** Revision 1.1 2000/10/24 12:19:33 matt 189 ** changed directory structure 190 ** 191 ** Revision 1.8 2000/10/22 19:17:46 matt 192 ** mapper cleanups galore 193 ** 194 ** Revision 1.7 2000/10/22 15:03:13 matt 195 ** simplified mirroring 196 ** 197 ** Revision 1.6 2000/10/21 19:33:38 matt 198 ** many more cleanups 199 ** 200 ** Revision 1.5 2000/10/10 13:58:17 matt 201 ** stroustrup squeezing his way in the door 202 ** 203 ** Revision 1.4 2000/07/15 23:52:19 matt 204 ** rounded out a bunch more mapper interfaces 205 ** 206 ** Revision 1.3 2000/07/10 05:29:03 matt 207 ** cleaned up some mirroring issues 208 ** 209 ** Revision 1.2 2000/07/06 02:48:42 matt 210 ** clearly labelled structure members 211 ** 212 ** Revision 1.1 2000/07/06 01:01:56 matt 213 ** initial revision 214 ** 215 */