1 //////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // Nestopia - NES/Famicom emulator written in C++ 4 // 5 // Copyright (C) 2003-2008 Martin Freij 6 // 7 // This file is part of Nestopia. 8 // 9 // Nestopia is free software; you can redistribute it and/or modify 10 // it under the terms of the GNU General Public License as published by 11 // the Free Software Foundation; either version 2 of the License, or 12 // (at your option) any later version. 13 // 14 // Nestopia is distributed in the hope that it will be useful, 15 // but WITHOUT ANY WARRANTY; without even the implied warranty of 16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 // GNU General Public License for more details. 18 // 19 // You should have received a copy of the GNU General Public License 20 // along with Nestopia; if not, write to the Free Software 21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 // 23 //////////////////////////////////////////////////////////////////////////////////////// 24 25 #include <cstring> 26 #include "NstBoard.hpp" 27 #include "NstBoardWaixing.hpp" 28 29 namespace Nes 30 { 31 namespace Core 32 { 33 namespace Boards 34 { 35 namespace Waixing 36 { 37 #ifdef NST_MSVC_OPTIMIZE 38 #pragma optimize("s", on) 39 #endif 40 SubReset(const bool hard)41 void TypeA::SubReset(const bool hard) 42 { 43 TypeI::SubReset( hard ); 44 45 for (uint i=0x0000; i < 0x2000; i += 0x2) 46 { 47 Map( 0xA000 + i, NMT_SWAP_VH01 ); 48 Map( 0xA001 + i, NOP_POKE ); 49 } 50 } 51 SubReset(const bool hard)52 void TypeF::SubReset(const bool hard) 53 { 54 exPrg[0] = 0x00; 55 exPrg[1] = 0x01; 56 exPrg[2] = 0x4E; 57 exPrg[3] = 0x4F; 58 59 TypeA::SubReset( hard ); 60 61 for (uint i=0x0000; i < 0x2000; i += 0x2) 62 Map( 0x8001 + i, &TypeF::Poke_8001 ); 63 } 64 SubReset(const bool hard)65 void TypeG::SubReset(const bool hard) 66 { 67 exPrg[0] = 0x00; 68 exPrg[1] = 0x01; 69 exPrg[2] = 0x3E; 70 exPrg[3] = 0x3F; 71 72 for (uint i=0; i < 8; ++i) 73 exChr[0] = i; 74 75 TypeA::SubReset( hard ); 76 77 for (uint i=0x0000; i < 0x2000; i += 0x2) 78 Map( 0x8001 + i, &TypeG::Poke_8001 ); 79 } 80 SubReset(const bool hard)81 void TypeH::SubReset(const bool hard) 82 { 83 exPrg = 0; 84 85 Mmc3::SubReset( hard ); 86 87 wrk.Source().SetSecurity( true, true ); 88 89 for (uint i=0x0000; i < 0x2000; i += 0x2) 90 { 91 Map( 0x8001 + i, &TypeH::Poke_8001 ); 92 Map( 0xA001 + i, NOP_POKE ); 93 } 94 } 95 SubReset(const bool hard)96 void TypeI::SubReset(const bool hard) 97 { 98 Mmc3::SubReset( hard ); 99 100 wrk.Source().SetSecurity( true, true ); 101 102 if (board.GetWram() >= SIZE_8K+SIZE_1K) 103 Map( 0x5000U, 0x5000U + NST_MIN(board.GetWram(),SIZE_4K) - 1, &TypeI::Peek_5000, &TypeI::Poke_5000 ); 104 } 105 SubReset(const bool hard)106 void TypeJ::SubReset(const bool hard) 107 { 108 if (hard) 109 { 110 exPrg[0] = 0x01; 111 exPrg[1] = 0x02; 112 exPrg[2] = 0x7E; 113 exPrg[3] = 0x7F; 114 } 115 116 TypeI::SubReset( hard ); 117 118 for (uint i=0x8001; i < 0xA000; i += 0x2) 119 Map( i, &TypeJ::Poke_8001 ); 120 } 121 SubLoad(State::Loader & state,const dword baseChunk)122 void TypeF::SubLoad(State::Loader& state,const dword baseChunk) 123 { 124 TypeA::SubLoad( state, baseChunk ); 125 126 for (uint i=0x0000; i < 0x8000; i += 0x2000) 127 exPrg[GetPrgIndex(i)] = prg.GetBank<SIZE_8K>(i); 128 } 129 SubLoad(State::Loader & state,const dword baseChunk)130 void TypeG::SubLoad(State::Loader& state,const dword baseChunk) 131 { 132 TypeA::SubLoad( state, baseChunk ); 133 134 for (uint i=0x0000; i < 0x8000; i += 0x2000) 135 exPrg[GetPrgIndex(i)] = prg.GetBank<SIZE_8K>(i); 136 137 for (uint i=0x0000; i < 0x2000; i += 0x0400) 138 exChr[GetChrIndex(i)] = chr.GetBank<SIZE_1K>(i); 139 } 140 SubLoad(State::Loader & state,const dword baseChunk)141 void TypeH::SubLoad(State::Loader& state,const dword baseChunk) 142 { 143 Mmc3::SubLoad( state, baseChunk ); 144 exPrg = prg.GetBank<SIZE_8K,0x0000>() | 0x40; 145 } 146 SubLoad(State::Loader & state,const dword baseChunk)147 void TypeJ::SubLoad(State::Loader& state,const dword baseChunk) 148 { 149 TypeI::SubLoad( state, baseChunk ); 150 151 for (uint i=0x0000; i < 0x8000; i += 0x2000) 152 exPrg[GetPrgIndex(i)] = prg.GetBank<SIZE_8K>(i); 153 } 154 155 #ifdef NST_MSVC_OPTIMIZE 156 #pragma optimize("", on) 157 #endif 158 159 NES_PEEK_A(TypeI,5000) 160 { 161 return wrk.Source()[address-(0x5000-0x2000)]; 162 } 163 164 NES_POKE_AD(TypeI,5000) 165 { 166 wrk.Source()[address-(0x5000-0x2000)] = data; 167 } 168 169 NES_POKE_AD(TypeF,8001) 170 { 171 if ((regs.ctrl0 & 7) >= 6) 172 exPrg[(regs.ctrl0 & 7) - 6] = data & (data >= 0x40 ? 0x4F : 0x3F); 173 174 Mmc3::NES_DO_POKE(8001,address,data); 175 } 176 177 NES_POKE_D(TypeG,8001) 178 { 179 switch (regs.ctrl0 & 0xF) 180 { 181 case 0x0: exChr[0] = data; Mmc3::UpdateChr(); break; 182 case 0x1: exChr[2] = data; Mmc3::UpdateChr(); break; 183 case 0x2: exChr[4] = data; Mmc3::UpdateChr(); break; 184 case 0x3: exChr[5] = data; Mmc3::UpdateChr(); break; 185 case 0x4: exChr[6] = data; Mmc3::UpdateChr(); break; 186 case 0x5: exChr[7] = data; Mmc3::UpdateChr(); break; 187 case 0x6: exPrg[0] = data; Mmc3::UpdatePrg(); break; 188 case 0x7: exPrg[1] = data; Mmc3::UpdatePrg(); break; 189 case 0x8: exPrg[2] = data; Mmc3::UpdatePrg(); break; 190 case 0x9: exPrg[3] = data; Mmc3::UpdatePrg(); break; 191 case 0xA: exChr[1] = data; Mmc3::UpdateChr(); break; 192 case 0xB: exChr[3] = data; Mmc3::UpdateChr(); break; 193 } 194 } 195 196 NES_POKE_AD(TypeH,8001) 197 { 198 if (!(regs.ctrl0 & 0x7)) 199 { 200 uint reg = data << 5 & 0x40; 201 202 if (exPrg != reg) 203 { 204 exPrg = reg; 205 Mmc3::UpdatePrg(); 206 } 207 } 208 209 Mmc3::NES_DO_POKE(8001,address,data); 210 } 211 212 NES_POKE_AD(TypeJ,8001) 213 { 214 const uint index = (regs.ctrl0 & 0x7); 215 216 if (index >= 6 && exPrg[index-6] != data) 217 { 218 exPrg[index-6] = data; 219 Mmc3::UpdatePrg(); 220 } 221 222 Mmc3::NES_DO_POKE(8001,address,data); 223 } 224 GetPrgIndex(uint address) const225 uint TypeI::GetPrgIndex(uint address) const 226 { 227 return address >> 13 ^ (regs.ctrl0 >> 5 & ~address >> 12 & 0x2); 228 } 229 GetChrIndex(uint address) const230 uint TypeI::GetChrIndex(uint address) const 231 { 232 return address >> 10 ^ (regs.ctrl0 >> 5 & 0x4); 233 } 234 UpdatePrg(uint address,uint)235 void NST_FASTCALL TypeF::UpdatePrg(uint address,uint) 236 { 237 prg.SwapBank<SIZE_8K>( address, exPrg[GetPrgIndex(address)] ); 238 } 239 UpdatePrg(uint address,uint)240 void NST_FASTCALL TypeG::UpdatePrg(uint address,uint) 241 { 242 prg.SwapBank<SIZE_8K>( address, exPrg[GetPrgIndex(address)] ); 243 } 244 UpdatePrg(uint address,uint bank)245 void NST_FASTCALL TypeH::UpdatePrg(uint address,uint bank) 246 { 247 prg.SwapBank<SIZE_8K>( address, exPrg | bank ); 248 } 249 UpdateChr(uint address,uint bank) const250 void NST_FASTCALL TypeA::UpdateChr(uint address,uint bank) const 251 { 252 chr.Source( GetChrSource(bank) ).SwapBank<SIZE_1K>( address, bank ); 253 } 254 UpdateChr(uint address,uint) const255 void NST_FASTCALL TypeG::UpdateChr(uint address,uint) const 256 { 257 uint bank = exChr[GetChrIndex(address)]; 258 chr.Source( bank <= 7 ).SwapBank<SIZE_1K>( address, bank ); 259 } 260 UpdateChr(uint address,uint bank) const261 void NST_FASTCALL TypeH::UpdateChr(uint address,uint bank) const 262 { 263 if (chr.Source().GetType() == Ram::ROM) 264 chr.SwapBank<SIZE_1K>( address, bank ); 265 } 266 UpdatePrg(uint address,uint bank)267 void NST_FASTCALL TypeJ::UpdatePrg(uint address,uint bank) 268 { 269 prg.SwapBank<SIZE_8K>( address, exPrg[GetPrgIndex(address)] ); 270 } 271 GetChrSource(uint bank) const272 uint NST_FASTCALL TypeA::GetChrSource(uint bank) const 273 { 274 return bank - 8 <= 1; 275 } 276 GetChrSource(uint bank) const277 uint NST_FASTCALL TypeB::GetChrSource(uint bank) const 278 { 279 return bank >> 7 & 0x1; 280 } 281 GetChrSource(uint bank) const282 uint NST_FASTCALL TypeC::GetChrSource(uint bank) const 283 { 284 return bank - 8 <= 3; 285 } 286 GetChrSource(uint bank) const287 uint NST_FASTCALL TypeD::GetChrSource(uint bank) const 288 { 289 return bank <= 1; 290 } 291 GetChrSource(uint bank) const292 uint NST_FASTCALL TypeE::GetChrSource(uint bank) const 293 { 294 return bank <= 3; 295 } 296 GetChrSource(uint) const297 uint NST_FASTCALL TypeF::GetChrSource(uint) const 298 { 299 return 0; 300 } 301 } 302 } 303 } 304 } 305