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 <new>
26 #include "../NstMachine.hpp"
27 #include "../NstStream.hpp"
28 #include "../NstFds.hpp"
29 #include "NstApiCartridge.hpp"
30 #include "NstApiMachine.hpp"
31 #include "NstApiFds.hpp"
32 
33 namespace Nes
34 {
35 	namespace Api
36 	{
37 		#ifdef NST_MSVC_OPTIMIZE
38 		#pragma optimize("s", on)
39 		#endif
40 
41 		Fds::DiskCaller Fds::diskCallback;
42 		Fds::DriveCaller Fds::driveCallback;
43 
File()44 		Fds::DiskData::File::File() throw()
45 		:
46 		id      (0),
47 		index   (0),
48 		address (0),
49 		type    (TYPE_UNKNOWN)
50 		{
51 			for (uint i=0; i < sizeof(name); ++i)
52 				name[i] = '\0';
53 		}
54 
DiskData()55 		Fds::DiskData::DiskData() throw()
56 		{
57 		}
58 
~DiskData()59 		Fds::DiskData::~DiskData() throw()
60 		{
61 		}
62 
GetDiskData(uint side,DiskData & data) const63 		Result Fds::GetDiskData(uint side,DiskData& data) const throw()
64 		{
65 			if (emulator.Is(Machine::DISK))
66 				return static_cast<Core::Fds*>(emulator.image)->GetDiskData( side, data );
67 
68 			return RESULT_ERR_NOT_READY;
69 		}
70 
IsAnyDiskInserted() const71 		bool Fds::IsAnyDiskInserted() const throw()
72 		{
73 			if (emulator.Is(Machine::DISK))
74 				return static_cast<const Core::Fds*>(emulator.image)->IsAnyDiskInserted();
75 
76 			return false;
77 		}
78 
InsertDisk(uint disk,uint side)79 		Result Fds::InsertDisk(uint disk,uint side) throw()
80 		{
81 			if (emulator.Is(Machine::DISK) && !emulator.tracker.IsLocked())
82 				return emulator.tracker.TryResync( static_cast<Core::Fds*>(emulator.image)->InsertDisk( disk, side ) );
83 
84 			return RESULT_ERR_NOT_READY;
85 		}
86 
ChangeSide()87 		Result Fds::ChangeSide() throw()
88 		{
89 			const int disk = GetCurrentDisk();
90 
91 			if (disk != NO_DISK)
92 				return InsertDisk( disk, GetCurrentDiskSide() ^ 1 );
93 
94 			return RESULT_ERR_NOT_READY;
95 		}
96 
EjectDisk()97 		Result Fds::EjectDisk() throw()
98 		{
99 			if (emulator.Is(Machine::DISK) && !emulator.tracker.IsLocked())
100 				return emulator.tracker.TryResync( static_cast<Core::Fds*>(emulator.image)->EjectDisk() );
101 
102 			return RESULT_ERR_NOT_READY;
103 		}
104 
SetBIOS(std::istream * const stdStream)105 		Result Fds::SetBIOS(std::istream* const stdStream) throw()
106 		{
107 			if (emulator.Is(Machine::GAME,Machine::ON))
108 				return RESULT_ERR_NOT_READY;
109 
110 			try
111 			{
112 				if (stdStream)
113 				{
114 					Core::Stream::In stream( stdStream );
115 
116 					idword offset;
117 
118 					Cartridge::NesHeader setup;
119 
120 					byte header[16];
121 					stream.Read( header );
122 
123 					if (NES_FAILED(setup.Import( header, 16 )))
124 					{
125 						offset = -16;
126 					}
127 					else if (setup.prgRom >= Core::SIZE_8K)
128 					{
129 						offset = (setup.trainer ? 512 : 0) + (setup.prgRom - Core::SIZE_8K);
130 					}
131 					else
132 					{
133 						return RESULT_ERR_CORRUPT_FILE;
134 					}
135 
136 					stream.Seek( offset );
137 				}
138 
139 				Core::Fds::SetBios( stdStream );
140 			}
141 			catch (Result result)
142 			{
143 				return result;
144 			}
145 			catch (const std::bad_alloc&)
146 			{
147 				return RESULT_ERR_OUT_OF_MEMORY;
148 			}
149 			catch (...)
150 			{
151 				return RESULT_ERR_GENERIC;
152 			}
153 
154 			return RESULT_OK;
155 		}
156 
GetBIOS(std::ostream & stream) const157 		Result Fds::GetBIOS(std::ostream& stream) const throw()
158 		{
159 			try
160 			{
161 				return Core::Fds::GetBios( stream );
162 			}
163 			catch (Result result)
164 			{
165 				return result;
166 			}
167 			catch (const std::bad_alloc&)
168 			{
169 				return RESULT_ERR_OUT_OF_MEMORY;
170 			}
171 			catch (...)
172 			{
173 				return RESULT_ERR_GENERIC;
174 			}
175 		}
176 
HasBIOS() const177 		bool Fds::HasBIOS() const throw()
178 		{
179 			return Core::Fds::HasBios();
180 		}
181 
GetNumDisks() const182 		uint Fds::GetNumDisks() const throw()
183 		{
184 			if (emulator.Is(Machine::DISK))
185 				return static_cast<const Core::Fds*>(emulator.image)->NumDisks();
186 
187 			return 0;
188 		}
189 
GetNumSides() const190 		uint Fds::GetNumSides() const throw()
191 		{
192 			if (emulator.Is(Machine::DISK))
193 				return static_cast<const Core::Fds*>(emulator.image)->NumSides();
194 
195 			return 0;
196 		}
197 
GetCurrentDisk() const198 		int Fds::GetCurrentDisk() const throw()
199 		{
200 			if (emulator.Is(Machine::DISK))
201 				return static_cast<const Core::Fds*>(emulator.image)->CurrentDisk();
202 
203 			return NO_DISK;
204 		}
205 
GetCurrentDiskSide() const206 		int Fds::GetCurrentDiskSide() const throw()
207 		{
208 			if (emulator.Is(Machine::DISK))
209 				return static_cast<const Core::Fds*>(emulator.image)->CurrentDiskSide();
210 
211 			return NO_DISK;
212 		}
213 
CanChangeDiskSide() const214 		bool Fds::CanChangeDiskSide() const throw()
215 		{
216 			if (emulator.Is(Machine::DISK))
217 				return static_cast<const Core::Fds*>(emulator.image)->CanChangeDiskSide();
218 
219 			return false;
220 		}
221 
HasHeader() const222 		bool Fds::HasHeader() const throw()
223 		{
224 			return emulator.Is(Machine::DISK) && static_cast<const Core::Fds*>(emulator.image)->HasHeader();
225 		}
226 
227 		#ifdef NST_MSVC_OPTIMIZE
228 		#pragma optimize("", on)
229 		#endif
230 	}
231 }
232