mirror of
https://github.com/TomHarte/CLK.git
synced 2024-11-26 08:49:37 +00:00
Converts 6560 to more project normative templated form.
This commit is contained in:
parent
3ad0b31db8
commit
428b6145fa
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace MOS;
|
using namespace MOS::MOS6560;
|
||||||
|
|
||||||
AudioGenerator::AudioGenerator(Concurrency::DeferringAsyncTaskQueue &audio_queue) :
|
AudioGenerator::AudioGenerator(Concurrency::DeferringAsyncTaskQueue &audio_queue) :
|
||||||
audio_queue_(audio_queue) {}
|
audio_queue_(audio_queue) {}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "../../Outputs/Speaker/Implementation/SampleSource.hpp"
|
#include "../../Outputs/Speaker/Implementation/SampleSource.hpp"
|
||||||
|
|
||||||
namespace MOS {
|
namespace MOS {
|
||||||
|
namespace MOS6560 {
|
||||||
|
|
||||||
// audio state
|
// audio state
|
||||||
class AudioGenerator: public ::Outputs::Speaker::SampleSource {
|
class AudioGenerator: public ::Outputs::Speaker::SampleSource {
|
||||||
@ -40,6 +41,17 @@ class AudioGenerator: public ::Outputs::Speaker::SampleSource {
|
|||||||
int16_t range_multiplier_ = 1;
|
int16_t range_multiplier_ = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BusHandler {
|
||||||
|
void perform_read(uint16_t address, uint8_t *pixel_data, uint8_t *colour_data) {
|
||||||
|
*pixel_data = 0xff;
|
||||||
|
*colour_data = 0xff;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class OutputMode {
|
||||||
|
PAL, NTSC
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
The 6560 Video Interface Chip ('VIC') is a video and audio output chip; it therefore vends both a @c CRT and a @c Speaker.
|
The 6560 Video Interface Chip ('VIC') is a video and audio output chip; it therefore vends both a @c CRT and a @c Speaker.
|
||||||
|
|
||||||
@ -48,9 +60,10 @@ class AudioGenerator: public ::Outputs::Speaker::SampleSource {
|
|||||||
|
|
||||||
@c set_register and @c get_register provide register access.
|
@c set_register and @c get_register provide register access.
|
||||||
*/
|
*/
|
||||||
template <class T> class MOS6560 {
|
template <class BusHandler> class MOS6560 {
|
||||||
public:
|
public:
|
||||||
MOS6560() :
|
MOS6560(BusHandler &bus_handler) :
|
||||||
|
bus_handler_(bus_handler),
|
||||||
crt_(new Outputs::CRT::CRT(65*4, 4, Outputs::CRT::DisplayType::NTSC60, 2)),
|
crt_(new Outputs::CRT::CRT(65*4, 4, Outputs::CRT::DisplayType::NTSC60, 2)),
|
||||||
audio_generator_(audio_queue_),
|
audio_generator_(audio_queue_),
|
||||||
speaker_(audio_generator_)
|
speaker_(audio_generator_)
|
||||||
@ -88,10 +101,6 @@ template <class T> class MOS6560 {
|
|||||||
speaker_.set_high_frequency_cutoff(cutoff);
|
speaker_.set_high_frequency_cutoff(cutoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum OutputMode {
|
|
||||||
PAL, NTSC
|
|
||||||
};
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Sets the output mode to either PAL or NTSC.
|
Sets the output mode to either PAL or NTSC.
|
||||||
*/
|
*/
|
||||||
@ -248,7 +257,7 @@ template <class T> class MOS6560 {
|
|||||||
|
|
||||||
uint8_t pixel_data;
|
uint8_t pixel_data;
|
||||||
uint8_t colour_data;
|
uint8_t colour_data;
|
||||||
static_cast<T *>(this)->perform_read(fetch_address, &pixel_data, &colour_data);
|
bus_handler_.perform_read(fetch_address, &pixel_data, &colour_data);
|
||||||
|
|
||||||
// TODO: there should be a further two-cycle delay on pixels being output; the reverse bit should
|
// TODO: there should be a further two-cycle delay on pixels being output; the reverse bit should
|
||||||
// divide the byte it is set for 3:1 and then continue as usual.
|
// divide the byte it is set for 3:1 and then continue as usual.
|
||||||
@ -422,6 +431,7 @@ template <class T> class MOS6560 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
BusHandler &bus_handler_;
|
||||||
std::unique_ptr<Outputs::CRT::CRT> crt_;
|
std::unique_ptr<Outputs::CRT::CRT> crt_;
|
||||||
|
|
||||||
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
Concurrency::DeferringAsyncTaskQueue audio_queue_;
|
||||||
@ -511,6 +521,7 @@ template <class T> class MOS6560 {
|
|||||||
OutputMode output_mode_;
|
OutputMode output_mode_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _560_hpp */
|
#endif /* _560_hpp */
|
||||||
|
@ -240,10 +240,10 @@ class SerialPort : public ::Commodore::Serial::Port {
|
|||||||
/*!
|
/*!
|
||||||
Provides the bus over which the Vic 6560 fetches memory in a Vic-20.
|
Provides the bus over which the Vic 6560 fetches memory in a Vic-20.
|
||||||
*/
|
*/
|
||||||
class Vic6560: public MOS::MOS6560<Vic6560> {
|
class Vic6560BusHandler {
|
||||||
public:
|
public:
|
||||||
/// Performs a read on behalf of the 6560; in practice uses @c video_memory_map and @c colour_memory to find data.
|
/// Performs a read on behalf of the 6560; in practice uses @c video_memory_map and @c colour_memory to find data.
|
||||||
inline void perform_read(uint16_t address, uint8_t *pixel_data, uint8_t *colour_data) {
|
forceinline void perform_read(uint16_t address, uint8_t *pixel_data, uint8_t *colour_data) {
|
||||||
*pixel_data = video_memory_map[address >> 10] ? video_memory_map[address >> 10][address & 0x3ff] : 0xff; // TODO
|
*pixel_data = video_memory_map[address >> 10] ? video_memory_map[address >> 10][address & 0x3ff] : 0xff; // TODO
|
||||||
*colour_data = colour_memory[address & 0x03ff];
|
*colour_data = colour_memory[address & 0x03ff];
|
||||||
}
|
}
|
||||||
@ -433,7 +433,7 @@ class ConcreteMachine:
|
|||||||
void set_ntsc_6560() {
|
void set_ntsc_6560() {
|
||||||
set_clock_rate(1022727);
|
set_clock_rate(1022727);
|
||||||
if(mos6560_) {
|
if(mos6560_) {
|
||||||
mos6560_->set_output_mode(MOS::MOS6560<Commodore::Vic20::Vic6560>::OutputMode::NTSC);
|
mos6560_->set_output_mode(MOS::MOS6560::OutputMode::NTSC);
|
||||||
mos6560_->set_clock_rate(1022727);
|
mos6560_->set_clock_rate(1022727);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,7 +441,7 @@ class ConcreteMachine:
|
|||||||
void set_pal_6560() {
|
void set_pal_6560() {
|
||||||
set_clock_rate(1108404);
|
set_clock_rate(1108404);
|
||||||
if(mos6560_) {
|
if(mos6560_) {
|
||||||
mos6560_->set_output_mode(MOS::MOS6560<Commodore::Vic20::Vic6560>::OutputMode::PAL);
|
mos6560_->set_output_mode(MOS::MOS6560::OutputMode::PAL);
|
||||||
mos6560_->set_clock_rate(1108404);
|
mos6560_->set_clock_rate(1108404);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,7 +459,7 @@ class ConcreteMachine:
|
|||||||
// Initialise the memory maps as all pointing to nothing
|
// Initialise the memory maps as all pointing to nothing
|
||||||
memset(processor_read_memory_map_, 0, sizeof(processor_read_memory_map_));
|
memset(processor_read_memory_map_, 0, sizeof(processor_read_memory_map_));
|
||||||
memset(processor_write_memory_map_, 0, sizeof(processor_write_memory_map_));
|
memset(processor_write_memory_map_, 0, sizeof(processor_write_memory_map_));
|
||||||
memset(mos6560_->video_memory_map, 0, sizeof(mos6560_->video_memory_map));
|
memset(mos6560_bus_handler_.video_memory_map, 0, sizeof(mos6560_bus_handler_.video_memory_map));
|
||||||
|
|
||||||
#define set_ram(baseaddr, length) \
|
#define set_ram(baseaddr, length) \
|
||||||
write_to_map(processor_read_memory_map_, &ram_[baseaddr], baseaddr, length); \
|
write_to_map(processor_read_memory_map_, &ram_[baseaddr], baseaddr, length); \
|
||||||
@ -503,11 +503,11 @@ class ConcreteMachine:
|
|||||||
for(auto addr = video_range.start; addr < video_range.end; addr += 0x400) {
|
for(auto addr = video_range.start; addr < video_range.end; addr += 0x400) {
|
||||||
auto destination_address = (addr & 0x1fff) | (((addr & 0x8000) >> 2) ^ 0x2000);
|
auto destination_address = (addr & 0x1fff) | (((addr & 0x8000) >> 2) ^ 0x2000);
|
||||||
if(processor_read_memory_map_[addr >> 10]) {
|
if(processor_read_memory_map_[addr >> 10]) {
|
||||||
write_to_map(mos6560_->video_memory_map, &ram_[addr], static_cast<uint16_t>(destination_address), 0x400);
|
write_to_map(mos6560_bus_handler_.video_memory_map, &ram_[addr], static_cast<uint16_t>(destination_address), 0x400);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mos6560_->colour_memory = colour_ram_;
|
mos6560_bus_handler_.colour_memory = colour_ram_;
|
||||||
|
|
||||||
// install the BASIC ROM
|
// install the BASIC ROM
|
||||||
write_to_map(processor_read_memory_map_, basic_rom_.data(), 0xc000, static_cast<uint16_t>(basic_rom_.size()));
|
write_to_map(processor_read_memory_map_, basic_rom_.data(), 0xc000, static_cast<uint16_t>(basic_rom_.size()));
|
||||||
@ -539,7 +539,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
write_to_map(processor_read_memory_map_, roms_[character_rom].data(), 0x8000, static_cast<uint16_t>(roms_[character_rom].size()));
|
write_to_map(processor_read_memory_map_, roms_[character_rom].data(), 0x8000, static_cast<uint16_t>(roms_[character_rom].size()));
|
||||||
write_to_map(mos6560_->video_memory_map, roms_[character_rom].data(), 0x0000, static_cast<uint16_t>(roms_[character_rom].size()));
|
write_to_map(mos6560_bus_handler_.video_memory_map, roms_[character_rom].data(), 0x0000, static_cast<uint16_t>(roms_[character_rom].size()));
|
||||||
write_to_map(processor_read_memory_map_, roms_[kernel_rom].data(), 0xe000, static_cast<uint16_t>(roms_[kernel_rom].size()));
|
write_to_map(processor_read_memory_map_, roms_[kernel_rom].data(), 0xe000, static_cast<uint16_t>(roms_[kernel_rom].size()));
|
||||||
|
|
||||||
// install the inserted ROM if there is one
|
// install the inserted ROM if there is one
|
||||||
@ -679,7 +679,7 @@ class ConcreteMachine:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setup_output(float aspect_ratio) override final {
|
void setup_output(float aspect_ratio) override final {
|
||||||
mos6560_.reset(new Vic6560());
|
mos6560_.reset(new MOS::MOS6560::MOS6560<Vic6560BusHandler>(mos6560_bus_handler_));
|
||||||
mos6560_->set_high_frequency_cutoff(1600); // There is a 1.6Khz low-pass filter in the Vic-20.
|
mos6560_->set_high_frequency_cutoff(1600); // There is a 1.6Khz low-pass filter in the Vic-20.
|
||||||
// Make a guess: PAL. Without setting a clock rate the 6560 isn't fully set up so contractually something must be set.
|
// Make a guess: PAL. Without setting a clock rate the 6560 isn't fully set up so contractually something must be set.
|
||||||
set_memory_map(commodore_target_.memory_model, commodore_target_.region);
|
set_memory_map(commodore_target_.memory_model, commodore_target_.region);
|
||||||
@ -789,7 +789,8 @@ class ConcreteMachine:
|
|||||||
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
|
std::vector<std::unique_ptr<Inputs::Joystick>> joysticks_;
|
||||||
|
|
||||||
Cycles cycles_since_mos6560_update_;
|
Cycles cycles_since_mos6560_update_;
|
||||||
std::unique_ptr<Vic6560> mos6560_;
|
Vic6560BusHandler mos6560_bus_handler_;
|
||||||
|
std::unique_ptr<MOS::MOS6560::MOS6560<Vic6560BusHandler>> mos6560_;
|
||||||
std::shared_ptr<UserPortVIA> user_port_via_port_handler_;
|
std::shared_ptr<UserPortVIA> user_port_via_port_handler_;
|
||||||
std::shared_ptr<KeyboardVIA> keyboard_via_port_handler_;
|
std::shared_ptr<KeyboardVIA> keyboard_via_port_handler_;
|
||||||
std::shared_ptr<SerialPort> serial_port_;
|
std::shared_ptr<SerialPort> serial_port_;
|
||||||
|
Loading…
Reference in New Issue
Block a user