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 "NstBoardBmcGoldenGame260in1.hpp"
27 
28 namespace Nes
29 {
30 	namespace Core
31 	{
32 		namespace Boards
33 		{
34 			namespace Bmc
35 			{
36 				#ifdef NST_MSVC_OPTIMIZE
37 				#pragma optimize("s", on)
38 				#endif
39 
GoldenGame260in1(const Context & c)40 				GoldenGame260in1::GoldenGame260in1(const Context& c)
41 				:
42 				Board (c),
43 				selector
44 				(
45 					prg.Source().Size() == SIZE_1024K ? 0 :
46 					prg.Source().Size() == SIZE_2048K ? 1 :
47 					prg.Source().Size() == SIZE_3072K ? 2 : 3
48 				)
49 				{
50 				}
51 
SubReset(const bool hard)52 				void GoldenGame260in1::SubReset(const bool hard)
53 				{
54 					Map( 0x8000U, 0xFFFFU, &GoldenGame260in1::Poke_8000 );
55 
56 					if (selector != 3)
57 						Map( 0x8000U, 0xFFFFU, &GoldenGame260in1::Peek_8000 );
58 
59 					if (hard)
60 					{
61 						open = false;
62 						NES_DO_POKE(8000,0x8000,0x00);
63 					}
64 				}
65 
SubLoad(State::Loader & state,const dword baseChunk)66 				void GoldenGame260in1::SubLoad(State::Loader& state,const dword baseChunk)
67 				{
68 					if (selector != 3)
69 					{
70 						NST_VERIFY( baseChunk == (AsciiId<'B','G','G'>::V) );
71 
72 						if (baseChunk == AsciiId<'B','G','G'>::V)
73 						{
74 							while (const dword chunk = state.Begin())
75 							{
76 								if (chunk == AsciiId<'B','U','S'>::V)
77 									open = state.Read8() & 0x1;
78 
79 								state.End();
80 							}
81 						}
82 					}
83 				}
84 
SubSave(State::Saver & state) const85 				void GoldenGame260in1::SubSave(State::Saver& state) const
86 				{
87 					if (selector != 3)
88 						state.Begin( AsciiId<'B','G','G'>::V ).Begin( AsciiId<'B','U','S'>::V ).Write8( open != 0 ).End().End();
89 				}
90 
91 				#ifdef NST_MSVC_OPTIMIZE
92 				#pragma optimize("", on)
93 				#endif
94 
95 				NES_POKE_A(GoldenGame260in1,8000)
96 				{
97 					ppu.SetMirroring
98 					(
99 						(address & 0x0400) ? Ppu::NMT_0 :
100 						(address & 0x2000) ? Ppu::NMT_H :
101                                              Ppu::NMT_V
102 					);
103 
104 					static const byte slots[4][4][2] =
105 					{
106 						{ {0x00,0}, {0x00,1}, {0x00,1}, {0x00,1} },
107 						{ {0x00,0}, {0x00,1}, {0x20,0}, {0x00,1} },
108 						{ {0x00,0}, {0x00,1}, {0x20,0}, {0x40,0} },
109 						{ {0x00,0}, {0x20,0}, {0x40,0}, {0x60,0} }
110 					};
111 
112 					uint bank = slots[selector][address >> 8 & 0x3][0] | (address & 0x1F);
113 					open = slots[selector][address >> 8 & 0x3][1];
114 
115 					if (address & 0x800)
116 					{
117 						bank = (bank << 1) | (address >> 12 & 0x1);
118 						prg.SwapBanks<SIZE_16K,0x0000>( bank, bank );
119 					}
120 					else
121 					{
122 						prg.SwapBank<SIZE_32K,0x0000>( bank );
123 					}
124 				}
125 
126 				NES_PEEK_A(GoldenGame260in1,8000)
127 				{
128 					return !open ? prg.Peek(address - 0x8000) : (address >> 8);
129 				}
130 			}
131 		}
132 	}
133 }
134