2017-11-20 04:08:23 +00:00
|
|
|
#pragma once
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "BaseControlDevice.h"
|
|
|
|
#include "IBarcodeReader.h"
|
2018-07-01 19:21:05 +00:00
|
|
|
#include "MemoryManager.h"
|
2017-11-20 04:08:23 +00:00
|
|
|
|
|
|
|
class BarcodeBattlerReader : public BaseControlDevice, public IBarcodeReader
|
|
|
|
{
|
|
|
|
private:
|
2018-07-01 19:21:05 +00:00
|
|
|
static constexpr int StreamSize = 200;
|
2017-11-20 04:08:23 +00:00
|
|
|
uint64_t _newBarcode = 0;
|
|
|
|
uint32_t _newBarcodeDigitCount = 0;
|
|
|
|
|
|
|
|
uint8_t _barcodeStream[BarcodeBattlerReader::StreamSize];
|
2019-05-12 16:28:01 +00:00
|
|
|
uint64_t _insertCycle = 0;
|
2017-11-20 04:08:23 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
void StreamState(bool saving) override
|
|
|
|
{
|
|
|
|
BaseControlDevice::StreamState(saving);
|
|
|
|
|
|
|
|
ArrayInfo<uint8_t> bitStream{ _barcodeStream, BarcodeBattlerReader::StreamSize };
|
|
|
|
Stream(_newBarcode, _newBarcodeDigitCount, _insertCycle, bitStream);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsRawString() override
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InitBarcodeStream()
|
|
|
|
{
|
2017-12-04 04:12:16 +00:00
|
|
|
vector<uint8_t> state = GetRawState().State;
|
|
|
|
string barcodeText(state.begin(), state.end());
|
2017-11-20 04:08:23 +00:00
|
|
|
|
|
|
|
//Signature at the end, needed for code to be recognized
|
|
|
|
barcodeText += "EPOCH\xD\xA";
|
|
|
|
//Pad to 20 characters with spaces
|
|
|
|
barcodeText.insert(0, 20 - barcodeText.size(), ' ');
|
|
|
|
|
|
|
|
int pos = 0;
|
|
|
|
vector<uint8_t> bits;
|
|
|
|
for(int i = 0; i < 20; i++) {
|
|
|
|
_barcodeStream[pos++] = 1;
|
|
|
|
for(int j = 0; j < 8; j++) {
|
|
|
|
_barcodeStream[pos++] = ~((barcodeText[i] >> j) & 0x01);
|
|
|
|
}
|
|
|
|
_barcodeStream[pos++] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
2018-07-14 02:19:26 +00:00
|
|
|
BarcodeBattlerReader(shared_ptr<Console> console) : BaseControlDevice(console, BaseControlDevice::ExpDevicePort)
|
2017-11-20 04:08:23 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void InternalSetStateFromInput() override
|
|
|
|
{
|
|
|
|
ClearState();
|
|
|
|
|
|
|
|
if(_newBarcodeDigitCount > 0) {
|
|
|
|
string barcodeText = std::to_string(_newBarcode);
|
|
|
|
//Pad 8 or 13 character barcode with 0s at start
|
|
|
|
barcodeText.insert(0, _newBarcodeDigitCount - barcodeText.size(), '0');
|
|
|
|
SetTextState(barcodeText);
|
|
|
|
|
|
|
|
_newBarcode = 0;
|
|
|
|
_newBarcodeDigitCount = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void OnAfterSetState() override
|
|
|
|
{
|
|
|
|
if(GetRawState().State.size() > 0) {
|
|
|
|
InitBarcodeStream();
|
2018-07-01 19:21:05 +00:00
|
|
|
if(_console) {
|
|
|
|
_insertCycle = _console->GetCpu()->GetCycleCount();
|
|
|
|
}
|
2017-11-20 04:08:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InputBarcode(uint64_t barcode, uint32_t digitCount) override
|
|
|
|
{
|
|
|
|
_newBarcode = barcode;
|
|
|
|
_newBarcodeDigitCount = digitCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ReadRAM(uint16_t addr) override
|
|
|
|
{
|
|
|
|
if(addr == 0x4017) {
|
2019-05-12 16:28:01 +00:00
|
|
|
uint64_t elapsedCycles = _console->GetCpu()->GetCycleCount() - _insertCycle;
|
2017-11-20 04:08:23 +00:00
|
|
|
constexpr uint32_t cyclesPerBit = CPU::ClockRateNtsc / 1200;
|
|
|
|
|
2019-05-12 16:28:01 +00:00
|
|
|
uint32_t streamPosition = (uint32_t)(elapsedCycles / cyclesPerBit);
|
2017-11-20 04:08:23 +00:00
|
|
|
if(streamPosition < BarcodeBattlerReader::StreamSize) {
|
|
|
|
return _barcodeStream[streamPosition] << 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WriteRAM(uint16_t addr, uint8_t value) override
|
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|