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 "../NstDipSwitches.hpp"
27 #include "NstBoardBmc8157.hpp"
28 
29 namespace Nes
30 {
31 	namespace Core
32 	{
33 		namespace Boards
34 		{
35 			namespace Bmc
36 			{
37 				#ifdef NST_MSVC_OPTIMIZE
38 				#pragma optimize("s", on)
39 				#endif
40 
CartSwitches()41 				B8157::CartSwitches::CartSwitches()
42 				: mode(0x100) {}
43 
SetMode(uint value)44 				inline void B8157::CartSwitches::SetMode(uint value)
45 				{
46 					mode = value ? 0x100 : 0x000;
47 				}
48 
GetMode() const49 				inline uint B8157::CartSwitches::GetMode() const
50 				{
51 					return mode;
52 				}
53 
GetValue(uint) const54 				uint B8157::CartSwitches::GetValue(uint) const
55 				{
56 					return mode ? 0 : 1;
57 				}
58 
SetValue(uint,uint value)59 				void B8157::CartSwitches::SetValue(uint,uint value)
60 				{
61 					mode = value ? 0x000 : 0x100;
62 				}
63 
NumDips() const64 				uint B8157::CartSwitches::NumDips() const
65 				{
66 					return 1;
67 				}
68 
NumValues(uint) const69 				uint B8157::CartSwitches::NumValues(uint) const
70 				{
71 					return 2;
72 				}
73 
GetDipName(uint) const74 				cstring B8157::CartSwitches::GetDipName(uint) const
75 				{
76 					return "Mode";
77 				}
78 
GetValueName(uint,uint i) const79 				cstring B8157::CartSwitches::GetValueName(uint,uint i) const
80 				{
81 					return i ? "20-in-1" : "4-in-1";
82 				}
83 
QueryDevice(DeviceType type)84 				B8157::Device B8157::QueryDevice(DeviceType type)
85 				{
86 					if (type == DEVICE_DIP_SWITCHES)
87 						return &cartSwitches;
88 					else
89 						return Board::QueryDevice( type );
90 				}
91 
SubReset(const bool hard)92 				void B8157::SubReset(const bool hard)
93 				{
94 					Map( 0x8000U, 0xFFFFU, &B8157::Peek_8000, &B8157::Poke_8000 );
95 
96 					trash = 0x00;
97 
98 					if (hard)
99 						NES_DO_POKE(8000,0x8000,0x00);
100 				}
101 
SubLoad(State::Loader & state,const dword baseChunk)102 				void B8157::SubLoad(State::Loader& state,const dword baseChunk)
103 				{
104 					NST_VERIFY( baseChunk == (AsciiId<'B','8','1'>::V) );
105 
106 					if (baseChunk == AsciiId<'B','8','1'>::V)
107 					{
108 						while (const dword chunk = state.Begin())
109 						{
110 							if (chunk == AsciiId<'R','E','G'>::V)
111 							{
112 								const uint data = state.Read8();
113 								trash = (data & 0x2) ? 0xFF : 0x00;
114 								cartSwitches.SetMode( data & 0x1 );
115 							}
116 
117 							state.End();
118 						}
119 					}
120 				}
121 
SubSave(State::Saver & state) const122 				void B8157::SubSave(State::Saver& state) const
123 				{
124 					state.Begin( AsciiId<'B','8','1'>::V ).Begin( AsciiId<'R','E','G'>::V ).Write8( (cartSwitches.GetMode() ? 0x1U : 0x0U) | (trash ? 0x2U : 0x0U) ).End().End();
125 				}
126 
127 				#ifdef NST_MSVC_OPTIMIZE
128 				#pragma optimize("", on)
129 				#endif
130 
131 				NES_PEEK_A(B8157,8000)
132 				{
133 					return prg.Peek( address - 0x8000 ) | trash;
134 				}
135 
136 				NES_POKE_A(B8157,8000)
137 				{
138 					trash = (address & cartSwitches.GetMode()) ? 0xFF : 0x00;
139 
140 					prg.SwapBanks<SIZE_16K,0x0000>
141 					(
142 						(address >> 2 & 0x18) | (address >> 2 & 0x7),
143 						(address >> 2 & 0x18) | ((address & 0x200) ? 0x7 : 0x0)
144 					);
145 
146 					ppu.SetMirroring( (address & 0x2) ? Ppu::NMT_H : Ppu::NMT_V );
147 				}
148 			}
149 		}
150 	}
151 }
152