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 "../NstTimer.hpp" 26 #include "NstBoard.hpp" 27 #include "NstBoardKonamiVrc4.hpp" 28 #include "NstBoardUnlWorldHero.hpp" 29 30 namespace Nes 31 { 32 namespace Core 33 { 34 namespace Boards 35 { 36 namespace Unlicensed 37 { 38 #ifdef NST_MSVC_OPTIMIZE 39 #pragma optimize("s", on) 40 #endif 41 WorldHero(const Context & c)42 WorldHero::WorldHero(const Context& c) 43 : Board(c), irq(*c.cpu) {} 44 SubReset(const bool hard)45 void WorldHero::SubReset(const bool hard) 46 { 47 if (hard) 48 prgSwap = 0; 49 50 irq.Reset( hard, hard ? false : irq.Connected() ); 51 52 for (dword i=0x8000; i <= 0xFFFF; ++i) 53 { 54 switch (i & 0xF0C3) 55 { 56 case 0x8000: Map( i, &WorldHero::Poke_8000 ); break; 57 case 0x9000: Map( i, NMT_SWAP_VH01 ); break; 58 case 0x9002: 59 case 0x9080: Map( i, &WorldHero::Poke_9000 ); break; 60 case 0xA000: Map( i, PRG_SWAP_8K_1 ); break; 61 case 0xB000: 62 case 0xB001: 63 case 0xB002: 64 case 0xB003: 65 case 0xC000: 66 case 0xC001: 67 case 0xC002: 68 case 0xC003: 69 case 0xD000: 70 case 0xD001: 71 case 0xD002: 72 case 0xD003: 73 case 0xE000: 74 case 0xE001: 75 case 0xE002: 76 case 0xE003: Map( i, &WorldHero::Poke_B000 ); break; 77 case 0xF000: Map( i, &WorldHero::Poke_F000 ); break; 78 case 0xF001: Map( i, &WorldHero::Poke_F001 ); break; 79 case 0xF002: Map( i, &WorldHero::Poke_F002 ); break; 80 case 0xF003: Map( i, &WorldHero::Poke_F003 ); break; 81 } 82 } 83 } 84 SubLoad(State::Loader & state,const dword baseChunk)85 void WorldHero::SubLoad(State::Loader& state,const dword baseChunk) 86 { 87 NST_VERIFY( baseChunk == (AsciiId<'U','W','H'>::V) ); 88 89 if (baseChunk == AsciiId<'U','W','H'>::V) 90 { 91 while (const dword chunk = state.Begin()) 92 { 93 switch (chunk) 94 { 95 case AsciiId<'R','E','G'>::V: 96 97 prgSwap = state.Read8() & 0x2; 98 break; 99 100 case AsciiId<'I','R','Q'>::V: 101 102 irq.LoadState( state ); 103 break; 104 } 105 106 state.End(); 107 } 108 } 109 } 110 SubSave(State::Saver & state) const111 void WorldHero::SubSave(State::Saver& state) const 112 { 113 state.Begin( AsciiId<'U','W','H'>::V ); 114 state.Begin( AsciiId<'R','E','G'>::V ).Write8( prgSwap ).End(); 115 irq.SaveState( state, AsciiId<'I','R','Q'>::V ); 116 state.End(); 117 } 118 119 #ifdef NST_MSVC_OPTIMIZE 120 #pragma optimize("", on) 121 #endif 122 123 NES_POKE_D(WorldHero,8000) 124 { 125 prg.SwapBank<SIZE_8K>( prgSwap << 13, data ); 126 } 127 128 NES_POKE_D(WorldHero,9000) 129 { 130 data &= 0x2; 131 132 if (prgSwap != data) 133 { 134 prgSwap = data; 135 136 prg.SwapBanks<SIZE_8K,0x0000> 137 ( 138 prg.GetBank<SIZE_8K,0x4000>(), 139 prg.GetBank<SIZE_8K,0x0000>() 140 ); 141 } 142 } 143 NES_POKE_AD(WorldHero,B000)144 NES_POKE_AD(WorldHero,B000) 145 { 146 ppu.Update(); 147 const bool part = address & 0x1; 148 address = ((address - 0xB000) >> 1 & 0x1800) | (address << 9 & 0x0400); 149 chr.SwapBank<SIZE_1K>( address, (chr.GetBank<SIZE_1K>(address) & (part ? 0x00F : 0xFF0)) | (part ? data << 4 : data & 0xF) ); 150 } 151 NES_POKE_D(WorldHero,F000)152 NES_POKE_D(WorldHero,F000) 153 { 154 irq.WriteLatch0( data ); 155 } 156 NES_POKE_D(WorldHero,F001)157 NES_POKE_D(WorldHero,F001) 158 { 159 irq.WriteLatch1( data ); 160 } 161 NES_POKE_D(WorldHero,F002)162 NES_POKE_D(WorldHero,F002) 163 { 164 irq.Toggle( data ); 165 } 166 NES_POKE(WorldHero,F003)167 NES_POKE(WorldHero,F003) 168 { 169 irq.Toggle(); 170 } 171 Sync(Event event,Input::Controllers * controllers)172 void WorldHero::Sync(Event event,Input::Controllers* controllers) 173 { 174 if (event == EVENT_END_FRAME) 175 irq.VSync(); 176 177 Board::Sync( event, controllers ); 178 } 179 } 180 } 181 } 182 } 183