fix slow floppy

Read data even if floppy motor is off?!?!

invert sense of CXROM

make some arrays const

improve debugger slightly
    fix disassembly
    add breakpoints
    add "step"
This commit is contained in:
Brad Grantham 2020-12-26 23:03:13 -08:00
parent 734900c314
commit 1271db3d95
1 changed files with 141 additions and 66 deletions

View File

@ -204,14 +204,15 @@ struct SoftSwitch
int set_address;
int read_address;
bool read_also_changes;
bool enabled = false;
bool enabled;
bool implemented;
SoftSwitch(const char* name_, int clear, int on, int read, bool read_changes, vector<SoftSwitch*>& s, bool implemented_ = false) :
SoftSwitch(const char* name_, int clear, int on, int read, bool read_changes, vector<SoftSwitch*>& s, bool initialValue, bool implemented_ = false) :
name(name_),
clear_address(clear),
set_address(on),
read_address(read),
read_also_changes(read_changes),
enabled(initialValue),
implemented(implemented_)
{
s.push_back(this);
@ -304,7 +305,7 @@ and a ".dsk" floppy image is only 143360 bytes.
*/
constexpr int sectorSize = 256;
constexpr int sectorsPerTrack = 16;
constexpr int tracksPerFloppy = 35;
// constexpr int tracksPerFloppy = 35;
const uint8_t sectorHeader[21] =
{
@ -349,7 +350,7 @@ constexpr size_t nybblizedTrackSize = trackGapSize + sectorsPerTrack * nybblized
void nybblizeSector(int trackIndex, int sectorIndex, const uint8_t *sectorBytes, uint8_t *sectorNybblized)
{
memset(sectorNybblized, 0xFF, nybblizedSectorSize); // Doesn't matter if 00s or FFs...
// memset(sectorNybblized, 0xFF, nybblizedSectorSize); // Doesn't matter if 00s or FFs...
uint8_t *p = sectorNybblized;
@ -381,7 +382,7 @@ void nybblizeSector(int trackIndex, int sectorIndex, const uint8_t *sectorBytes,
memcpy(p + 0x56, sectorBytes, 256);
// XOR the data block with itself, offset by one byte,
// creating a 343rd byte which is used as a cheksum.
// creating a 343rd byte which is used as a checksum.
p[342] = 0x00;
@ -397,7 +398,6 @@ void nybblizeSector(int trackIndex, int sectorIndex, const uint8_t *sectorBytes,
// Done with the nybblization, now for the epilogue...
memcpy(p, sectorFooter, sizeof(sectorFooter));
// p += 48;
}
bool nybblizeTrackFromFile(FILE *floppyImageFile, int trackIndex, uint8_t *nybblizedTrack, const int *skew)
@ -421,7 +421,9 @@ bool nybblizeTrackFromFile(FILE *floppyImageFile, int trackIndex, uint8_t *nybbl
return false;
}
nybblizeSector(trackIndex, sectorIndex, sectorBytes, nybblizedTrack + trackGapSize + sectorIndex * nybblizedSectorSize);
uint8_t *sectorDest = nybblizedTrack + trackGapSize + sectorIndex * nybblizedSectorSize;
nybblizeSector(trackIndex, sectorIndex, sectorBytes, sectorDest);
}
return true;
}
@ -536,8 +538,11 @@ struct DISKIIboard : board_base
uint8_t readNextTrackByte()
{
if(headMode != READ || !driveMotorEnabled[driveSelected] || !floppyPresent[driveSelected])
// bool dataValid = (headMode != READ || !driveMotorEnabled[driveSelected] || !floppyPresent[driveSelected]);
bool dataValid = floppyPresent[driveSelected];
if(!dataValid) {
return 0x00;
}
if(trackBytesOutOfDate) {
readDriveTrack();
@ -546,6 +551,10 @@ struct DISKIIboard : board_base
uint8_t data = trackBytes[trackByteIndex];
if(false) {
printf("read track %d byte %d (sector %ld byte %ld), yields %d (%02X)\n", nybblizedTrackIndex / 2, trackByteIndex, trackByteIndex / floppy::nybblizedSectorSize, trackByteIndex % floppy::nybblizedSectorSize, data, data);
}
trackByteIndex = (trackByteIndex + 1) % floppy::nybblizedTrackSize;
return data;
@ -569,6 +578,7 @@ struct DISKIIboard : board_base
nybblizedTrackIndex = currentTrackNumber[driveSelected];
nybblizedDriveIndex = driveSelected;
trackByteIndex = 0;
return true;
}
@ -663,11 +673,13 @@ struct DISKIIboard : board_base
if(debug & DEBUG_FLOPPY) printf("floppy select first drive\n");
driveSelected = 0;
trackBytesOutOfDate = true;
data = 0;
return true;
} else if(addr == SELECT + 1) {
if(debug & DEBUG_FLOPPY) printf("floppy select second drive\n");
driveSelected = 1;
trackBytesOutOfDate = true;
data = 0;
return true;
} else if(addr == ENABLE) {
if(debug & DEBUG_FLOPPY) printf("floppy switch off\n");
@ -675,6 +687,7 @@ struct DISKIIboard : board_base
floppy_activity(driveSelected, false);
// go disable reading
// disable other drive?
data = 0;
return true;
} else if(addr == ENABLE + 1) {
if(debug & DEBUG_FLOPPY) printf("floppy switch on\n");
@ -682,6 +695,7 @@ struct DISKIIboard : board_base
floppy_activity(driveSelected, true);
// go enable reading
// disable other drive?
data = 0;
return true;
}
if(debug & DEBUG_WARN) printf("DISK II unhandled read from %04X (%s)\n", addr, io.at(addr).c_str());
@ -690,8 +704,8 @@ struct DISKIIboard : board_base
}
virtual void reset(void)
{
driveMotorEnabled[0] = false; // Is this safe?
driveMotorEnabled[1] = false; // Is this safe?
driveMotorEnabled[0] = false; // Is this what the drive HW does?
driveMotorEnabled[1] = false; // Is this what the drive HW does?
driveSelected = 0;
trackBytesOutOfDate = true;
floppy_activity(0, false);
@ -740,7 +754,7 @@ void initialize_audio_waveform()
}
int hires_blanking_address_base[262];
extern int hires_visible_address_base[262];
extern const int hires_visible_address_base[262];
static void generate_hires_scanout_addresses() __attribute__((constructor));
void generate_hires_scanout_addresses()
@ -762,7 +776,7 @@ int get_hires_scanout_address(int byte_in_frame)
return 0x2000 + (hires_visible_address_base[line_in_frame] + byte_in_line - 25) % 0x2000;
}
static int text_blanking_address_base[] =
const static int text_blanking_address_base[] =
{
0x1468,
0x14E8,
@ -799,7 +813,7 @@ static int text_blanking_address_base[] =
0x17E0, // last text line is actually scanned 14 times so add another row
};
static int text_visible_address_base[] =
const static int text_visible_address_base[] =
{
0x0400,
0x0480,
@ -855,20 +869,19 @@ struct MAINboard : board_base
vector<SoftSwitch*> switches;
SoftSwitch* switches_by_address[256];
// SoftSwitch(const char* name_, int clear, int on, int read, bool read_changes, vector<SoftSwitch*>& s, bool implemented_ = false) :
// Inside the Apple //e, page 379
SoftSwitch CXROM {"CXROM", 0xC006, 0xC007, 0xC015, false, switches, true};
SoftSwitch STORE80 {"STORE80", 0xC000, 0xC001, 0xC018, false, switches, true};
SoftSwitch RAMRD {"RAMRD", 0xC002, 0xC003, 0xC013, false, switches, true};
SoftSwitch RAMWRT {"RAMWRT", 0xC004, 0xC005, 0xC014, false, switches, true};
SoftSwitch ALTZP {"ALTZP", 0xC008, 0xC009, 0xC016, false, switches, true};
SoftSwitch C3ROM {"C3ROM", 0xC00A, 0xC00B, 0xC017, false, switches, true};
SoftSwitch ALTCHAR {"ALTCHAR", 0xC00E, 0xC00F, 0xC01E, false, switches, true};
SoftSwitch VID80 {"VID80", 0xC00C, 0xC00D, 0xC01F, false, switches, true};
SoftSwitch TEXT {"TEXT", 0xC050, 0xC051, 0xC01A, true, switches, true};
SoftSwitch MIXED {"MIXED", 0xC052, 0xC053, 0xC01B, true, switches, true};
SoftSwitch PAGE2 {"PAGE2", 0xC054, 0xC055, 0xC01C, true, switches, true};
SoftSwitch HIRES {"HIRES", 0xC056, 0xC057, 0xC01D, true, switches, true};
SoftSwitch SLOTCXROM {"SLOTCXROM", 0xC007, 0xC006, 0xC015, false, switches, false, true};
SoftSwitch STORE80 {"STORE80", 0xC000, 0xC001, 0xC018, false, switches, false, true};
SoftSwitch RAMRD {"RAMRD", 0xC002, 0xC003, 0xC013, false, switches, false, true};
SoftSwitch RAMWRT {"RAMWRT", 0xC004, 0xC005, 0xC014, false, switches, false, true};
SoftSwitch ALTZP {"ALTZP", 0xC008, 0xC009, 0xC016, false, switches, false, true};
SoftSwitch C3ROM {"C3ROM", 0xC00A, 0xC00B, 0xC017, false, switches, false, true};
SoftSwitch ALTCHAR {"ALTCHAR", 0xC00E, 0xC00F, 0xC01E, false, switches, false, true};
SoftSwitch VID80 {"VID80", 0xC00C, 0xC00D, 0xC01F, false, switches, false, true};
SoftSwitch TEXT {"TEXT", 0xC050, 0xC051, 0xC01A, true, switches, false, true};
SoftSwitch MIXED {"MIXED", 0xC052, 0xC053, 0xC01B, true, switches, false, true};
SoftSwitch PAGE2 {"PAGE2", 0xC054, 0xC055, 0xC01C, true, switches, false, true};
SoftSwitch HIRES {"HIRES", 0xC056, 0xC057, 0xC01D, true, switches, false, true};
vector<backed_region*> regions;
std::array<backed_region*,256> read_regions_by_page;
@ -910,10 +923,10 @@ struct MAINboard : board_base
enabled_func always_disabled = []{return false;};
bool internal_C800_ROM_selected = false;
backed_region rom_C100 = {"rom_C100", 0xC100, 0x0200, ROM, &regions, [&]{return CXROM;}, always_disabled};
backed_region rom_C300 = {"rom_C300", 0xC300, 0x0100, ROM, &regions, [&]{return CXROM || (!CXROM && !C3ROM);}, always_disabled};
backed_region rom_C400 = {"rom_C400", 0xC400, 0x0400, ROM, &regions, [&]{return CXROM;}, always_disabled};
backed_region rom_C800 = {"rom_C800", 0xC800, 0x0800, ROM, &regions, [&]{return CXROM || (!CXROM && !C3ROM && internal_C800_ROM_selected);}, always_disabled};
backed_region rom_C100 = {"rom_C100", 0xC100, 0x0200, ROM, &regions, [&]{return !SLOTCXROM;}, always_disabled};
backed_region rom_C300 = {"rom_C300", 0xC300, 0x0100, ROM, &regions, [&]{return !SLOTCXROM || (SLOTCXROM && !C3ROM);}, always_disabled};
backed_region rom_C400 = {"rom_C400", 0xC400, 0x0400, ROM, &regions, [&]{return !SLOTCXROM;}, always_disabled};
backed_region rom_C800 = {"rom_C800", 0xC800, 0x0800, ROM, &regions, [&]{return !SLOTCXROM || (SLOTCXROM && !C3ROM && internal_C800_ROM_selected);}, always_disabled};
backed_region rom_CXXX_default = {"rom_CXXX_default", 0xC100, 0x0F00, ROM, &regions, [&]{return true;}, always_disabled};
enabled_func read_from_aux_ram = [&]{return RAMRD;};
@ -962,18 +975,46 @@ struct MAINboard : board_base
backed_region hires_page2 = {"hires_page2", 0x4000, 0x2000, RAM, &regions, read_from_main_ram, write_to_main_ram};
backed_region hires_page2x = {"hires_page2x", 0x4000, 0x2000, RAM, &regions, read_from_aux_ram, write_to_aux_ram};
set<int> ignore_mmio = {0xC058, 0xC05A, 0xC05D, 0xC05F, 0xC061, 0xC062};
set<int> ignore_mmio = {
0xC058, // CLRAN0 through Apple //e
0xC05A, // CLRAN1 through Apple //e
0xC05D, // SETAN2 through Apple //e
0xC05F, // SETAN3 through Apple //e
0xC060, // TAPEIN through Apple //e
0xC061, // RDBTN0 Open Apple on and after Apple //e
0xC062, // BUTN1 Solid Apple on and after Apple //e
};
set<int> banking_read_switches = {
0xC080, 0xC081, 0xC082, 0xC083, 0xC084, 0xC085, 0xC086, 0xC087,
0xC088, 0xC089, 0xC08A, 0xC08B, 0xC08C, 0xC08D, 0xC08E, 0xC08F,
0xC080,
0xC081,
0xC082,
0xC083,
0xC084,
0xC085,
0xC086,
0xC087,
0xC088,
0xC089,
0xC08A,
0xC08B,
0xC08C,
0xC08D,
0xC08E,
0xC08F,
};
set<int> banking_write_switches = {
0xC006, 0xC007,
0xC000, 0xC001,
0xC002, 0xC003,
0xC004, 0xC005,
0xC008, 0xC009,
0xC00A, 0xC00B,
0xC006,
0xC007,
0xC000,
0xC001,
0xC002,
0xC003,
0xC004,
0xC005,
0xC008,
0xC009,
0xC00A,
0xC00B,
};
deque<uint8_t> keyboard_buffer;
@ -1100,7 +1141,7 @@ struct MAINboard : board_base
// Partially from Apple //e Technical Reference
// XXX need to double-check these against the actual hardware
ALTZP.enabled = false;
CXROM.enabled = false;
SLOTCXROM.enabled = false;
RAMRD.enabled = false;
RAMWRT.enabled = false;
C3ROM.enabled = false;
@ -1191,14 +1232,14 @@ struct MAINboard : board_base
data = sw->enabled ? 0x80 : 0x00;
if(debug & DEBUG_SWITCH) printf("Read status of %s = %02X\n", sw->name.c_str(), data);
return true;
} else if(sw->read_also_changes && addr == sw->set_address) {
} else if(sw->read_also_changes && (addr == sw->set_address)) {
if(!sw->implemented) { printf("%s ; set is unimplemented\n", sw->name.c_str()); fflush(stdout); exit(0); }
data = result;
sw->enabled = true;
if(debug & DEBUG_SWITCH) printf("Set %s\n", sw->name.c_str());
post_soft_switch_mode_change();
return true;
} else if(sw->read_also_changes && addr == sw->clear_address) {
} else if(sw->read_also_changes && (addr == sw->clear_address)) {
if(!sw->implemented) { printf("%s ; unimplemented\n", sw->name.c_str()); fflush(stdout); exit(0); }
data = result;
sw->enabled = false;
@ -1588,7 +1629,7 @@ string read_bus_and_disassemble(bus_frontend &bus, int pc)
buf[1] = bus.read(pc + 1);
buf[2] = bus.read(pc + 2);
buf[3] = bus.read(pc + 3);
tie(bytes, dis) = disassemble_6502(pc - 1, buf);
tie(bytes, dis) = disassemble_6502(pc, buf);
return dis;
}
@ -1975,6 +2016,8 @@ int main(int argc, char **argv)
clk_t cpu_previous_cycles = 0;
averaged_sequence<float, 20> cpu_speed_averaged;
std::set<uint16_t> breakpoints;
while(1) {
if(!debugging) {
@ -2049,6 +2092,7 @@ int main(int argc, char **argv)
} else {
int steps = 1;
printf("> ");
char line[512];
if(fgets(line, sizeof(line) - 1, stdin) == NULL) {
@ -2059,6 +2103,20 @@ int main(int argc, char **argv)
printf("continuing\n");
debugging = false;
continue;
} else if(strncmp(line, "step", 4) == 0) {
if(line[5] != '\0') {
steps = atoi(line + 5);
printf("run for %d steps\n", steps);
}
} else if(strncmp(line, "break", 5) == 0) {
if(line[6] != '\0') {
uint16_t addr = strtoul(line + 5, NULL, 0);
printf("breakpoint at 0x%04X\n", addr);
breakpoints.insert(addr);
} else {
printf("expected breakpoint address\n");
}
continue;
} else if(strcmp(line, "fast") == 0) {
printf("run flat out\n");
run_fast = true;
@ -2086,31 +2144,48 @@ int main(int argc, char **argv)
cpu.nmi();
continue;
}
if(debug & DEBUG_DECODE) {
string dis = read_bus_and_disassemble(bus,
for(int i = 0; i < steps; i++) {
if(debug & DEBUG_DECODE) {
string dis = read_bus_and_disassemble(bus,
#ifdef SUPPORT_FAKE_6502
use_fake6502 ? pc :
use_fake6502 ? pc :
#endif
cpu.pc);
printf("%s\n", dis.c_str());
}
#ifdef SUPPORT_FAKE_6502
if(use_fake6502) {
clockticks6502 = 0;
step6502();
clk.add_cpu_cycles(clockticks6502);
} else
#endif
{
cpu.cycle();
if(debug & DEBUG_STATE)
print_cpu_state(cpu);
}
mainboard->sync();
cpu.pc);
printf("%s\n", dis.c_str());
}
#ifdef SUPPORT_FAKE_6502
if(use_fake6502) {
clockticks6502 = 0;
step6502();
clk.add_cpu_cycles(clockticks6502);
} else
#endif
{
cpu.cycle();
if(debug & DEBUG_STATE)
print_cpu_state(cpu);
}
if((i % 10000) == 0) {
mainboard->sync();
}
if((i % 100000) == 0) {
APPLE2Einterface::iterate(mode_history, clk.clock_cpu, 1.023);
mode_history.clear();
}
uint16_t pcnow =
#ifdef SUPPORT_FAKE_6502
use_fake6502 ? pc :
#endif
cpu.pc;
printf("%04X, %zd\n", pcnow, breakpoints.count(pcnow));
if(breakpoints.count(pcnow) > 0) {
printf("break at 0x%4X\n", pcnow);
break;
}
}
APPLE2Einterface::iterate(mode_history, clk.clock_cpu, 1.023);
mode_history.clear();
}
}
@ -2118,7 +2193,7 @@ int main(int argc, char **argv)
return 0;
}
int hires_visible_address_base[262] =
const int hires_visible_address_base[262] =
{
0x0000, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00,
0x0080, 0x0480, 0x0880, 0x0C80, 0x1080, 0x1480, 0x1880, 0x1C80,