1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-26 23:52:26 +00:00

Merge pull request #397 from TomHarte/Vic20FastTape

Improves Vic-20 fast tape ownership and simplifies memory logic.
This commit is contained in:
Thomas Harte 2018-03-31 21:05:22 -04:00 committed by GitHub
commit 7b381a8b6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 35 deletions

View File

@ -87,8 +87,11 @@ void Analyser::Static::Commodore::AddTargets(const Media &media, std::vector<std
// make a first guess based on loading address
switch(files.front().starting_address) {
default:
printf("Starting address %04x?\n", files.front().starting_address);
case 0x1001:
default: break;
target->memory_model = Target::MemoryModel::Unexpanded;
break;
case 0x1201:
target->memory_model = Target::MemoryModel::ThirtyTwoKB;
break;

View File

@ -144,7 +144,7 @@ template <class T> class MOS6560 {
}
crt_->set_new_display_type(static_cast<unsigned int>(timing_.cycles_per_line*4), display_type);
// crt_->set_visible_area(Outputs::CRT::Rect(0.05f, 0.05f, 0.9f, 0.9f));
crt_->set_visible_area(Outputs::CRT::Rect(0.1f, 0.05f, 0.9f, 0.9f));
// switch(output_mode) {
// case OutputMode::PAL:

View File

@ -453,37 +453,53 @@ class ConcreteMachine:
set_pal_6560();
}
// Initialise the memory maps as all pointing to nothing
memset(processor_read_memory_map_, 0, sizeof(processor_read_memory_map_));
memset(processor_write_memory_map_, 0, sizeof(processor_write_memory_map_));
memset(mos6560_->video_memory_map, 0, sizeof(mos6560_->video_memory_map));
#define set_ram(baseaddr, length) \
write_to_map(processor_read_memory_map_, &ram_[baseaddr], baseaddr, length); \
write_to_map(processor_write_memory_map_, &ram_[baseaddr], baseaddr, length);
// Add 6502-visible RAM as requested
switch(memory_model) {
default: break;
case Analyser::Static::Commodore::Target::MemoryModel::Unexpanded:
// The default Vic-20 memory map has 1kb at address 0 and another 4kb at address 0x1000.
set_ram(0x0000, 0x0400);
set_ram(0x1000, 0x1000);
break;
case Analyser::Static::Commodore::Target::MemoryModel::EightKB:
write_to_map(processor_read_memory_map_, expansion_ram_, 0x0000, 0x1000);
write_to_map(processor_write_memory_map_, expansion_ram_, 0x0000, 0x1000);
// An 8kb Vic-20 fills in the gap between the two blocks of RAM on an unexpanded machine.
set_ram(0x0000, 0x2000);
break;
case Analyser::Static::Commodore::Target::MemoryModel::ThirtyTwoKB:
write_to_map(processor_read_memory_map_, expansion_ram_, 0x0000, 0x8000);
write_to_map(processor_write_memory_map_, expansion_ram_, 0x0000, 0x8000);
// A 32kb Vic-20 fills the entire lower 32kb with RAM.
set_ram(0x0000, 0x8000);
break;
}
// install the system ROMs and VIC-visible memory
write_to_map(processor_read_memory_map_, user_basic_memory_, 0x0000, sizeof(user_basic_memory_));
write_to_map(processor_read_memory_map_, screen_memory_, 0x1000, sizeof(screen_memory_));
write_to_map(processor_read_memory_map_, colour_memory_, 0x9400, sizeof(colour_memory_));
#undef set_ram
write_to_map(processor_write_memory_map_, user_basic_memory_, 0x0000, sizeof(user_basic_memory_));
write_to_map(processor_write_memory_map_, screen_memory_, 0x1000, sizeof(screen_memory_));
write_to_map(processor_write_memory_map_, colour_memory_, 0x9400, sizeof(colour_memory_));
// all expansions also have colour RAM visible at 0x9400.
write_to_map(processor_read_memory_map_, colour_ram_, 0x9400, sizeof(colour_ram_));
write_to_map(processor_write_memory_map_, colour_ram_, 0x9400, sizeof(colour_ram_));
write_to_map(mos6560_->video_memory_map, user_basic_memory_, 0x2000, sizeof(user_basic_memory_));
write_to_map(mos6560_->video_memory_map, screen_memory_, 0x3000, sizeof(screen_memory_));
mos6560_->colour_memory = colour_memory_;
// also push memory resources into the 6560 video memory map; the 6560 has only a
// 14-bit address bus and the top bit is invested and used as bit 15 for the main
// memory bus.
for(int addr = 0; addr < 0x4000; addr += 0x400) {
int source_address = (addr & 0x1fff) | (((addr & 0x2000) << 2) ^ 0x8000);
if(processor_read_memory_map_[source_address >> 10]) {
write_to_map(mos6560_->video_memory_map, &ram_[source_address], static_cast<uint16_t>(addr), 0x400);
}
}
mos6560_->colour_memory = colour_ram_;
// install the BASIC ROM
write_to_map(processor_read_memory_map_, basic_rom_.data(), 0xc000, static_cast<uint16_t>(basic_rom_.size()));
// install the system ROM
ROM character_rom;
ROM kernel_rom;
switch(region) {
@ -545,30 +561,35 @@ class ConcreteMachine:
Storage::Tape::Commodore::Parser parser;
std::unique_ptr<Storage::Tape::Commodore::Header> header = parser.get_next_header(tape_->get_tape());
// serialise to wherever b2:b3 points
uint16_t tape_buffer_pointer = static_cast<uint16_t>(user_basic_memory_[0xb2]) | static_cast<uint16_t>(user_basic_memory_[0xb3] << 8);
const uint64_t tape_position = tape_->get_tape()->get_offset();
if(header) {
header->serialise(&user_basic_memory_[tape_buffer_pointer], 0x8000 - tape_buffer_pointer);
// serialise to wherever b2:b3 points
const uint16_t tape_buffer_pointer = static_cast<uint16_t>(ram_[0xb2]) | static_cast<uint16_t>(ram_[0xb3] << 8);
header->serialise(&ram_[tape_buffer_pointer], 0x8000 - tape_buffer_pointer);
hold_tape_ = true;
printf("Found header\n");
} else {
// no header found, so store end-of-tape
user_basic_memory_[tape_buffer_pointer] = 0x05; // i.e. end of tape
// no header found, so pretend this hack never interceded
tape_->get_tape()->set_offset(tape_position);
hold_tape_ = false;
printf("Didn't find header\n");
}
// clear status and the verify flag
user_basic_memory_[0x90] = 0;
user_basic_memory_[0x93] = 0;
ram_[0x90] = 0;
ram_[0x93] = 0;
*value = 0x0c; // i.e. NOP abs
*value = 0x0c; // i.e. NOP abs, to swallow the entire JSR
} else if(address == 0xf90b) {
uint8_t x = static_cast<uint8_t>(m6502_.get_value_of_register(CPU::MOS6502::Register::X));
if(x == 0xe) {
Storage::Tape::Commodore::Parser parser;
const uint64_t tape_position = tape_->get_tape()->get_offset();
std::unique_ptr<Storage::Tape::Commodore::Data> data = parser.get_next_data(tape_->get_tape());
const std::unique_ptr<Storage::Tape::Commodore::Data> data = parser.get_next_data(tape_->get_tape());
if(data) {
uint16_t start_address, end_address;
start_address = static_cast<uint16_t>(user_basic_memory_[0xc1] | (user_basic_memory_[0xc2] << 8));
end_address = static_cast<uint16_t>(user_basic_memory_[0xae] | (user_basic_memory_[0xaf] << 8));
start_address = static_cast<uint16_t>(ram_[0xc1] | (ram_[0xc2] << 8));
end_address = static_cast<uint16_t>(ram_[0xae] | (ram_[0xaf] << 8));
// perform a via-processor_write_memory_map_ memcpy
uint8_t *data_ptr = data->data.data();
@ -582,7 +603,7 @@ class ConcreteMachine:
}
// set tape status, carry and flag
user_basic_memory_[0x90] |= 0x40;
ram_[0x90] |= 0x40;
uint8_t flags = static_cast<uint8_t>(m6502_.get_value_of_register(CPU::MOS6502::Register::Flags));
flags &= ~static_cast<uint8_t>((CPU::MOS6502::Flag::Carry | CPU::MOS6502::Flag::Interrupt));
m6502_.set_value_of_register(CPU::MOS6502::Register::Flags, flags);
@ -591,8 +612,12 @@ class ConcreteMachine:
// ensure that the PC leaps to 0xfccf
m6502_.set_value_of_register(CPU::MOS6502::Register::ProgramCounter, 0xfccf);
*value = 0xea; // i.e. NOP implied
hold_tape_ = true;
printf("Found data\n");
} else {
tape_->get_tape()->set_offset(tape_position);
hold_tape_ = false;
printf("Didn't find data\n");
}
}
}
@ -621,7 +646,7 @@ class ConcreteMachine:
typer_.reset();
}
}
if(!tape_is_sleeping_) tape_->run_for(Cycles(1));
if(!tape_is_sleeping_ && !hold_tape_) tape_->run_for(Cycles(1));
if(c1540_) c1540_->run_for(Cycles(1));
return Cycles(1);
@ -716,14 +741,11 @@ class ConcreteMachine:
std::vector<uint8_t> character_rom_;
std::vector<uint8_t> basic_rom_;
std::vector<uint8_t> kernel_rom_;
uint8_t expansion_ram_[0x8000];
std::vector<uint8_t> rom_;
uint16_t rom_address_, rom_length_;
uint8_t user_basic_memory_[0x0400];
uint8_t screen_memory_[0x1000];
uint8_t colour_memory_[0x0400];
uint8_t ram_[0x8000];
uint8_t colour_ram_[0x0400];
std::function<std::vector<std::unique_ptr<std::vector<uint8_t>>>(const std::string &machine, const std::vector<std::string> &names)> rom_fetcher_;
@ -755,6 +777,7 @@ class ConcreteMachine:
// Tape
std::shared_ptr<Storage::Tape::BinaryTapePlayer> tape_;
bool use_fast_tape_hack_ = false;
bool hold_tape_ = false;
bool allow_fast_tape_hack_ = false;
bool tape_is_sleeping_ = true;
void set_use_fast_tape() {