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 "NstBoard.hpp" 26 #include "NstBoardMmc3.hpp" 27 #include "NstBoardUnlA9746.hpp" 28 29 namespace Nes 30 { 31 namespace Core 32 { 33 namespace Boards 34 { 35 namespace Unlicensed 36 { 37 #ifdef NST_MSVC_OPTIMIZE 38 #pragma optimize("s", on) 39 #endif 40 SubReset(const bool hard)41 void A9746::SubReset(const bool hard) 42 { 43 exRegs[0] = 0; 44 exRegs[1] = 0; 45 exRegs[2] = 0; 46 47 Mmc3::SubReset( hard ); 48 49 for (uint i=0x8000; i < 0xA000; i += 0x4) 50 { 51 Map( i + 0x0, &A9746::Poke_8000 ); 52 Map( i + 0x1, &A9746::Poke_8001 ); 53 Map( i + 0x2, &A9746::Poke_8002 ); 54 Map( i + 0x3, NOP_POKE ); 55 } 56 } 57 SubLoad(State::Loader & state,const dword baseChunk)58 void A9746::SubLoad(State::Loader& state,const dword baseChunk) 59 { 60 if (baseChunk == AsciiId<'A','9','7'>::V) 61 { 62 while (const dword chunk = state.Begin()) 63 { 64 if (chunk == AsciiId<'R','E','G'>::V) 65 { 66 State::Loader::Data<3> data( state ); 67 68 exRegs[0] = data[0]; 69 exRegs[1] = data[1]; 70 exRegs[2] = data[2] << 4; 71 } 72 73 state.End(); 74 } 75 } 76 else 77 { 78 Mmc3::SubLoad( state, baseChunk ); 79 } 80 } 81 SubSave(State::Saver & state) const82 void A9746::SubSave(State::Saver& state) const 83 { 84 Mmc3::SubSave( state ); 85 86 const byte data[] = 87 { 88 exRegs[0], exRegs[1], exRegs[2] >> 4 89 }; 90 91 state.Begin( AsciiId<'A','9','7'>::V ).Begin( AsciiId<'R','E','G'>::V ).Write( data ).End().End(); 92 } 93 94 #ifdef NST_MSVC_OPTIMIZE 95 #pragma optimize("", on) 96 #endif 97 98 NES_POKE_AD(A9746,8000) 99 { 100 exRegs[0] = 0; 101 exRegs[1] = data; 102 } 103 104 NES_POKE_D(A9746,8001) 105 { 106 ppu.Update(); 107 108 if (exRegs[0] - 0x23 < 4) 109 { 110 prg.SwapBank<SIZE_8K> 111 ( 112 (exRegs[0] - 0x23) << 13 ^ 0x6000, 113 (data >> 5 & 0x1) | 114 (data >> 3 & 0x2) | 115 (data >> 1 & 0x4) | 116 (data << 1 & 0x8) 117 ); 118 } 119 120 switch (exRegs[1]) 121 { 122 case 0x08: 123 case 0x0A: 124 case 0x0E: 125 case 0x12: 126 case 0x16: 127 case 0x1A: 128 case 0x1E: exRegs[2] = data << 4; break; 129 case 0x09: chr.SwapBank<SIZE_1K,0x0000>( exRegs[2] | (data >> 1 & 0xE) ); break; 130 case 0x0B: chr.SwapBank<SIZE_1K,0x0400>( exRegs[2] | (data >> 1 | 0x1) ); break; 131 case 0x0C: 132 case 0x0D: chr.SwapBank<SIZE_1K,0x0800>( exRegs[2] | (data >> 1 & 0xE) ); break; 133 case 0x0F: chr.SwapBank<SIZE_1K,0x0C00>( exRegs[2] | (data >> 1 | 0x1) ); break; 134 case 0x10: 135 case 0x11: chr.SwapBank<SIZE_1K,0x1000>( exRegs[2] | (data >> 1 & 0xF) ); break; 136 case 0x14: 137 case 0x15: chr.SwapBank<SIZE_1K,0x1400>( exRegs[2] | (data >> 1 & 0xF) ); break; 138 case 0x18: 139 case 0x19: chr.SwapBank<SIZE_1K,0x1800>( exRegs[2] | (data >> 1 & 0xF) ); break; 140 case 0x1C: 141 case 0x1D: chr.SwapBank<SIZE_1K,0x1C00>( exRegs[2] | (data >> 1 & 0xF) ); break; 142 } 143 } 144 145 NES_POKE_AD(A9746,8002) 146 { 147 exRegs[0] = data; 148 exRegs[1] = 0; 149 } 150 } 151 } 152 } 153 } 154