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 <cstring> 26 #include "NstInpDevice.hpp" 27 #include "NstInpBarcodeWorld.hpp" 28 29 namespace Nes 30 { 31 namespace Core 32 { 33 namespace Input 34 { 35 #ifdef NST_MSVC_OPTIMIZE 36 #pragma optimize("s", on) 37 #endif 38 BarcodeWorld(const Cpu & cpu)39 BarcodeWorld::BarcodeWorld(const Cpu& cpu) 40 : Device(cpu,Api::Input::BARCODEWORLD) 41 { 42 BarcodeWorld::Reset(); 43 } 44 Reset()45 void BarcodeWorld::Reset() 46 { 47 reader.Reset(); 48 } 49 LoadState(State::Loader & loader,const dword id)50 void BarcodeWorld::LoadState(State::Loader& loader,const dword id) 51 { 52 reader.LoadState( loader, id ); 53 } 54 SaveState(State::Saver & saver,const byte id) const55 void BarcodeWorld::SaveState(State::Saver& saver,const byte id) const 56 { 57 reader.SaveState( saver, id ); 58 } 59 Reset()60 void BarcodeWorld::Reader::Reset() 61 { 62 stream = data; 63 std::memset( data, END, MAX_DATA_LENGTH ); 64 } 65 IsDigitsSupported(uint count) const66 bool BarcodeWorld::Reader::IsDigitsSupported(uint count) const 67 { 68 return count == NUM_DIGITS; 69 } 70 IsTransferring() const71 bool BarcodeWorld::Reader::IsTransferring() const 72 { 73 return *stream != END; 74 } 75 LoadState(State::Loader & loader,const dword id)76 void BarcodeWorld::Reader::LoadState(State::Loader& loader,const dword id) 77 { 78 if (id == AsciiId<'B','W'>::V) 79 { 80 Reset(); 81 82 while (const dword chunk = loader.Begin()) 83 { 84 switch (chunk) 85 { 86 case AsciiId<'P','T','R'>::V: 87 88 stream = data + (loader.Read8() & (MAX_DATA_LENGTH-1)); 89 break; 90 91 case AsciiId<'D','A','T'>::V: 92 93 loader.Uncompress( data ); 94 data[MAX_DATA_LENGTH-1] = END; 95 break; 96 } 97 98 loader.End(); 99 } 100 } 101 } 102 SaveState(State::Saver & saver,const byte id) const103 void BarcodeWorld::Reader::SaveState(State::Saver& saver,const byte id) const 104 { 105 saver.Begin( AsciiId<'B','W'>::R(0,0,id) ); 106 107 if (Reader::IsTransferring()) 108 { 109 saver.Begin( AsciiId<'P','T','R'>::V ).Write8( stream - data ).End(); 110 saver.Begin( AsciiId<'D','A','T'>::V ).Compress( data ).End(); 111 } 112 113 saver.End(); 114 } 115 Transfer(cstring const string,const uint length)116 bool BarcodeWorld::Reader::Transfer(cstring const string,const uint length) 117 { 118 NST_COMPILE_ASSERT( MAX_DATA_LENGTH >= 191 ); 119 120 Reset(); 121 122 if (!string || length != NUM_DIGITS) 123 return false; 124 125 byte code[NUM_DIGITS+7]; 126 127 for (uint i=0; i < NUM_DIGITS; ++i) 128 { 129 const int c = string[i]; 130 131 if (c >= '0' && c <= '9') 132 code[i] = c - '0' + Ascii<'0'>::V; 133 else 134 return false; 135 } 136 137 code[NUM_DIGITS+0] = Ascii<'S'>::V; 138 code[NUM_DIGITS+1] = Ascii<'U'>::V; 139 code[NUM_DIGITS+2] = Ascii<'N'>::V; 140 code[NUM_DIGITS+3] = Ascii<'S'>::V; 141 code[NUM_DIGITS+4] = Ascii<'O'>::V; 142 code[NUM_DIGITS+5] = Ascii<'F'>::V; 143 code[NUM_DIGITS+6] = Ascii<'T'>::V; 144 145 byte* NST_RESTRICT output = data; 146 147 *output++ = 0x04; 148 149 for (uint i=0; i < NUM_DIGITS+7; ++i) 150 { 151 *output++ = 0x04; 152 153 for (uint j=0x01, c=code[i]; j != 0x100; j <<= 1) 154 *output++ = (c & j) ? 0x00 : 0x04; 155 156 *output++ = 0x00; 157 } 158 159 return true; 160 } 161 162 #ifdef NST_MSVC_OPTIMIZE 163 #pragma optimize("", on) 164 #endif 165 Read()166 uint BarcodeWorld::Reader::Read() 167 { 168 if (Reader::IsTransferring()) 169 { 170 uint next = *stream; 171 stream += (next != END); 172 return next; 173 } 174 else 175 { 176 return 0; 177 } 178 } 179 Peek(uint port)180 uint BarcodeWorld::Peek(uint port) 181 { 182 return port == 1 ? reader.Read() : 0; 183 } 184 } 185 } 186 } 187