use more well-defined int types

This commit is contained in:
Brad Grantham 2020-12-16 23:03:43 -08:00
parent fb7d31d814
commit 3c1b43f2ad
4 changed files with 206 additions and 165 deletions

View File

@ -13,5 +13,7 @@ all: apple2e
apple2e: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LDLIBS)
apple2e.o: cpu6502.h
clean:
rm $(OBJECTS)

View File

@ -14,11 +14,53 @@
#include <thread>
#include <functional>
#include <signal.h>
#include <unistd.h>
#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<int,string> 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<unsigned char> memory;
vector<uint8_t> 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<unsigned int, string> io = {
const map<uint32_t, string> 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<void (int number, bool activity)> 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<unsigned char> keyboard_buffer;
deque<uint8_t> 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<bool (int addr, bool aux, unsigned char data)> display_write_func;
typedef std::function<bool (int addr, bool aux, uint8_t data)> display_write_func;
display_write_func display_write;
typedef std::function<void (char *audiobuffer, size_t dist)> audio_flush_func;
typedef std::function<void (uint8_t *audiobuffer, size_t dist)> audio_flush_func;
audio_flush_func audio_flush;
typedef std::function<tuple<float, bool> (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<int, vector<unsigned char> > writes;
map<int, vector<unsigned char> > reads;
map<int, vector<uint8_t> > writes;
map<int, vector<uint8_t> > 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<int, key_to_ascii> 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<class CLK, class BUS>
void print_cpu_state(const CPU6502<CLK, BUS>& 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<CLK, BUS>& 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 <class TYPE, unsigned int LENGTH>
template <class TYPE, uint32_t LENGTH>
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<float, bool>{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) {

View File

@ -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<chrono::system_clock> 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<float,bool> 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<unsigned char> bytes(new unsigned char[content.size() + 1]);
unique_ptr<uint8_t> 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<float, float> 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<int, bool> address_auxpage;
map< address_auxpage, unsigned char> writes;
typedef pair<uint16_t, bool> address_auxpage;
map<address_auxpage, uint8_t> 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,

View File

@ -83,16 +83,16 @@ struct ModeSettings
}
};
typedef std::tuple<unsigned long long, ModeSettings> ModePoint;
typedef std::tuple<uint64_t, ModeSettings> ModePoint;
typedef std::vector<ModePoint> ModeHistory;
bool write(int addr, bool aux, unsigned char data);
bool write(uint16_t addr, bool aux, uint8_t data);
std::tuple<float,bool> 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