1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-10-20 06:25:01 +00:00

Merge branch 'master' into SSLandCSL

This commit is contained in:
Thomas Harte 2024-07-05 14:54:47 -04:00
commit 0e58f7fa69
4 changed files with 59 additions and 21 deletions

View File

@ -254,12 +254,10 @@ class CGA {
}
void serialise_pixels(const Motorola::CRTC::BusState &state) {
// This is what I think is happenings:
// Refresh address is shifted left and two bytes are fetched, just as if the fetch were for
// character code + attributes, but producing two bytes worth of graphics.
//
// Refresh address is still shifted left one and two bytes are fetched, just as if it were
// character code + attributes except that these are two bytes worth of graphics.
//
// Meanwhile, row address is used to invent a 15th address line.
// Meanwhile, row address is used as a substitute 14th address line.
const auto base_address =
((state.refresh_address & 0xfff) << 1) +
((state.row_address & 1) << 13);

View File

@ -708,12 +708,23 @@ void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
continue;
case CycleFetchFromHalfUpdatedPC: {
uint16_t halfUpdatedPc = uint16_t(((pc_.halves.low + int8_t(operand_)) & 0xff) | (pc_.halves.high << 8));
throwaway_read(halfUpdatedPc);
uint16_t half_updated_pc = uint16_t(((pc_.halves.low + int8_t(operand_)) & 0xff) | (pc_.halves.high << 8));
throwaway_read(half_updated_pc);
} break;
case CycleFetchFromNextAddress:
throwaway_read(next_address_.full);
break;
case OperationAddSignedOperandToPC16:
next_address_ = pc_.full;
pc_.full = uint16_t(pc_.full + int8_t(operand_));
// Skip a step if 8-bit arithmetic would have been sufficient;
// in practise this operation is used only by BBS/BBR.
if(pc_.halves.high == next_address_.halves.high) {
++scheduled_program_counter_;
}
continue;
case OperationBBRBBS: {
@ -725,7 +736,7 @@ void Processor<personality, T, uses_ready_line>::run_for(const Cycles cycles) {
} else {
scheduled_program_counter_ = operations_[size_t(OperationsSlot::DoNotBBRBBS)];
}
} break;
} continue;
// MARK: - Transfers

View File

@ -269,18 +269,35 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
/* 0x105: Do BBR or BBS. */
Program(
CycleFetchOperand, // Fetch offset.
CycleFetchOperand, // Fetch offset, and increment PC.
OperationIncrementPC,
CycleFetchFromHalfUpdatedPC,
OperationAddSignedOperandToPC16
OperationAddSignedOperandToPC16, // Calculate target PC, leaving old PC in next_address_
// and possibly skipping the next instruction.
CycleFetchFromNextAddress,
CycleFetchFromNextAddress
),
// Six or seven cycles total are:
// (1) operation;
// (2) zero page address as operand;
// (3) zero page address;
// (4) duplicate of (3);
// (5) further operand;
// (6) read from next PC;
// (7) repeat read from next PC if 16-bit arithmetic was required.
/* 0x106: Complete BBR or BBS without branching. */
Program(
CycleFetchOperand,
OperationIncrementPC,
CycleFetchFromHalfUpdatedPC
CycleFetchOperand, // Fetch offset.
OperationIncrementPC
)
// Five cycles total are:
// (1) operation;
// (2) zero page address as operand;
// (3) zero page address;
// (4) duplicate of (3);
// (5) further operand, which goes unused.
};
static_assert(sizeof(operations_6502) == sizeof(operations_));
@ -408,15 +425,25 @@ ProcessorStorage::ProcessorStorage(Personality personality) {
// 0xc7, 0xcb, 0xcf, 0xd7, 0xdb, 0xdf,
// 0xe7, 0xef, 0xf7, 0xff
if(has_bbrbbsrmbsmb(personality)) {
// Add BBS and BBR. These take five cycles. My guessed breakdown is:
// Add BBS and BBR. These take five, six or seven cycles. First five:
// 1. read opcode
// 2. read operand
// 2. read first operand (i.e. zero-page address)
// 3. read zero page
// 4. read second operand
// 5. read from PC without top byte fixed yet
// ... with the caveat that (3) and (4) could be the other way around.
// 4. reread zero page (presumably as a stall, to make a decision on the above)
// 5. read second operand (i.e. branch offset)
//
// ... and then, if the branch is taken:
//
// 6. read from where next instruction would have been
// 7. reread, if a further stall is necessary to cover up for a 16-bit address change.
for(int location = 0x0f; location <= 0xff; location += 0x10) {
Install(location, Program(OperationLoadAddressZeroPage, CycleFetchOperandFromAddress, OperationBBRBBS));
Install(location, Program(
OperationLoadAddressZeroPage,
CycleFetchOperandFromAddress, // (cycle 3)
CycleFetchOperandFromAddress, // (cycle 4)
OperationBBRBBS // Branches to either OperationsSlot::DoBBRBBS, or to
// OperationSlot::DoNotBBRBBS, depending on data read.
));
}
// Add RMB and SMB.

View File

@ -186,7 +186,9 @@ class ProcessorStorage {
CycleFetchFromHalfUpdatedPC, // performs a throwaway read from (PC + (signed)operand).l combined with PC.h
CycleAddSignedOperandToPC, // sets next_address to PC + (signed)operand. If the high byte of next_address differs from the PC, schedules a throwaway read from the half-updated PC. 65C02 specific: if the top two bytes are the same, proceeds directly to fetch-decode-execute, ignoring any pending interrupts.
OperationAddSignedOperandToPC16, // adds (signed)operand into the PC
OperationAddSignedOperandToPC16, // adds (signed)operand into the PC, leaving old PC in next_address_ and skipping a program step if there was no carry from low to high byte
CycleFetchFromNextAddress, // performs a throwaway fetch from next_address_
OperationSetFlagsFromOperand, // sets all flags based on operand_
OperationSetOperandFromFlagsWithBRKSet, // sets operand_ to the value of all flags, with the break flag set