diff --git a/Makefile b/Makefile index 0d5776e..d15f9d6 100644 --- a/Makefile +++ b/Makefile @@ -13,5 +13,7 @@ all: apple2e apple2e: $(OBJECTS) $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS) +apple2e.o: cpu6502.h + clean: rm $(OBJECTS) diff --git a/apple2e.cpp b/apple2e.cpp index 827de6c..a6d51c4 100644 --- a/apple2e.cpp +++ b/apple2e.cpp @@ -14,11 +14,53 @@ #include #include #include +#include #ifndef M_PI #define M_PI 3.14159 #endif +typedef uint64_t clk_t; +struct system_clock +{ + clk_t clock_cpu = 0; // Actual CPU and memory clocks, variable rate + clk_t clock_14mhz = 0; // Fixed 14.31818MHz clock + clk_t phase_hpe = 0; // Phase of CPU clock within horizontal lines + operator clk_t() const { return clock_14mhz; } + void add_cpu_cycles(clk_t elapsed_cpu) + { + clock_cpu += elapsed_cpu; + clock_14mhz += elapsed_cpu * 14 + (elapsed_cpu + phase_hpe) / 65 * 2; + phase_hpe = (phase_hpe + elapsed_cpu) % 65; + if(0) printf("added %llu, new cpu clock %llu, 14mhz clock %llu, phase %llu\n", elapsed_cpu, clock_cpu, clock_14mhz, phase_hpe); + } +} clk; + + +#define printf PrintToLine3 + +clk_t clockRangeStart = 2427489692 - 100000; +clk_t clockRangeEnd = 2427489692 + 1000; + +void PrintToLine3(const char *fmt, ...) +{ + if(clk < clockRangeStart) { + return; + } + if(clk > clockRangeEnd) { + abort(); + } + static char buffer[36]; + va_list args; + + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + + write(0, buffer, strlen(buffer)); +} + + // Brad's 6502 #include "cpu6502.h" @@ -37,15 +79,16 @@ using namespace std; #define LK_HACK 0 -constexpr unsigned int DEBUG_ERROR = 0x01; -constexpr unsigned int DEBUG_WARN = 0x02; -constexpr unsigned int DEBUG_DECODE = 0x04; -constexpr unsigned int DEBUG_STATE = 0x08; -constexpr unsigned int DEBUG_RW = 0x10; -constexpr unsigned int DEBUG_BUS = 0x20; -constexpr unsigned int DEBUG_FLOPPY = 0x40; -constexpr unsigned int DEBUG_SWITCH = 0x80; -volatile unsigned int debug = DEBUG_ERROR | DEBUG_WARN; // | DEBUG_DECODE | DEBUG_STATE | DEBUG_RW; +constexpr uint32_t DEBUG_ERROR = 0x01; +constexpr uint32_t DEBUG_WARN = 0x02; +constexpr uint32_t DEBUG_DECODE = 0x04; +constexpr uint32_t DEBUG_STATE = 0x08; +constexpr uint32_t DEBUG_RW = 0x10; +constexpr uint32_t DEBUG_BUS = 0x20; +constexpr uint32_t DEBUG_FLOPPY = 0x40; +constexpr uint32_t DEBUG_SWITCH = 0x80; +constexpr uint32_t DEBUG_CLOCK = 0x100; +volatile unsigned int debug = DEBUG_ERROR | DEBUG_WARN; // DEBUG_DECODE | DEBUG_RW | DEBUG_STATE | DEBUG_CLOCK; // | DEBUG_DECODE | DEBUG_STATE | DEBUG_RW; bool delete_is_left_arrow = true; volatile bool exit_on_banking = false; @@ -64,26 +107,10 @@ const float paddle_max_pulse_seconds = .00282; // Map from memory address to name of function (from the ld65 map file). static map address_to_function_name; -typedef unsigned long long clk_t; -struct system_clock -{ - clk_t clock_cpu = 0; // Actual CPU and memory clocks, variable rate - clk_t clock_14mhz = 0; // Fixed 14.31818MHz clock - clk_t phase_hpe = 0; // Phase of CPU clock within horizontal lines - operator clk_t() const { return clock_14mhz; } - void add_cpu_cycles(clk_t elapsed_cpu) - { - clock_cpu += elapsed_cpu; - clock_14mhz += elapsed_cpu * 14 + (elapsed_cpu + phase_hpe) / 65 * 2; - phase_hpe = (phase_hpe + elapsed_cpu) % 65; - if(0) printf("added %llu, new cpu clock %llu, 14mhz clock %llu, phase %llu\n", elapsed_cpu, clock_cpu, clock_14mhz, phase_hpe); - } -} clk; - const int machine_clock_rate = 14318180; -bool read_blob(const char *name, unsigned char *b, size_t sz) +bool read_blob(const char *name, uint8_t *b, size_t sz) { FILE *fp = fopen(name, "rb"); if(fp == NULL) { @@ -211,7 +238,7 @@ enum MemoryType {RAM, ROM}; struct backed_region : region { - vector memory; + vector memory; MemoryType type; enabled_func read_enabled; enabled_func write_enabled; @@ -245,7 +272,7 @@ struct backed_region : region return (addr >= base) && (addr < base + size); } - bool read(int addr, unsigned char& data) + bool read(int addr, uint8_t& data) { if(contains(addr) && read_enabled()) { data = memory[addr - base]; @@ -254,7 +281,7 @@ struct backed_region : region return false; } - bool write(int addr, unsigned char data) + bool write(int addr, uint8_t data) { if((type == RAM) && contains(addr) && write_enabled()) { memory[addr - base] = data; @@ -278,7 +305,7 @@ constexpr int sectorSize = 256; constexpr int sectorsPerTrack = 16; constexpr int tracksPerFloppy = 35; -const unsigned char sectorHeader[21] = +const uint8_t sectorHeader[21] = { 0xD5, 0xAA, 0x96, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAA, 0xFF, 0xFF, 0xFF, @@ -294,7 +321,7 @@ const int sectorSkewProDOS[16] = 0x0, 0x8, 0x1, 0x9, 0x2, 0xA, 0x3, 0xB, 0x4, 0xC, 0x5, 0xD, 0x6, 0xE, 0x7, 0xF }; -const unsigned char sectorFooter[48] = +const uint8_t sectorFooter[48] = { 0xDE, 0xAA, 0xEB, 0xFF, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -303,7 +330,7 @@ const unsigned char sectorFooter[48] = 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -const unsigned char SixBitsToBytes[0x40] = +const uint8_t SixBitsToBytes[0x40] = { 0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, @@ -372,20 +399,20 @@ void nybblizeSector(int trackIndex, int sectorIndex, const uint8_t *sectorBytes, // p += 48; } -bool nybblizeTrackFromFile(FILE *floppyImageFile, int trackIndex, unsigned char *nybblizedTrack, const int *skew) +bool nybblizeTrackFromFile(FILE *floppyImageFile, int trackIndex, uint8_t *nybblizedTrack, const int *skew) { memset(nybblizedTrack, 0xFF, trackGapSize); // Write gap 1, 64 bytes (self-sync) - for(unsigned char sectorIndex = 0; sectorIndex < 16; sectorIndex++) + for(int sectorIndex = 0; sectorIndex < 16; sectorIndex++) { - long sectorOffset = (skew[sectorIndex] + trackIndex * sectorsPerTrack) * sectorSize; + uint32_t sectorOffset = (skew[sectorIndex] + trackIndex * sectorsPerTrack) * sectorSize; int seeked = fseek(floppyImageFile, sectorOffset, SEEK_SET); if(seeked == -1) { fprintf(stderr, "failed to seek to sector in floppy disk image\n"); return false; } - unsigned char sectorBytes[256]; + uint8_t sectorBytes[256]; size_t wasRead = fread(sectorBytes, 1, sectorSize, floppyImageFile); if(wasRead != sectorSize) { fprintf(stderr, "failed to read sector from floppy disk image\n"); @@ -414,7 +441,7 @@ struct DISKIIboard : board_base static constexpr int Q7L = 0xC0EE; // IO strobe for clear static constexpr int Q7H = 0xC0EF; // IO strobe for shift - const map io = { + const map io = { {0xC0E0, "CA0OFF"}, {0xC0E1, "CA0ON"}, {0xC0E2, "CA1OFF"}, @@ -444,7 +471,7 @@ struct DISKIIboard : board_base int driveSelected = 0; bool driveMotorEnabled[2]; enum {READ, WRITE} headMode = READ; - unsigned char dataLatch = 0x00; + uint8_t dataLatch = 0x00; int headStepperPhase[2][4] = { {0, 0, 0, 0}, {0, 0, 0, 0} }; int headStepperMostRecentPhase[2] = {0, 0}; int currentTrackNumber[2] = {0, 0}; // physical track number - DOS and ProDOS only use even tracks @@ -454,7 +481,7 @@ struct DISKIIboard : board_base bool trackBytesOutOfDate = true; int nybblizedTrackIndex = -1; int nybblizedDriveIndex = -1; - unsigned int trackByteIndex = 0; + uint32_t trackByteIndex = 0; void set_floppy(int number, const char *name) // number 0 or 1; name = NULL to eject { @@ -494,7 +521,7 @@ struct DISKIIboard : board_base typedef std::function floppy_activity_func; floppy_activity_func floppy_activity; - DISKIIboard(const unsigned char diskII_rom[256], const char *floppy0_name, const char *floppy1_name, floppy_activity_func floppy_activity_) : + DISKIIboard(const uint8_t diskII_rom[256], const char *floppy0_name, const char *floppy1_name, floppy_activity_func floppy_activity_) : floppy_activity(floppy_activity_) { std::copy(diskII_rom, diskII_rom + 0x100, rom_C600.memory.begin()); @@ -506,7 +533,7 @@ struct DISKIIboard : board_base } } - unsigned char readNextTrackByte() + uint8_t readNextTrackByte() { if(headMode != READ || !driveMotorEnabled[driveSelected] || !floppyPresent[driveSelected]) return 0x00; @@ -545,7 +572,7 @@ struct DISKIIboard : board_base return true; } - void controlTrackMotor(unsigned int addr) + void controlTrackMotor(uint32_t addr) { int phase = (addr & 0x7) >> 1; int state = addr & 0x1; @@ -588,7 +615,7 @@ struct DISKIIboard : board_base } } - virtual bool write(int addr, unsigned char data) + virtual bool write(int addr, uint8_t data) { if(addr < 0xC0E0 || addr > 0xC0EF) return false; @@ -596,7 +623,7 @@ struct DISKIIboard : board_base return false; } - virtual bool read(int addr, unsigned char &data) + virtual bool read(int addr, uint8_t &data) { if(rom_C600.read(addr, data)) { if(debug & DEBUG_RW) printf("DiskII read 0x%04X -> %02X\n", addr, data); @@ -677,7 +704,7 @@ struct Mockingboard : board_base { } - virtual bool write(int addr, unsigned char data) + virtual bool write(int addr, uint8_t data) { if((addr >= 0xC400) && (addr <= 0xC4FF)) { if(debug & DEBUG_RW) printf("Mockingboard write 0x%02X to 0x%04X ignored\n", data, addr); @@ -685,7 +712,7 @@ struct Mockingboard : board_base } return false; } - virtual bool read(int addr, unsigned char &data) + virtual bool read(int addr, uint8_t &data) { if((addr >= 0xC400) && (addr <= 0xC4FF)) { if(debug & DEBUG_RW) printf("Mockingboard read at 0x%04X ignored\n", addr); @@ -699,7 +726,7 @@ struct Mockingboard : board_base const int waveform_length = 44100 / 1000 / 2; // half of a wave at 4000 Hz const float waveform_max_amplitude = .35f; -static unsigned char waveform[waveform_length]; +static uint8_t waveform[waveform_length]; static void initialize_audio_waveform() __attribute__((constructor)); void initialize_audio_waveform() @@ -948,19 +975,19 @@ struct MAINboard : board_base 0xC00A, 0xC00B, }; - deque keyboard_buffer; + deque keyboard_buffer; static const int sample_rate = 44100; static const size_t audio_buffer_size = sample_rate / 100; - char audio_buffer[audio_buffer_size]; - long long audio_buffer_start_sample = 0; - long long audio_buffer_next_sample = 0; - unsigned char speaker_level; + uint8_t audio_buffer[audio_buffer_size]; + uint64_t audio_buffer_start_sample = 0; + uint64_t audio_buffer_next_sample = 0; + uint8_t speaker_level; bool speaker_transitioning_to_high = false; int where_in_waveform = 0; #if LK_HACK - unsigned char *disassemble_buffer = 0; + uint8_t *disassemble_buffer = 0; int disassemble_state = 0; int disassemble_index = 0; int disassemble_size = 0; @@ -969,11 +996,11 @@ struct MAINboard : board_base void fill_flush_audio() { - long long current_sample = clk * sample_rate / machine_clock_rate; + uint64_t current_sample = clk * sample_rate / machine_clock_rate; - for(long long i = audio_buffer_next_sample; i < current_sample; i++) { + for(uint64_t i = audio_buffer_next_sample; i < current_sample; i++) { if(where_in_waveform < waveform_length) { - unsigned char level = waveform[where_in_waveform++]; + uint8_t level = waveform[where_in_waveform++]; speaker_level = speaker_transitioning_to_high ? level : (255 - level); } @@ -1000,7 +1027,7 @@ struct MAINboard : board_base fill_flush_audio(); } - void enqueue_key(unsigned char k) + void enqueue_key(uint8_t k) { keyboard_buffer.push_back(k); } @@ -1028,14 +1055,14 @@ struct MAINboard : board_base } } - typedef std::function display_write_func; + typedef std::function display_write_func; display_write_func display_write; - typedef std::function audio_flush_func; + typedef std::function audio_flush_func; audio_flush_func audio_flush; typedef std::function (int num)> get_paddle_func; get_paddle_func get_paddle; clk_t paddles_clock_out[4]; - MAINboard(system_clock& clk_, const unsigned char rom_image[32768], display_write_func display_write_, audio_flush_func audio_flush_, get_paddle_func get_paddle_) : + MAINboard(system_clock& clk_, const uint8_t rom_image[32768], display_write_func display_write_, audio_flush_func audio_flush_, get_paddle_func get_paddle_) : clk(clk_), internal_C800_ROM_selected(true), speaker_level(waveform[0]), @@ -1087,7 +1114,7 @@ struct MAINboard : board_base } } - bool read(int addr, unsigned char &data) + bool read(int addr, uint8_t &data) { if(debug & DEBUG_RW) printf("MAIN board read\n"); for(auto b : boards) { @@ -1109,7 +1136,7 @@ struct MAINboard : board_base SoftSwitch* sw = switches_by_address[addr - 0xC000]; if(sw != nullptr) { - unsigned char result = 0xFF; + uint8_t result = 0xFF; // Special case for floating bus for reading video scanout // XXX doesn't handle 80-column nor AUX @@ -1283,7 +1310,7 @@ struct MAINboard : board_base } return false; } - bool write(int addr, unsigned char data) + bool write(int addr, uint8_t data) { #if LK_HACK if(addr == 0xBFFE) { @@ -1306,7 +1333,7 @@ struct MAINboard : board_base case 1: // MSB of size. disassemble_size |= data << 8; - disassemble_buffer = new unsigned char[disassemble_size]; + disassemble_buffer = new uint8_t[disassemble_size]; disassemble_index = 0; printf("Size of buffer: %d bytes\n", disassemble_size); @@ -1462,30 +1489,38 @@ struct MAINboard : board_base struct bus_frontend { MAINboard* board; - map > writes; - map > reads; + map > writes; + map > reads; - unsigned char read(int addr) + uint8_t read(uint16_t addr) { - unsigned char data = 0xaa; + uint8_t data = 0xaa; if(board->read(addr & 0xFFFF, data)) { - if(debug & DEBUG_BUS) printf("read %04X returned %02X\n", addr & 0xFFFF, data); + if(debug & DEBUG_BUS) + { + printf("read %04X returned %02X\n", addr & 0xFFFF, data); + } // reads[addr & 0xFFFF].push_back(data); return data; } - if(debug & DEBUG_ERROR) + if(debug & DEBUG_ERROR) { fprintf(stderr, "no ownership of read at %04X\n", addr & 0xFFFF); + } return 0xAA; } - void write(int addr, unsigned char data) + void write(uint16_t addr, uint8_t data) { if(board->write(addr & 0xFFFF, data)) { - if(debug & DEBUG_BUS) printf("write %04X %02X\n", addr & 0xFFFF, data); + if(debug & DEBUG_BUS) + { + printf("write %04X %02X\n", addr & 0xFFFF, data); + } // writes[addr & 0xFFFF].push_back(data); return; } - if(debug & DEBUG_ERROR) + if(debug & DEBUG_ERROR) { fprintf(stderr, "no ownership of write %02X at %04X\n", data, addr & 0xFFFF); + } } void reset() @@ -1547,7 +1582,7 @@ string read_bus_and_disassemble(bus_frontend &bus, int pc) { int bytes; string dis; - unsigned char buf[4]; + uint8_t buf[4]; buf[0] = bus.read(pc + 0); buf[1] = bus.read(pc + 1); buf[2] = bus.read(pc + 2); @@ -1560,10 +1595,10 @@ int millis_per_slice = 16; struct key_to_ascii { - unsigned char no_shift_no_control; - unsigned char yes_shift_no_control; - unsigned char no_shift_yes_control; - unsigned char yes_shift_yes_control; + uint8_t no_shift_no_control; + uint8_t yes_shift_no_control; + uint8_t no_shift_yes_control; + uint8_t yes_shift_yes_control; }; map interface_key_to_apple2e = @@ -1635,7 +1670,7 @@ enum APPLE2Einterface::EventType process_events(MAINboard *board, bus_frontend& diskIIboard->set_floppy(e.value, e.str); free(e.str); } else if(e.type == APPLE2Einterface::PASTE) { - for(unsigned int i = 0; i < strlen(e.str); i++) + for(uint32_t i = 0; i < strlen(e.str); i++) if(e.str[i] == '\n') board->enqueue_key('\r'); else @@ -1734,12 +1769,12 @@ extern uint16_t pc; template void print_cpu_state(const CPU6502& cpu) { - unsigned char s0 = bus.read(0x100 + cpu.s + 0); - unsigned char s1 = bus.read(0x100 + cpu.s + 1); - unsigned char s2 = bus.read(0x100 + cpu.s + 2); - unsigned char pc0 = bus.read(cpu.pc + 0); - unsigned char pc1 = bus.read(cpu.pc + 1); - unsigned char pc2 = bus.read(cpu.pc + 2); + uint8_t s0 = bus.read(0x100 + cpu.s + 0); + uint8_t s1 = bus.read(0x100 + cpu.s + 1); + uint8_t s2 = bus.read(0x100 + cpu.s + 2); + uint8_t pc0 = bus.read(cpu.pc + 0); + uint8_t pc1 = bus.read(cpu.pc + 1); + uint8_t pc2 = bus.read(cpu.pc + 2); printf("6502: A:%02X X:%02X Y:%02X P:", cpu.a, cpu.x, cpu.y); printf("%s", (cpu.p & cpu.N) ? "N" : "n"); printf("%s", (cpu.p & cpu.V) ? "V" : "v"); @@ -1749,10 +1784,11 @@ void print_cpu_state(const CPU6502& cpu) printf("%s", (cpu.p & cpu.I) ? "I" : "i"); printf("%s", (cpu.p & cpu.Z) ? "Z" : "z"); printf("%s ", (cpu.p & cpu.C) ? "C" : "c"); - printf("S:%02X (%02X %02X %02X ...) PC:%04X (%02X %02X %02X ...)\n", cpu.s, s0, s1, s2, cpu.pc, pc0, pc1, pc2); + printf("S:%02X (%02X %02X %02X ...) ", cpu.s, s0, s1, s2); + printf("PC:%04X (%02X %02X %02X ...)\n", cpu.pc, pc0, pc1, pc2); } -template +template struct averaged_sequence { int where; @@ -1762,7 +1798,7 @@ struct averaged_sequence averaged_sequence() : where(-1) { - for(unsigned int i = 0; i < LENGTH; i++) + for(uint32_t i = 0; i < LENGTH; i++) list[i] = 0; sum = 0; } @@ -1770,7 +1806,7 @@ struct averaged_sequence void add(TYPE value) { if(where == -1) { - for(unsigned int i = 0; i < LENGTH; i++) + for(uint32_t i = 0; i < LENGTH; i++) list[i] = value; sum = value * LENGTH; where = 0; @@ -1860,13 +1896,13 @@ int main(int argc, char **argv) } const char *romname = argv[0]; - unsigned char b[32768]; + uint8_t b[32768]; if(!read_blob(romname, b, sizeof(b))) { exit(EXIT_FAILURE); } - unsigned char diskII_rom[256]; + uint8_t diskII_rom[256]; if(diskII_rom_name != NULL) { if(!read_blob(diskII_rom_name, diskII_rom, sizeof(diskII_rom))) exit(EXIT_FAILURE); @@ -1879,15 +1915,15 @@ int main(int argc, char **argv) MAINboard* mainboard; - MAINboard::display_write_func display = [](int addr, bool aux, unsigned char data)->bool{return APPLE2Einterface::write(addr, aux, data);}; + MAINboard::display_write_func display = [](uint16_t addr, bool aux, uint8_t data)->bool{return APPLE2Einterface::write(addr, aux, data);}; MAINboard::get_paddle_func paddle = [](int num)->tuple{return APPLE2Einterface::get_paddle(num);}; MAINboard::audio_flush_func audio; if(mute) - audio = [](char *buf, size_t sz){ }; + audio = [](uint8_t *buf, size_t sz){ }; else - audio = [](char *buf, size_t sz){ if(!run_fast) APPLE2Einterface::enqueue_audio_samples(buf, sz); }; + audio = [](uint8_t *buf, size_t sz){ if(!run_fast) APPLE2Einterface::enqueue_audio_samples(buf, sz); }; mainboard = new MAINboard(clk, b, display, audio, paddle); bus.board = mainboard; @@ -1977,6 +2013,9 @@ int main(int argc, char **argv) if(debug & DEBUG_STATE) print_cpu_state(cpu); } + if(debug & DEBUG_CLOCK) { + printf("clock = %lu, %lu\n", (uint32_t)(clk / (1LLU << 32)), (uint32_t)(clk % (1LLU << 32))); + } } mainboard->sync(); @@ -2029,7 +2068,7 @@ int main(int argc, char **argv) exit_on_banking = true; continue; } else if(strncmp(line, "debug", 5) == 0) { - sscanf(line + 6, "%d", &debug); + sscanf(line + 6, "%u", &debug); printf("debug set to %02X\n", debug); continue; } else if(strcmp(line, "reset") == 0) { diff --git a/interface.cpp b/interface.cpp index 4ef9464..38c2abf 100644 --- a/interface.cpp +++ b/interface.cpp @@ -42,10 +42,10 @@ using namespace std; namespace APPLE2Einterface { -const int apple2_screen_width = 280; -const int apple2_screen_height = 192; -const int recording_scale = 2; -const int recording_frame_duration_hundredths = 5; +constexpr uint32_t apple2_screen_width = 280; +constexpr uint32_t apple2_screen_height = 192; +constexpr int recording_scale = 2; +constexpr uint32_t recording_frame_duration_hundredths = 5; chrono::time_point start_time; @@ -58,8 +58,8 @@ int joystick_axis1 = -1; int joystick_button0 = -1; int joystick_button1 = -1; -extern int font_offset; -extern const unsigned char font_bytes[96 * 7 * 8]; +extern uint16_t font_offset; +extern const uint8_t font_bytes[96 * 7 * 8]; static int gWindowWidth, gWindowHeight; @@ -96,14 +96,14 @@ event dequeue_event() } opengl_texture font_texture; -const int fonttexture_w = 7; -const int fonttexture_h = 8 * 96; +constexpr uint32_t fonttexture_w = 7; +constexpr uint32_t fonttexture_h = 8 * 96; opengl_texture textport_texture[2][2]; // [aux][page] GLuint text_program; -const int textport_w = 40; -const int textport_h = 24; +constexpr uint32_t textport_w = 40; +constexpr uint32_t textport_h = 24; GLuint textport_texture_location; GLuint textport_texture_coord_scale_location; GLuint textport_blink_location; @@ -135,8 +135,8 @@ GLuint lores_x_offset_location; GLuint lores_y_offset_location; GLuint lores_to_screen_location; -const int hires_w = 320; // MSBit is color chooser, Apple ][ weirdness -const int hires_h = 192; +const uint32_t hires_w = 320; // MSBit is color chooser, Apple ][ weirdness +const uint32_t hires_h = 192; opengl_texture hires_texture[2]; GLuint hires_program; @@ -170,7 +170,7 @@ tuple get_paddle(int num) return make_tuple(paddle_values[num], paddle_buttons[num]); } -const int raster_coords_attrib = 0; +const uint32_t raster_coords_attrib = 0; static const char *hires_vertex_shader = R"( uniform mat3 to_screen; @@ -485,7 +485,7 @@ void set_image_shader(float to_screen[9], const opengl_texture& texture, float x void initialize_screen_areas() { - for(int i = 0; i < apple2_screen_height; i++) { + for(uint32_t i = 0; i < apple2_screen_height; i++) { line_to_area[i].push_back({make_rectangle_array_buffer(0, i, apple2_screen_width, 1), raster_coords_attrib, 2, GL_FLOAT, GL_FALSE, 0}); } } @@ -632,7 +632,7 @@ struct apple2screen : public widget h = h_; long long elapsed_millis = now * 1000; - for(int i = 0; i < apple2_screen_height; i++) { + for(uint32_t i = 0; i < apple2_screen_height; i++) { const ModeSettings& settings = line_to_mode[i]; set_shader(to_screen, settings.mode, (i < 160) ? false : settings.mixed, settings.page, settings.vid80, (elapsed_millis / 300) % 2, x, y); @@ -723,9 +723,9 @@ struct image_widget : public widget { opengl_texture image; vertex_array rectangle; - int w, h; + int32_t w, h; - image_widget(int w_, int h_, unsigned char *buffer) : + image_widget(int32_t w_, int32_t h_, uint8_t *buffer) : w(w_), h(h_) { @@ -760,7 +760,7 @@ struct text_widget : public widget { content = content_; // construct string texture - unique_ptr bytes(new unsigned char[content.size() + 1]); + unique_ptr bytes(new uint8_t[content.size() + 1]); int i = 0; for(auto c : content) { if(c >= ' ' && c <= '?') @@ -1120,7 +1120,7 @@ void initialize_gl(void) CheckOpenGL(__FILE__, __LINE__); } -unsigned char disk_in_on_bitmap[] = { +uint8_t disk_in_on_bitmap[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 40, 40 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 255, // 40, 40 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, // 40, 40 @@ -1146,7 +1146,7 @@ unsigned char disk_in_on_bitmap[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 40, 40 }; -unsigned char disk_out_bitmap[] = { +uint8_t disk_out_bitmap[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 40, 40 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 255, // 40, 40 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, // 40, 40 @@ -1172,7 +1172,7 @@ unsigned char disk_out_bitmap[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 40, 40 }; -unsigned char disk_in_off_bitmap[] = { +uint8_t disk_in_off_bitmap[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // 40, 40 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 255, // 40, 40 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, // 40, 40 @@ -1397,9 +1397,9 @@ tuple window_to_widget(float x, float y) return make_tuple(wx, wy); } -void save_rgba_to_ppm(const unsigned char *rgba8_pixels, int width, int height, const char *filename) +void save_rgba_to_ppm(const uint8_t *rgba8_pixels, uint32_t width, uint32_t height, const char *filename) { - int row_bytes = width * 4; + size_t row_bytes = width * 4; FILE *fp = fopen(filename, "w"); fprintf(fp, "P6 %d %d 255\n", width, height); @@ -1413,7 +1413,7 @@ void save_rgba_to_ppm(const unsigned char *rgba8_pixels, int width, int height, void add_rendertarget_to_gif(double now, render_target *rt) { - static unsigned char image_recorded[apple2_screen_width * recording_scale * apple2_screen_height * recording_scale * 4]; + static uint8_t image_recorded[apple2_screen_width * recording_scale * apple2_screen_height * recording_scale * 4]; rt->start_rendering(); @@ -1590,7 +1590,7 @@ static void scroll(GLFWwindow *window, double dx, double dy) { } -const int pixel_scale = 3; +constexpr uint32_t pixel_scale = 3; void load_joystick_setup() { @@ -1623,9 +1623,9 @@ void drop_callback(GLFWwindow* window, int count, const char** paths) ui->drop(elapsed.count(), wx, wy, count, paths); } -void enqueue_audio_samples(char *buf, size_t sz) +void enqueue_audio_samples(uint8_t *buf, size_t sz) { - ao_play(aodev, buf, sz); + ao_play(aodev, (char*)buf, sz); } ao_device *open_ao() @@ -1714,15 +1714,15 @@ void apply_writes(void); // of frames worth of mode changes anyway. void map_mode_to_lines(const ModePoint& p, unsigned long long to_byte) { - unsigned int byte = get<0>(p); + uint64_t byte = get<0>(p); const ModeSettings& settings = get<1>(p); - int line = (byte + 17029) / 65; + uint64_t line = (byte + 17029) / 65; - int to_line = (to_byte + 17029) / 65; + uint64_t to_line = (to_byte + 17029) / 65; - for(int l = line; l < to_line; l++) { - int line_in_frame = l % 262; - if(0)printf("to_byte %llu, line %d : mode %s\n", to_byte, line_in_frame, (settings.mode == APPLE2Einterface::TEXT) ? "TEXT" : ((settings.mode == APPLE2Einterface::LORES) ? "LORES" : "HIRES")); + for(uint64_t l = line; l < to_line; l++) { + uint64_t line_in_frame = l % 262; + if(0)printf("to_byte %llu, line %llu: mode %s\n", to_byte, line_in_frame, (settings.mode == APPLE2Einterface::TEXT) ? "TEXT" : ((settings.mode == APPLE2Einterface::LORES) ? "LORES" : "HIRES")); if(line_in_frame < 192) line_to_mode[line_in_frame] = settings; } @@ -1741,7 +1741,7 @@ void map_history_to_lines(const ModeHistory& history, unsigned long long current auto& current = history[i]; auto& next = history[i + 1]; - unsigned int byte2 = get<0>(next); + uint64_t byte2 = get<0>(next); map_mode_to_lines(current, byte2); } @@ -1799,7 +1799,7 @@ void iterate(const ModeHistory& history, unsigned long long current_byte, float int axis_count, button_count; const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axis_count); - const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &button_count); + const uint8_t* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &button_count); { static bool checkedJoystickProbing = false; @@ -1863,30 +1863,30 @@ void shutdown() glfwTerminate(); } -static const int text_page1_base = 0x400; -static const int text_page2_base = 0x800; -static const int text_page_size = 0x400; -static const int hires_page1_base = 0x2000; -static const int hires_page2_base = 0x4000; -static const int hires_page_size = 8192; +constexpr uint16_t text_page1_base = 0x400; +constexpr uint16_t text_page2_base = 0x800; +constexpr uint16_t text_page_size = 0x400; +constexpr uint16_t hires_page1_base = 0x2000; +constexpr uint16_t hires_page2_base = 0x4000; +constexpr uint16_t hires_page_size = 8192; -extern int text_row_base_offsets[24]; -extern int hires_memory_to_scanout_address[8192]; +extern uint16_t text_row_base_offsets[24]; +extern uint16_t hires_memory_to_scanout_address[8192]; -typedef pair address_auxpage; -map< address_auxpage, unsigned char> writes; +typedef pair address_auxpage; +map writes; int collisions = 0; -void write2(int addr, bool aux, unsigned char data) +void write2(uint16_t addr, bool aux, uint8_t data) { // We know text page 1 and 2 are contiguous if((addr >= text_page1_base) && (addr < text_page2_base + text_page_size)) { - int page = (addr >= text_page2_base) ? 1 : 0; - int within_page = addr - text_page1_base - page * text_page_size; + uint16_t page = (addr >= text_page2_base) ? 1 : 0; + uint16_t within_page = addr - text_page1_base - page * text_page_size; for(int row = 0; row < 24; row++) { - int row_offset = text_row_base_offsets[row]; + uint16_t row_offset = text_row_base_offsets[row]; if((within_page >= row_offset) && (within_page < row_offset + 40)) { - int col = within_page - row_offset; + uint16_t col = within_page - row_offset; glBindTexture(GL_TEXTURE_2D, textport_texture[aux ? 1 : 0][page]); glTexSubImage2D(GL_TEXTURE_2D, 0, col, row, 1, 1, GL_RED, GL_UNSIGNED_BYTE, &data); CheckOpenGL(__FILE__, __LINE__); @@ -1895,15 +1895,15 @@ void write2(int addr, bool aux, unsigned char data) } else if(((addr >= hires_page1_base) && (addr < hires_page1_base + hires_page_size)) || ((addr >= hires_page2_base) && (addr < hires_page2_base + hires_page_size))) { - int page = (addr < hires_page2_base) ? 0 : 1; - int page_base = (page == 0) ? hires_page1_base : hires_page2_base; - int within_page = addr - page_base; - int scanout_address = hires_memory_to_scanout_address[within_page]; - int row = scanout_address / 40; - int col = scanout_address % 40; + uint16_t page = (addr < hires_page2_base) ? 0 : 1; + uint16_t page_base = (page == 0) ? hires_page1_base : hires_page2_base; + uint16_t within_page = addr - page_base; + uint16_t scanout_address = hires_memory_to_scanout_address[within_page]; + uint16_t row = scanout_address / 40; + uint16_t col = scanout_address % 40; glBindTexture(GL_TEXTURE_2D, hires_texture[page]); if(page == 0) hgr_page1[addr - 0x2000] = data; // XXX hack - unsigned char pixels[8]; + uint8_t pixels[8]; for(int i = 0; i < 8 ; i++) pixels[i] = ((data & (1 << i)) ? 255 : 0); glTexSubImage2D(GL_TEXTURE_2D, 0, col * 8, row, 8, 1, GL_RED, GL_UNSIGNED_BYTE, pixels); @@ -1914,7 +1914,7 @@ void write2(int addr, bool aux, unsigned char data) void apply_writes(void) { for(auto it : writes) { - int addr; + uint16_t addr; bool aux; tie(addr, aux) = it.first; write2(addr, aux, it.second); @@ -1923,7 +1923,7 @@ void apply_writes(void) collisions = 0; } -bool write(int addr, bool aux, unsigned char data) +bool write(uint16_t addr, bool aux, uint8_t data) { // We know text page 1 and 2 are contiguous if((addr >= text_page1_base) && (addr < text_page2_base + text_page_size)) { @@ -1943,7 +1943,7 @@ bool write(int addr, bool aux, unsigned char data) return false; } -int text_row_base_offsets[24] = +uint16_t text_row_base_offsets[24] = { 0x000, 0x080, @@ -1971,7 +1971,7 @@ int text_row_base_offsets[24] = 0x3D0, }; -static int hires_row_base_offsets[192] = +static uint16_t hires_row_base_offsets[192] = { 0x0000, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x0080, 0x0480, 0x0880, 0x0C80, 0x1080, 0x1480, 0x1880, 0x1C80, @@ -1999,21 +1999,21 @@ static int hires_row_base_offsets[192] = 0x03D0, 0x07D0, 0x0BD0, 0x0FD0, 0x13D0, 0x17D0, 0x1BD0, 0x1FD0, }; -int hires_memory_to_scanout_address[8192]; +uint16_t hires_memory_to_scanout_address[8192]; static void initialize_memory_to_scanout() __attribute__((constructor)); void initialize_memory_to_scanout() { - for(int row = 0; row < 192; row++) { - int row_address = hires_row_base_offsets[row]; - for(int byte = 0; byte < 40; byte++) { + for(uint16_t row = 0; row < 192; row++) { + uint16_t row_address = hires_row_base_offsets[row]; + for(uint16_t byte = 0; byte < 40; byte++) { hires_memory_to_scanout_address[row_address + byte] = row * 40 + byte; } } } -int font_offset = 32; -const unsigned char font_bytes[96 * 7 * 8] = { +uint16_t font_offset = 32; +const uint8_t font_bytes[96 * 7 * 8] = { // 32 : 0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00, diff --git a/interface.h b/interface.h index 9367bcc..5d31b05 100644 --- a/interface.h +++ b/interface.h @@ -83,16 +83,16 @@ struct ModeSettings } }; -typedef std::tuple ModePoint; +typedef std::tuple ModePoint; typedef std::vector ModeHistory; -bool write(int addr, bool aux, unsigned char data); +bool write(uint16_t addr, bool aux, uint8_t data); std::tuple get_paddle(int num); void show_floppy_activity(int number, bool activity); -void enqueue_audio_samples(char *buf, size_t sz); +void enqueue_audio_samples(uint8_t *buf, size_t sz); void start(bool run_fast, bool add_floppies, bool floppy0_inserted, bool floppy1_inserted); void iterate(const ModeHistory& history, unsigned long long current_byte_in_frame, float megahertz); // display