mirror of
https://github.com/TomHarte/CLK.git
synced 2025-08-15 14:27:29 +00:00
Adjust factoring of read and write per expanded V9938 scope.
This commit is contained in:
@@ -517,21 +517,30 @@ void Base<personality>::output_border(int cycles, [[maybe_unused]] uint32_t cram
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - External interface.
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
void TMS9918<personality>::write(int address, uint8_t value) {
|
int Base<personality>::masked_address(int address) {
|
||||||
// Writes to address 0 are writes to the video RAM. Store
|
if constexpr (is_yamaha_vdp(personality)) {
|
||||||
// the value and return.
|
return address & 3;
|
||||||
if(!(address & 1)) {
|
} else {
|
||||||
this->write_phase_ = false;
|
return address & 1;
|
||||||
|
|
||||||
// Enqueue the write to occur at the next available slot.
|
|
||||||
this->read_ahead_buffer_ = value;
|
|
||||||
this->queued_access_ = MemoryAccess::Write;
|
|
||||||
this->cycles_until_access_ = Timing<personality>::VRAMAccessDelay;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
void Base<personality>::write_vram(uint8_t value) {
|
||||||
|
// Latch the value and exit.
|
||||||
|
this->write_phase_ = false;
|
||||||
|
|
||||||
|
// Enqueue the write to occur at the next available slot.
|
||||||
|
this->read_ahead_buffer_ = value;
|
||||||
|
this->queued_access_ = MemoryAccess::Write;
|
||||||
|
this->cycles_until_access_ = Timing<personality>::VRAMAccessDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
void Base<personality>::write_register(uint8_t value) {
|
||||||
// Writes to address 1 are performed in pairs; if this is the
|
// Writes to address 1 are performed in pairs; if this is the
|
||||||
// low byte of a value, store it and wait for the high byte.
|
// low byte of a value, store it and wait for the high byte.
|
||||||
if(!this->write_phase_) {
|
if(!this->write_phase_) {
|
||||||
@@ -648,6 +657,75 @@ void TMS9918<personality>::write(int address, uint8_t value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
void Base<personality>::write_palette(uint8_t value) {
|
||||||
|
LOG("Palette write TODO");
|
||||||
|
(void)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
void Base<personality>::write_register_indirect(uint8_t value) {
|
||||||
|
LOG("Register indirect write TODO");
|
||||||
|
(void)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
void TMS9918<personality>::write(int address, uint8_t value) {
|
||||||
|
switch(this->masked_address(address)) {
|
||||||
|
default: break;
|
||||||
|
case 0: this->write_vram(value); break;
|
||||||
|
case 1: this->write_register(value); break;
|
||||||
|
case 2: this->write_palette(value); break;
|
||||||
|
case 3: this->write_register_indirect(value); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
uint8_t Base<personality>::read_vram() {
|
||||||
|
// Take whatever is currently in the read-ahead buffer and
|
||||||
|
// enqueue a further read to occur at the next available slot.
|
||||||
|
const uint8_t result = this->read_ahead_buffer_;
|
||||||
|
this->queued_access_ = MemoryAccess::Read;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
uint8_t Base<personality>::read_register() {
|
||||||
|
// Gets the status register.
|
||||||
|
const uint8_t result = this->status_;
|
||||||
|
this->status_ &= ~(StatusInterrupt | StatusSpriteOverflow | StatusSpriteCollision);
|
||||||
|
this->line_interrupt_pending_ = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
uint8_t Base<personality>::read_palette() {
|
||||||
|
LOG("Palette read TODO");
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
uint8_t Base<personality>::read_register_indirect() {
|
||||||
|
LOG("Register indirect read TODO");
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Personality personality>
|
||||||
|
uint8_t TMS9918<personality>::read(int address) {
|
||||||
|
// TODO: is this still a global effect of reads, even in the world of the Yamahas?
|
||||||
|
this->write_phase_ = false;
|
||||||
|
|
||||||
|
switch(this->masked_address(address)) {
|
||||||
|
default: return 0xff;
|
||||||
|
case 0: return this->read_vram();
|
||||||
|
case 1: return this->read_register();
|
||||||
|
case 2: return this->read_palette();
|
||||||
|
case 3: return this->read_register_indirect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Ephemeral state.
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
uint8_t TMS9918<personality>::get_current_line() const {
|
uint8_t TMS9918<personality>::get_current_line() const {
|
||||||
// Determine the row to return.
|
// Determine the row to return.
|
||||||
@@ -682,26 +760,6 @@ uint8_t TMS9918<personality>::get_current_line() const {
|
|||||||
|
|
||||||
return uint8_t(source_row);
|
return uint8_t(source_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <Personality personality>
|
|
||||||
uint8_t TMS9918<personality>::read(int address) {
|
|
||||||
this->write_phase_ = false;
|
|
||||||
|
|
||||||
// Reads from address 0 read video RAM, via the read-ahead buffer.
|
|
||||||
if(!(address & 1)) {
|
|
||||||
// Enqueue the write to occur at the next available slot.
|
|
||||||
const uint8_t result = this->read_ahead_buffer_;
|
|
||||||
this->queued_access_ = MemoryAccess::Read;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads from address 1 get the status register.
|
|
||||||
const uint8_t result = this->status_;
|
|
||||||
this->status_ &= ~(StatusInterrupt | StatusSpriteOverflow | StatusSpriteCollision);
|
|
||||||
this->line_interrupt_pending_ = false;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <Personality personality>
|
template <Personality personality>
|
||||||
HalfCycles TMS9918<personality>::get_next_sequence_point() const {
|
HalfCycles TMS9918<personality>::get_next_sequence_point() const {
|
||||||
if(!this->generate_interrupts_ && !this->enable_line_interrupts_) return HalfCycles::max();
|
if(!this->generate_interrupts_ && !this->enable_line_interrupts_) return HalfCycles::max();
|
||||||
|
@@ -286,6 +286,16 @@ template <Personality personality> struct Base {
|
|||||||
size_t sprite_generator_table_address;
|
size_t sprite_generator_table_address;
|
||||||
} master_system_;
|
} master_system_;
|
||||||
|
|
||||||
|
int masked_address(int address);
|
||||||
|
void write_vram(uint8_t);
|
||||||
|
void write_register(uint8_t);
|
||||||
|
void write_palette(uint8_t);
|
||||||
|
void write_register_indirect(uint8_t);
|
||||||
|
uint8_t read_vram();
|
||||||
|
uint8_t read_register();
|
||||||
|
uint8_t read_palette();
|
||||||
|
uint8_t read_register_indirect();
|
||||||
|
|
||||||
ScreenMode current_screen_mode() const {
|
ScreenMode current_screen_mode() const {
|
||||||
if(blank_display_) {
|
if(blank_display_) {
|
||||||
return ScreenMode::Blank;
|
return ScreenMode::Blank;
|
||||||
|
Reference in New Issue
Block a user