Uploaded Initial Repo Files
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
// boostrap.c
|
||||
// Boostrapping Functions for the SplitBit CPU Emulator
|
||||
// Written by Anachronaut
|
||||
// 10/16/2024
|
||||
|
||||
#include "bootstrap.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int byte = 0;
|
||||
const uint8_t HEADER_LENGTH = 3; // Number of bytes for the header.
|
||||
const uint8_t LENGTH_SIZE = 2; // Number of bytes for the segment length.
|
||||
|
||||
uint32_t readLength(FILE *file) {
|
||||
uint16_t length = 0;
|
||||
for (int i = 0; i < LENGTH_SIZE; i++) {
|
||||
int byte = fgetc(file);
|
||||
if (byte == EOF) {
|
||||
fprintf(stderr, "Error: Unexpected end of file while reading a segment length.\n");
|
||||
return UINT32_MAX;
|
||||
}
|
||||
length = (length << 8) | (uint8_t)byte;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
uint32_t readHeader(FILE *file, const char *expectedHeader) {
|
||||
uint8_t header[HEADER_LENGTH];
|
||||
for (int i = 0; i < HEADER_LENGTH; i++) {
|
||||
int byte = fgetc(file);
|
||||
if (byte == EOF) {
|
||||
fprintf(stderr, "Error: Unexpected end of file while reading a header.\n");
|
||||
return UINT32_MAX;
|
||||
}
|
||||
header[i] = (uint8_t)byte;
|
||||
}
|
||||
if (strncmp(header, expectedHeader, 3)) {
|
||||
fprintf(stderr, "Error: Bad header.\n");
|
||||
printf("Header: %s\nExpected Header: %s\n", header, expectedHeader);
|
||||
return UINT32_MAX;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t loadSegment(FILE *file, uint8_t *Memory, uint16_t length) {
|
||||
for (int16_t i = 0; i < length; i++) {
|
||||
byte = fgetc(file);
|
||||
if (byte == EOF) {
|
||||
fprintf(stderr, "Error: Unexpected end of file while reading a segment.\n");
|
||||
return 1;
|
||||
}
|
||||
Memory[i] = (uint8_t)byte;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t loadFile(char *path, uint8_t *Program, uint8_t *Data) {
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Error: Couldn't open file: %s\n", path);
|
||||
return 1;
|
||||
}
|
||||
// Read the first three bytes and check if they're the PRG header.
|
||||
if (readHeader(file, "PRG") == UINT32_MAX) {
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
// Now we need to get the length of the Program Section.
|
||||
uint32_t length = readLength(file);
|
||||
if (length == UINT32_MAX) {
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
// Now we load the Program Segment.
|
||||
if (loadSegment(file, Program, (uint16_t)length)) {
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
// Okay, Program is loaded, now do the same thing but for Data.
|
||||
// Check the header.
|
||||
if (readHeader(file, "DAT") == UINT32_MAX) {
|
||||
return 1;
|
||||
}
|
||||
// Get the legnth of the Data Section.
|
||||
length = readLength(file);
|
||||
if (length == UINT32_MAX){
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
// Now load the Data Section.
|
||||
if (loadSegment(file, Data, (uint16_t)length)) {
|
||||
fclose(file);
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// boostrap.h
|
||||
// Boostrapping Functions for the SplitBit CPU Emulator
|
||||
// Written by Anachronaut
|
||||
// 10/16/2024
|
||||
|
||||
#ifndef BOOTSTRAP_H
|
||||
#define BOOTSTRAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t loadFile(char *path, uint8_t *Program, uint8_t *Data);
|
||||
|
||||
#endif // BOOTSTRAP_H
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
// cpu.c
|
||||
// SplitBit CPU Emulator Core
|
||||
// Written by Anachronaut
|
||||
// 10/16/2024
|
||||
|
||||
#include "cpu.h"
|
||||
#include "io.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void initializeCPU(CPURegisters *cpu, uint8_t *programMemory, uint8_t *dataMemory) {
|
||||
cpu->A = 0;
|
||||
cpu->B = 0;
|
||||
cpu->Q = 0;
|
||||
cpu->Status = 0;
|
||||
cpu->ProgramCounter = 0x0000;
|
||||
cpu->DataPointer = 0x0000;
|
||||
cpu->StackPointer = 0xFFFF;
|
||||
cpu->Program = programMemory;
|
||||
cpu->Data = dataMemory;
|
||||
}
|
||||
|
||||
void genericBranch(CPURegisters *cpu){
|
||||
// Load the next two bytes from program memory into the Program Counter.
|
||||
// Byte order is imporant. Most Significant first, then Least Significant.
|
||||
cpu->ProgramCounter++; // Move to the next byte. (MSB)
|
||||
uint16_t DestinationAddress;
|
||||
DestinationAddress = (uint16_t)cpu->Program[cpu->ProgramCounter] << 8; // Cast the 8 bit value to a 16 bit value and shifts it up to the high byte.
|
||||
cpu->ProgramCounter++; // Move to the next byte. (LSB)
|
||||
DestinationAddress = DestinationAddress | (uint16_t)cpu->Program[cpu->ProgramCounter]; // Cast the 8 bit value to a 16 bit value and or it to add it to the desination.
|
||||
cpu->ProgramCounter = DestinationAddress-1;
|
||||
}
|
||||
|
||||
uint8_t executeOperation(uint8_t Instruction, CPURegisters *cpu) {
|
||||
switch(Instruction) {
|
||||
// 0x - Arithmetic and Logic Operations.
|
||||
case 0x00:
|
||||
// ADD - A + B + Carry -> Q
|
||||
uint16_t result = (uint16_t)cpu->A + (uint16_t)cpu->B + (cpu->Status & 0x01);
|
||||
if (result > 255) {
|
||||
cpu->Status |= 0x01;
|
||||
} else {
|
||||
cpu->Status &= ~0x01;
|
||||
}
|
||||
cpu->Q = result & 0xFF;
|
||||
break;
|
||||
case 0x01:
|
||||
// SUB - A - B - Carry -> Q
|
||||
result = (uint16_t)cpu->A - (uint16_t)cpu->B - (cpu->Status & 0x01);
|
||||
if (result > 255) {
|
||||
cpu->Status |= 0x01;
|
||||
} else {
|
||||
cpu->Status &= ~0x01;
|
||||
}
|
||||
cpu->Q = result & 0xFF;
|
||||
break;
|
||||
case 0x02:
|
||||
// AND - A and B -> Q
|
||||
cpu->Q = cpu->A&cpu->B;
|
||||
break;
|
||||
case 0x03:
|
||||
// OR - A or B -> Q
|
||||
cpu->Q = cpu->A|cpu->B;
|
||||
break;
|
||||
case 0x04:
|
||||
// NAND - A nand B -> Q
|
||||
cpu->Q = ~(cpu->A&cpu->B);
|
||||
break;
|
||||
case 0x05:
|
||||
// NOR - A nor B -> Q
|
||||
cpu->Q = ~(cpu->A|cpu->B);
|
||||
break;
|
||||
case 0x06:
|
||||
// XOR - A xor B -> Q
|
||||
cpu->Q = cpu->A^cpu->B;
|
||||
break;
|
||||
case 0x07:
|
||||
// NOTA - not A -> Q
|
||||
cpu->Q = ~cpu->A;
|
||||
break;
|
||||
case 0x08:
|
||||
// NOTB - not B -> Q
|
||||
cpu->Q = ~cpu->B;
|
||||
break;
|
||||
//
|
||||
// 1x - Branch Operations:
|
||||
//
|
||||
case 0x10:
|
||||
// BRI - Branch Immediately
|
||||
genericBranch(cpu);
|
||||
break;
|
||||
case 0x11:
|
||||
// BRQ - Branch if Q = 0
|
||||
if(cpu->Q == 0) {
|
||||
genericBranch(cpu);
|
||||
} else {
|
||||
|
||||
cpu->ProgramCounter+=2;
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
// BRA - Branch if A = 0
|
||||
if(cpu->A == 0) {
|
||||
genericBranch(cpu);
|
||||
|
||||
} else {
|
||||
cpu->ProgramCounter+=2;
|
||||
}
|
||||
break;
|
||||
case 0x13:
|
||||
// BRB - if B = 0
|
||||
if(cpu->B == 0) {
|
||||
|
||||
genericBranch(cpu);
|
||||
} else {
|
||||
cpu->ProgramCounter+=2;
|
||||
}
|
||||
break;
|
||||
//
|
||||
// 2x - Register Operations:
|
||||
//
|
||||
case 0x20:
|
||||
// RSTA - Reset A to 0.
|
||||
cpu->A = 0;
|
||||
break;
|
||||
case 0x21:
|
||||
// RSTB - Reset B to 0.
|
||||
cpu->B = 0;
|
||||
break;
|
||||
case 0x22:
|
||||
// INCA - Add 1 to A.
|
||||
cpu->A++;
|
||||
break;
|
||||
case 0x23:
|
||||
// INCB - Add 1 to B.
|
||||
cpu->B++;
|
||||
break;
|
||||
case 0x24:
|
||||
// DECA - Subtract 1 from A.
|
||||
cpu->A--;
|
||||
break;
|
||||
case 0x25:
|
||||
// DECB - Subtract 1 from B.
|
||||
cpu->B--;
|
||||
break;
|
||||
case 0x26:
|
||||
// LDA - Load the byte referenced by the Data Pointer to A.
|
||||
cpu->A = cpu->Data[cpu->DataPointer];
|
||||
break;
|
||||
case 0x27:
|
||||
// LDB - Load the byte referenced by the Data Pointer to B.
|
||||
cpu->B = cpu->Data[cpu->DataPointer];
|
||||
break;
|
||||
case 0x28:
|
||||
// INCD - Add 1 to the Data Pointer.
|
||||
cpu->DataPointer++;
|
||||
break;
|
||||
case 0x29:
|
||||
// DECD - Subtract 1 from the Data Pointer.
|
||||
cpu->DataPointer--;
|
||||
break;
|
||||
//
|
||||
// 3x - Stack Operations:
|
||||
//
|
||||
case 0x30:
|
||||
// PSHQ - Push Q to the Stack.
|
||||
cpu->Data[cpu->StackPointer] = cpu->Q;
|
||||
cpu->StackPointer--;
|
||||
break;
|
||||
case 0x31:
|
||||
// PSHA - Push A to the Stack.
|
||||
cpu->Data[cpu->StackPointer] = cpu->A;
|
||||
cpu->StackPointer--;
|
||||
break;
|
||||
case 0x32:
|
||||
// PSHB - Push B to the Stack.
|
||||
cpu->Data[cpu->StackPointer] = cpu->B;
|
||||
cpu->StackPointer--;
|
||||
break;
|
||||
case 0x33:
|
||||
// PSHP - Push the Program Counter to the Stack.
|
||||
// Order, low byte, high byte
|
||||
cpu->Data[cpu->StackPointer] = cpu->ProgramCounter & 0xFF;
|
||||
cpu->StackPointer--;
|
||||
cpu->Data[cpu->StackPointer] = (cpu->ProgramCounter >> 8) & 0xFF;
|
||||
cpu->StackPointer--;
|
||||
break;
|
||||
case 0x34:
|
||||
// PSHD - Push the Data Pointer to the Stack.
|
||||
// Order, low byte, high byte
|
||||
cpu->Data[cpu->StackPointer] = cpu->DataPointer & 0xFF;
|
||||
cpu->StackPointer--;
|
||||
cpu->Data[cpu->StackPointer] = (cpu->DataPointer >> 8) & 0xFF;
|
||||
cpu->StackPointer--;
|
||||
break;
|
||||
case 0x35:
|
||||
// POPA - Pop Data to A.
|
||||
cpu->A = cpu->Data[cpu->StackPointer];
|
||||
cpu->StackPointer++;
|
||||
break;
|
||||
case 0x36:
|
||||
// POPB - Pop Data to B.
|
||||
cpu->B = cpu->Data[cpu->StackPointer];
|
||||
cpu->StackPointer++;
|
||||
break;
|
||||
case 0x37:
|
||||
// POPP - Pop Data to the Program Counter
|
||||
cpu->ProgramCounter = (uint16_t)cpu->Data[cpu->StackPointer] << 8;
|
||||
cpu->StackPointer++;
|
||||
cpu->ProgramCounter = cpu->ProgramCounter | (uint16_t)cpu->Data[cpu->StackPointer];
|
||||
cpu->StackPointer++;
|
||||
break;
|
||||
case 0x38:
|
||||
// POPD - Pop Data to the Data Pointer
|
||||
cpu->DataPointer = (uint16_t)cpu->Data[cpu->StackPointer] << 8;
|
||||
cpu->StackPointer++;
|
||||
cpu->DataPointer |= (uint16_t)cpu->Data[cpu->StackPointer];
|
||||
cpu->StackPointer++;
|
||||
break;
|
||||
//
|
||||
// 4x - Data Operations:
|
||||
//
|
||||
case 0x40:
|
||||
// INCD - Increment Data Pointer.
|
||||
cpu->DataPointer++;
|
||||
break;
|
||||
case 0x41:
|
||||
// DECD - Decrement Data Pointer.
|
||||
cpu->DataPointer--;
|
||||
break;
|
||||
case 0x42:
|
||||
// LDA - Load A from Data.
|
||||
cpu->A = cpu->Data[cpu->DataPointer];
|
||||
break;
|
||||
case 0x43:
|
||||
// LDB - Load B from Data.
|
||||
cpu->B = cpu->Data[cpu->DataPointer];
|
||||
break;
|
||||
case 0x44:
|
||||
// STQ - Store Q into Data.
|
||||
cpu->Data[cpu->DataPointer] = cpu->Q;
|
||||
break;
|
||||
case 0x45:
|
||||
// STA - Store A into Data.
|
||||
cpu->Data[cpu->DataPointer] = cpu->A;
|
||||
break;
|
||||
case 0x46:
|
||||
// STB - Store B into Data.
|
||||
cpu->Data[cpu->DataPointer] = cpu->B;
|
||||
break;
|
||||
//
|
||||
// Dx - Output Operations:
|
||||
//
|
||||
case 0xD0:
|
||||
// OUTQ - Write the value of Q to an output port.
|
||||
cpu->ProgramCounter++;
|
||||
OutputHandler(cpu->Q, cpu->Program[cpu->ProgramCounter]);
|
||||
break;
|
||||
case 0xD1:
|
||||
// OUTA - Write the value of A to an output port.
|
||||
cpu->ProgramCounter++;
|
||||
OutputHandler(cpu->A, cpu->Program[cpu->ProgramCounter]);
|
||||
break;
|
||||
case 0xD2:
|
||||
// OUTB - Write the value of B to an output port.
|
||||
cpu->ProgramCounter++;
|
||||
OutputHandler(cpu->B, cpu->Program[cpu->ProgramCounter]);
|
||||
break;
|
||||
//
|
||||
// Ex - Input Operations:
|
||||
//
|
||||
case 0xE0:
|
||||
// CIN - Read Input Select to A.
|
||||
// cpu->A = InputSelect;
|
||||
break;
|
||||
case 0xE1:
|
||||
// RDA - Read an Input to A.
|
||||
cpu->ProgramCounter++;
|
||||
cpu->A = InputHandler(cpu->Program[cpu->ProgramCounter]);
|
||||
break;
|
||||
case 0xE2:
|
||||
// RDB - Read an Input to B.
|
||||
cpu->ProgramCounter++;
|
||||
cpu->B = InputHandler(cpu->Program[cpu->ProgramCounter]);
|
||||
break;
|
||||
case 0xE3:
|
||||
// RDD - Read an Input to Data Memory.
|
||||
cpu->ProgramCounter++;
|
||||
cpu->Data[cpu->DataPointer] = InputHandler(cpu->Program[cpu->ProgramCounter]);
|
||||
break;
|
||||
//
|
||||
// Fx - Special Operations:
|
||||
//
|
||||
case 0xF0:
|
||||
// NOP - Do nothing.
|
||||
break;
|
||||
case 0xFF:
|
||||
// HALT - Set the Halt Bit of the Status Register.
|
||||
cpu->Status |= 0x80;
|
||||
break;
|
||||
default:
|
||||
// Unknown Instruction.
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// cpu.h
|
||||
// SplitBit CPU Emulator Core
|
||||
// Written by Anachronaut
|
||||
// 10/16/2024
|
||||
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// The struct containing the CPU registers.
|
||||
typedef struct {
|
||||
uint8_t A;
|
||||
uint8_t B;
|
||||
uint8_t Q;
|
||||
uint8_t Status;
|
||||
uint16_t ProgramCounter;
|
||||
uint16_t DataPointer;
|
||||
uint16_t StackPointer;
|
||||
uint8_t *Program;
|
||||
uint8_t *Data;
|
||||
} CPURegisters;
|
||||
|
||||
uint8_t executeOperation(uint8_t instruction, CPURegisters *cpu);
|
||||
|
||||
void initializeCPU(CPURegisters *cpu, uint8_t *programMemory, uint8_t *dataMemory);
|
||||
|
||||
#endif // CPU_H
|
||||
@@ -0,0 +1,61 @@
|
||||
// emulator.c
|
||||
|
||||
// SplitBit Emulator
|
||||
// Small 8-Bit Harvard Architecture CPU
|
||||
// Written by Anachronaut
|
||||
// 10/15/2024
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "cpu.h"
|
||||
#include "utility.h"
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
uint8_t debugEnable = 0;
|
||||
int cycleCount = 0;
|
||||
char *programFile = NULL;
|
||||
|
||||
// Memory Banks:
|
||||
uint8_t Program[0x10000], Data[0x10000];
|
||||
|
||||
int main (int argc, char *argv[]) {
|
||||
uint8_t test = parseOptions(argc, argv);
|
||||
if (test == 1){
|
||||
// Enable the Debug Mode.
|
||||
debugEnable = 1;
|
||||
} else if (test == 2){
|
||||
// User asked for help or gave a bad option, don't execute.
|
||||
return 1;
|
||||
}
|
||||
if (optind < argc) {
|
||||
programFile = argv[optind];
|
||||
optind++;
|
||||
} else {
|
||||
fprintf(stderr, "Error: No binary file specified.\n");
|
||||
printHelp(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (optind < argc) {
|
||||
fprintf(stderr, "Error: Unexpected argument: %s\n", argv[optind]);
|
||||
return 1;
|
||||
}
|
||||
if (loadFile(programFile, Program, Data)) {
|
||||
fprintf(stderr, "Error: Couldn't read file: %s\n", programFile);
|
||||
return 1;
|
||||
}
|
||||
CPURegisters cpu;
|
||||
initializeCPU(&cpu, Program, Data);
|
||||
while (!(cpu.Status & 0x80)) {
|
||||
if (debugEnable) {
|
||||
getchar();
|
||||
printRegisters(&cpu, Program, Data);
|
||||
}
|
||||
|
||||
executeOperation(cpu.Program[cpu.ProgramCounter], &cpu);
|
||||
cpu.ProgramCounter++;
|
||||
cycleCount++;
|
||||
}
|
||||
printf("Execution halted after %u cycles.\n", cycleCount);
|
||||
}
|
||||
Binary file not shown.
+37
@@ -0,0 +1,37 @@
|
||||
// io.c
|
||||
// I/O for the SplitBit CPU Emulator
|
||||
// Written by Anachronaut
|
||||
// 10/16/2024
|
||||
|
||||
#include "io.h"
|
||||
#include <stdio.h>
|
||||
|
||||
uint8_t OutputHandler(uint8_t DataByte, uint8_t Address) {
|
||||
// This function sends the DataByte to the appropriate place based on the Port Address.
|
||||
switch(Address) {
|
||||
case 0x00:
|
||||
// If data is sent here, it should be written to STDOUT.
|
||||
// For now, I'll implement this so it simply writes each byte out as it comes in.
|
||||
// Later, I'll want to use a buffer for this for performance, probably.
|
||||
putchar(DataByte);
|
||||
break;
|
||||
default:
|
||||
// Writes to unused Output Ports are ignored.
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t InputHandler(uint8_t Address) {
|
||||
switch(Address) {
|
||||
case 0x00:
|
||||
// If data is sent here, it should be read from STDIN.
|
||||
return getchar();
|
||||
break;
|
||||
default:
|
||||
// Reading from an unused port is ignored.
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// io.h
|
||||
// I/O for the SplitBit CPU Emulator
|
||||
// Written by Anachronaut
|
||||
// 10/16/2024
|
||||
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "cpu.h"
|
||||
|
||||
uint8_t OutputHandler(uint8_t DataByte, uint8_t Address);
|
||||
|
||||
uint8_t InputHandler(uint8_t Address);
|
||||
|
||||
#endif // IO_H
|
||||
@@ -0,0 +1,55 @@
|
||||
// utility.c
|
||||
// Utilities for the SplitBit CPU Emulator
|
||||
// Written by Anachronaut
|
||||
// 10/15/2024
|
||||
|
||||
#include "utility.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
|
||||
void printHelp(const char *programName) {
|
||||
printf("Usage: %s [OPTIONS] <binaryfile>\n", programName);
|
||||
printf("\n");
|
||||
printf("Options:\n");
|
||||
printf(" -d, --debug Enable debug mode.\n");
|
||||
printf(" -h, --help Display this help message.\n");
|
||||
}
|
||||
|
||||
uint8_t parseOptions(int argc, char *argv[]) {
|
||||
static struct option long_options[] = {
|
||||
{"debug", no_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
|
||||
// Parse options
|
||||
while ((opt = getopt_long(argc, argv, "dh", long_options, &option_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'd':
|
||||
return 1;
|
||||
break;
|
||||
case 'h':
|
||||
printHelp(argv[0]);
|
||||
return 2;
|
||||
case '?':
|
||||
printHelp(argv[0]);
|
||||
return 2;
|
||||
default:
|
||||
printHelp(argv[0]);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void printRegisters(CPURegisters *cpu, uint8_t *Program, uint8_t *Data) {
|
||||
printf("***** CPU Registers *****\n");
|
||||
printf("A: 0x%02X\tB: 0x%02X\tQ: 0x%02X\tStatus: 0b%08b\n", cpu->A, cpu->B, cpu->Q, cpu->Status);
|
||||
printf("Program Counter: 0x%04X Current Instruction: 0x%02X\n", cpu->ProgramCounter, Program[cpu->ProgramCounter]);
|
||||
printf(" Data Pointer: 0x%04X Current Data Value: 0x%02X\n", cpu->DataPointer, Data[cpu->DataPointer]);
|
||||
printf(" Stack Pointer: 0x%04X Current Value: 0x%02X\n", cpu->StackPointer, Data[cpu->StackPointer]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// utility.h
|
||||
// Utilities for the SplitBit CPU Emulator
|
||||
// Written by Anachronaut
|
||||
// 10/15/2024
|
||||
|
||||
|
||||
#ifndef UTILITY_H
|
||||
#define UTILITY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "cpu.h"
|
||||
|
||||
uint8_t parseOptions(int argc, char *argv[]);
|
||||
|
||||
void printHelp(const char *programName);
|
||||
|
||||
uint8_t loadFile(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
|
||||
Reference in New Issue
Block a user