mirror of
https://github.com/TomHarte/CLK.git
synced 2025-02-05 05:34:20 +00:00
This has now successfully loaded its first PRG-as-a-tape.
This commit is contained in:
parent
902c0f967a
commit
4edd1214f1
@ -108,10 +108,10 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin
|
|||||||
// printf("%04x\n", address);
|
// printf("%04x\n", address);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if(operation == CPU6502::BusOperation::Write && (address >= 0x033C && address < 0x033C + 192))
|
// if(operation == CPU6502::BusOperation::Write && (address >= 0x033C && address < 0x033C + 192))
|
||||||
{
|
// {
|
||||||
printf("\n[%04x] <- %02x\n", address, *value);
|
// printf("\n[%04x] <- %02x\n", address, *value);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// run the phase-1 part of this cycle, in which the VIC accesses memory
|
// run the phase-1 part of this cycle, in which the VIC accesses memory
|
||||||
_mos6560->run_for_cycles(1);
|
_mos6560->run_for_cycles(1);
|
||||||
@ -238,11 +238,11 @@ void Machine::set_prg(const char *file_name, size_t length, const uint8_t *data)
|
|||||||
_rom_length = (uint16_t)(length - 2);
|
_rom_length = (uint16_t)(length - 2);
|
||||||
|
|
||||||
// install in the ROM area if this looks like a ROM; otherwise put on tape and throw into that mechanism
|
// install in the ROM area if this looks like a ROM; otherwise put on tape and throw into that mechanism
|
||||||
if(_rom_address == 0xa000 && (_rom_length == 0x1000 || _rom_length == 0x2000))
|
if(_rom_address == 0xa000)
|
||||||
{
|
{
|
||||||
_rom = new uint8_t[length - 2];
|
_rom = new uint8_t[0x2000];
|
||||||
memcpy(_rom, &data[2], length - 2);
|
memcpy(_rom, &data[2], length - 2);
|
||||||
write_to_map(_processorReadMemoryMap, _rom, _rom_address, _rom_length);
|
write_to_map(_processorReadMemoryMap, _rom, _rom_address, 0x2000);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -29,9 +29,6 @@ TapePRG::TapePRG(const char *file_name) : _file(nullptr), _bitPhase(3), _filePha
|
|||||||
_load_address |= (uint16_t)fgetc(_file) << 8;
|
_load_address |= (uint16_t)fgetc(_file) << 8;
|
||||||
_length = (uint16_t)(file_stats.st_size - 2);
|
_length = (uint16_t)(file_stats.st_size - 2);
|
||||||
|
|
||||||
fseek(_file, 2, SEEK_SET);
|
|
||||||
|
|
||||||
|
|
||||||
if (_load_address + _length >= 65536)
|
if (_load_address + _length >= 65536)
|
||||||
throw ErrorBadFormat;
|
throw ErrorBadFormat;
|
||||||
}
|
}
|
||||||
@ -53,6 +50,8 @@ Tape::Pulse TapePRG::get_next_pulse()
|
|||||||
if(!_bitPhase) get_next_output_token();
|
if(!_bitPhase) get_next_output_token();
|
||||||
|
|
||||||
Tape::Pulse pulse;
|
Tape::Pulse pulse;
|
||||||
|
pulse.length.clock_rate = 1000000;
|
||||||
|
pulse.type = (_bitPhase&1) ? Pulse::High : Pulse::Low;
|
||||||
switch(_outputToken)
|
switch(_outputToken)
|
||||||
{
|
{
|
||||||
case Leader: pulse.length.length = leader_zero_length; break;
|
case Leader: pulse.length.length = leader_zero_length; break;
|
||||||
@ -60,9 +59,8 @@ Tape::Pulse TapePRG::get_next_pulse()
|
|||||||
case One: pulse.length.length = (_bitPhase&2) ? zero_length : one_length; break;
|
case One: pulse.length.length = (_bitPhase&2) ? zero_length : one_length; break;
|
||||||
case WordMarker: pulse.length.length = (_bitPhase&2) ? one_length : marker_length; break;
|
case WordMarker: pulse.length.length = (_bitPhase&2) ? one_length : marker_length; break;
|
||||||
case EndOfBlock: pulse.length.length = (_bitPhase&2) ? zero_length : marker_length; break;
|
case EndOfBlock: pulse.length.length = (_bitPhase&2) ? zero_length : marker_length; break;
|
||||||
|
case Silence: pulse.type = Pulse::Zero; pulse.length.length = 5000; break;
|
||||||
}
|
}
|
||||||
pulse.length.clock_rate = 1000000;
|
|
||||||
pulse.type = (_bitPhase&1) ? Pulse::High : Pulse::Low;
|
|
||||||
return pulse;
|
return pulse;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,17 +77,23 @@ void TapePRG::get_next_output_token()
|
|||||||
{
|
{
|
||||||
static const int block_length = 192; // not counting the checksum
|
static const int block_length = 192; // not counting the checksum
|
||||||
static const int countdown_bytes = 9;
|
static const int countdown_bytes = 9;
|
||||||
|
static const int leadin_length = 20000;
|
||||||
|
static const int block_leadin_length = 5000;
|
||||||
|
|
||||||
|
if(_filePhase == FilePhaseHeaderDataGap)
|
||||||
|
{
|
||||||
|
_outputToken = Silence;
|
||||||
|
_filePhase = FilePhaseData;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// the lead-in is 20,000 instances of the lead-in pair; every other phase begins with 5000
|
// the lead-in is 20,000 instances of the lead-in pair; every other phase begins with 5000
|
||||||
// before doing whatever it should be doing
|
// before doing whatever it should be doing
|
||||||
if((_filePhase == FilePhaseLeadIn || _filePhase == FilePhaseHeaderDataGap) || _phaseOffset < 50)
|
if(_filePhase == FilePhaseLeadIn || _phaseOffset < block_leadin_length)
|
||||||
{
|
{
|
||||||
_outputToken = Leader;
|
_outputToken = Leader;
|
||||||
_phaseOffset++;
|
_phaseOffset++;
|
||||||
if(
|
if(_filePhase == FilePhaseLeadIn && _phaseOffset == leadin_length)
|
||||||
(_filePhase == FilePhaseLeadIn && _phaseOffset == 20000) ||
|
|
||||||
(_filePhase == FilePhaseHeaderDataGap && _phaseOffset == 5586)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
_phaseOffset = 0;
|
_phaseOffset = 0;
|
||||||
_filePhase = (_filePhase == FilePhaseLeadIn) ? FilePhaseHeader : FilePhaseData;
|
_filePhase = (_filePhase == FilePhaseLeadIn) ? FilePhaseHeader : FilePhaseData;
|
||||||
@ -98,12 +102,17 @@ void TapePRG::get_next_output_token()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// determine whether a new byte needs to be queued up
|
// determine whether a new byte needs to be queued up
|
||||||
int block_offset = _phaseOffset - 50;
|
int block_offset = _phaseOffset - block_leadin_length;
|
||||||
int bit_offset = block_offset % 10;
|
int bit_offset = block_offset % 10;
|
||||||
int byte_offset = block_offset / 10;
|
int byte_offset = block_offset / 10;
|
||||||
_phaseOffset++;
|
_phaseOffset++;
|
||||||
|
|
||||||
if(byte_offset == block_length + countdown_bytes + 1) // i.e. after the checksum
|
if(!bit_offset &&
|
||||||
|
(
|
||||||
|
(_filePhase == FilePhaseHeader && byte_offset == block_length + countdown_bytes + 1) ||
|
||||||
|
feof(_file)
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
_outputToken = EndOfBlock;
|
_outputToken = EndOfBlock;
|
||||||
_phaseOffset = 0;
|
_phaseOffset = 0;
|
||||||
@ -111,22 +120,16 @@ void TapePRG::get_next_output_token()
|
|||||||
switch(_filePhase)
|
switch(_filePhase)
|
||||||
{
|
{
|
||||||
default: break;
|
default: break;
|
||||||
// case FilePhaseLeadIn:
|
|
||||||
// _filePhase = FilePhaseHeader;
|
|
||||||
// break;
|
|
||||||
case FilePhaseHeader:
|
case FilePhaseHeader:
|
||||||
_copy_mask ^= 0x80;
|
_copy_mask ^= 0x80;
|
||||||
if(_copy_mask) _filePhase = FilePhaseHeaderDataGap;
|
if(_copy_mask) _filePhase = FilePhaseHeaderDataGap;
|
||||||
break;
|
break;
|
||||||
case FilePhaseData:
|
case FilePhaseData:
|
||||||
if(feof(_file))
|
_copy_mask ^= 0x80;
|
||||||
{
|
fseek(_file, 2, SEEK_SET);
|
||||||
_copy_mask ^= 0x80;
|
if(_copy_mask) reset();
|
||||||
fseek(_file, 2, SEEK_SET);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf("\n===\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,41 +140,48 @@ void TapePRG::get_next_output_token()
|
|||||||
{
|
{
|
||||||
_output_byte = (uint8_t)(countdown_bytes - byte_offset) | _copy_mask;
|
_output_byte = (uint8_t)(countdown_bytes - byte_offset) | _copy_mask;
|
||||||
}
|
}
|
||||||
else if(byte_offset == countdown_bytes + block_length)
|
|
||||||
{
|
|
||||||
_output_byte = _check_digit;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(byte_offset == countdown_bytes) _check_digit = 0;
|
|
||||||
if(_filePhase == FilePhaseHeader)
|
if(_filePhase == FilePhaseHeader)
|
||||||
{
|
{
|
||||||
switch(byte_offset - countdown_bytes)
|
if(byte_offset == countdown_bytes + block_length)
|
||||||
{
|
{
|
||||||
case 0: _output_byte = 0x03; break;
|
_output_byte = _check_digit;
|
||||||
case 1: _output_byte = _load_address & 0xff; break;
|
}
|
||||||
case 2: _output_byte = (_load_address >> 8)&0xff; break;
|
else
|
||||||
case 3: _output_byte = (_load_address + _length) & 0xff; break;
|
{
|
||||||
case 4: _output_byte = ((_load_address + _length) >> 8) & 0xff; break;
|
if(byte_offset == countdown_bytes) _check_digit = 0;
|
||||||
|
if(_filePhase == FilePhaseHeader)
|
||||||
|
{
|
||||||
|
switch(byte_offset - countdown_bytes)
|
||||||
|
{
|
||||||
|
case 0: _output_byte = 0x03; break;
|
||||||
|
case 1: _output_byte = _load_address & 0xff; break;
|
||||||
|
case 2: _output_byte = (_load_address >> 8)&0xff; break;
|
||||||
|
case 3: _output_byte = (_load_address + _length) & 0xff; break;
|
||||||
|
case 4: _output_byte = ((_load_address + _length) >> 8) & 0xff; break;
|
||||||
|
|
||||||
case 5: _output_byte = 0x50; break; // P
|
case 5: _output_byte = 0x50; break; // P
|
||||||
case 6: _output_byte = 0x52; break; // R
|
case 6: _output_byte = 0x52; break; // R
|
||||||
case 7: _output_byte = 0x47; break; // G
|
case 7: _output_byte = 0x47; break; // G
|
||||||
default:
|
default:
|
||||||
_output_byte = 0x20;
|
_output_byte = 0x20;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_output_byte = (uint8_t)fgetc(_file);
|
_output_byte = (uint8_t)fgetc(_file);
|
||||||
if(feof(_file)) _output_byte = 0x00;
|
if(feof(_file))
|
||||||
|
{
|
||||||
|
_output_byte = _check_digit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_check_digit ^= _output_byte;
|
_check_digit ^= _output_byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" %02x", _output_byte);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(bit_offset)
|
switch(bit_offset)
|
||||||
@ -189,7 +199,6 @@ void TapePRG::get_next_output_token()
|
|||||||
parity ^= (parity >> 2);
|
parity ^= (parity >> 2);
|
||||||
parity ^= (parity >> 1);
|
parity ^= (parity >> 1);
|
||||||
_outputToken = (parity&1) ? Zero : One;
|
_outputToken = (parity&1) ? Zero : One;
|
||||||
printf("[%d]", parity&1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,8 @@ class TapePRG: public Tape {
|
|||||||
Zero,
|
Zero,
|
||||||
One,
|
One,
|
||||||
WordMarker,
|
WordMarker,
|
||||||
EndOfBlock
|
EndOfBlock,
|
||||||
|
Silence
|
||||||
} _outputToken;
|
} _outputToken;
|
||||||
void get_next_output_token();
|
void get_next_output_token();
|
||||||
uint8_t _output_byte;
|
uint8_t _output_byte;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user