The first recording ever made with this came back 1,766 frames of nothing. It recorded pad NOUGHT and the controller was somewhere else - which pad one lands on is an accident of the host, the same accident that made Lunar Porter read all four in the first place - and a flight flown for the purpose was lost to it. So every pad is or-ed into the byte. A demo is a record of what somebody DID, and on a machine one person is playing the number it arrived on is not part of that. It plays back on pad nought, where --pad puts the first file given, and any program that reads more than one pad reads them or-ed anyway for exactly the same reason. --record-pad takes one file now rather than filling pads in turn, because there is nothing left for the second one to mean. The check for it plays a recording on pad ONE with nought holding nothing and requires the bytes back. That is the case that was missing: the round trip was tested and passed, on pad nought, which is the only pad it could not have gone wrong on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
67 lines
2.9 KiB
C
67 lines
2.9 KiB
C
// utility.h
|
|
// Utilities for the SplitBit CPU Emulator
|
|
// Written by Anachronaut
|
|
// 10/15/2024
|
|
|
|
|
|
#ifndef UTILITY_H
|
|
#define UTILITY_H
|
|
|
|
#include <stdint.h>
|
|
#include "io.h"
|
|
#include "cpu.h"
|
|
|
|
// Results of reading the command line.
|
|
#define OPTIONS_OK 0 // Carry on and run the program.
|
|
#define OPTIONS_HELP 1 // The user asked for help, so stop, but not because of an error.
|
|
#define OPTIONS_ERROR 2 // The command line was no good, stop and complain.
|
|
|
|
// As many as the machine has pads.
|
|
#define PAD_DRIVE_COUNT 4
|
|
|
|
typedef struct {
|
|
uint8_t debug; // Step one instruction at a time, printing the registers.
|
|
uint8_t fast; // Ignore the cycle rate and run as fast as the host allows.
|
|
unsigned long cycles; // Stop after this many cycles. Zero means run until the program halts.
|
|
unsigned long diskCycles; // How long a block move takes. Zero is instant, and the default.
|
|
// ---- The drives, in the order they were named ----
|
|
//
|
|
// --disk given more than once fills them in turn, so the first is drive 0 and the machine
|
|
// has as many as were asked for. One name is the ordinary case and reads exactly as it
|
|
// did when there could only be one.
|
|
const char *disk; // Disk image to attach, or NULL for a machine with no disk.
|
|
const char *disks[DISK_DRIVE_COUNT];
|
|
int diskCount;
|
|
// A drive of this many blocks made of memory, taking the next drive number after the
|
|
// images above. Zero for a machine without one.
|
|
unsigned long ramDisk;
|
|
uint8_t writeProtect; // Attach the disk read only, the way a tab on a floppy would.
|
|
const char *screen; // Where to save a picture of the screen when the machine stops.
|
|
const char *keyboard; // Feed the console from this file as a keyboard, not a terminal.
|
|
const char *sound; // Where to save the samples the machine made, as raw 16 bit.
|
|
// ---- A controller made of a file ----
|
|
//
|
|
// One byte a frame, each byte the buttons held during it. Voyager reads a real pad, and
|
|
// its own tests run headless with nobody holding anything - so without this the device
|
|
// would be exercised only by somebody playing, which is exactly the state the console's
|
|
// line editing was in when it broke twice in two days.
|
|
const char *pads[PAD_DRIVE_COUNT];
|
|
int padCount; // --pad given more than once fills them in turn, like --disk.
|
|
// Where to write what the controllers held, one byte a frame, in the format --pad reads.
|
|
// Every pad or-ed together, because which one a controller lands on is the host's business
|
|
// and a demo is a record of what somebody did.
|
|
const char *padRecord;
|
|
} EmulatorOptions;
|
|
|
|
uint8_t parseOptions(int argc, char *argv[], EmulatorOptions *options);
|
|
|
|
void printHelp(const char *programName);
|
|
|
|
uint8_t loadFile(const char *path, uint8_t *Program, uint8_t *Data);
|
|
|
|
void bootStrap(uint8_t *Program, uint8_t *Data);
|
|
|
|
void printRegisters(CPURegisters *cpu, uint8_t *Program, uint8_t *Data);
|
|
|
|
#endif // UTILITY_H
|