Fix BASIC

Fix cycle waiting
Fix warnings
This commit is contained in:
Kilian committed 2026-09-27 04:48:39 +02:00
1 parent 8101cc3f62
commit a5e30a7b28
12 files changed
+111 -58

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
{
"cSpell.words": [
"msbasic",
"Wmissing",
"Wunused"
]
}
+6
View File
@@ -10,12 +10,18 @@ enable_language(C)
add_executable(${CMAKE_PROJECT_NAME}) add_executable(${CMAKE_PROJECT_NAME})
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE _POSIX_C_SOURCE=200809L)
if(MSVC) if(MSVC)
target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE /W4) target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE /W4)
else() else()
target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic) target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic)
endif() endif()
target_compile_options(${CMAKE_PROJECT_NAME} PRIVATE
-include ${CMAKE_CURRENT_SOURCE_DIR}/inc/diag.h
)
target_sources(${CMAKE_PROJECT_NAME} PRIVATE target_sources(${CMAKE_PROJECT_NAME} PRIVATE
"src/main.c" "src/main.c"
"src/ram.c" "src/ram.c"
+28
View File
@@ -0,0 +1,28 @@
#define DIAG_STRINGIFY_(x) #x
#define DIAG_STRINGIFY(x) DIAG_STRINGIFY_(x)
#define DIAG_DO_PRAGMA(x) _Pragma(DIAG_STRINGIFY(x))
#if defined(__clang__)
#define DIAG_PUSH() DIAG_DO_PRAGMA(clang diagnostic push)
#define DIAG_POP() DIAG_DO_PRAGMA(clang diagnostic pop)
#define DIAG_IGNORE(w) DIAG_DO_PRAGMA(clang diagnostic ignored w)
#elif defined(__GNUC__)
#define DIAG_PUSH() DIAG_DO_PRAGMA(GCC diagnostic push)
#define DIAG_POP() DIAG_DO_PRAGMA(GCC diagnostic pop)
#define DIAG_IGNORE(w) DIAG_DO_PRAGMA(GCC diagnostic ignored w)
#else
#define DIAG_PUSH()
#define DIAG_POP()
#define DIAG_IGNORE(w)
#endif
+2 -2
View File
@@ -1,12 +1,12 @@
#ifndef MEMORY_MAP_H #ifndef MEMORY_MAP_H
#define MEMORY_MAP_H #define MEMORY_MAP_H
#include <stdint.h>
#include "io.h" #include "io.h"
#include "ram.h" #include "ram.h"
#include "rom.h" #include "rom.h"
#include <stdint.h>
uint8_t readMemory(uint16_t address, uint8_t *ram, uint8_t *rom); uint8_t readMemory(uint16_t address, uint8_t *ram, uint8_t *rom);
void writeMemory(uint16_t address, uint8_t value, uint8_t *ram); void writeMemory(uint16_t address, uint8_t value, uint8_t *ram);
+2 -2
View File
@@ -1,9 +1,9 @@
#ifndef RAM_H #ifndef RAM_H
#define RAM_H #define RAM_H
#include "stdint.h" #include <stdint.h>
#define RAM_SIZE (64 * 1024) // 55KiB #define RAM_SIZE (64 * 1024) // 64KiB, read/write to IO is ignored, ROM can be banked
#define RAM_BASE (0x00) // 0 #define RAM_BASE (0x00) // 0
int createRAM(uint8_t **ram); int createRAM(uint8_t **ram);
+1 -1
View File
@@ -22,6 +22,6 @@ USR := GORESTART ; XXX
; constants ; constants
SPACE_FOR_GOSUB := $3E SPACE_FOR_GOSUB := $3E
STACK_TOP := $FA STACK_TOP := $FA
WIDTH := 40 WIDTH := 80
WIDTH2 := 30 WIDTH2 := 30
RAMSTART2 := $0400 RAMSTART2 := $0400
+8 -1
View File
@@ -200,6 +200,11 @@ L4098:
lda #$01 lda #$01
sta INPUTBUFFER-3 sta INPUTBUFFER-3
sta INPUTBUFFER-4 sta INPUTBUFFER-4
.endif
.ifdef CONFIG_INPUTBUFFER_0200
lda #$01
sta INPUTBUFFER-3
sta INPUTBUFFER-4
.endif .endif
ldx #TEMPST ldx #TEMPST
stx TEMPPT stx TEMPPT
@@ -226,7 +231,9 @@ L4098:
.ifndef AIM65 .ifndef AIM65
.ifndef SYM1 .ifndef SYM1
cmp #$41 cmp #$41
beq PR_WRITTEN_BY bne SKIPPED
jmp PR_WRITTEN_BY
SKIPPED:
.endif .endif
.endif .endif
tay tay
+3 -3
View File
@@ -58,10 +58,10 @@ static void doSBC(CPU *cpu, uint8_t value) {
} }
void initCPU(CPU *cpu) { void initCPU(CPU *cpu) {
#pragma clang diagnostic push DIAG_PUSH();
#pragma clang diagnostic ignored "-Wmissing-field-initializers" DIAG_IGNORE("-Wmissing-field-initializers");
*cpu = (CPU){0x0000, 0xFF}; *cpu = (CPU){0x0000, 0xFF};
#pragma clang diagnostic pop DIAG_POP();
} }
void resetCPU(CPU *cpu, uint8_t *rom) { void resetCPU(CPU *cpu, uint8_t *rom) {
+41 -38
View File
@@ -1,18 +1,23 @@
#include "cpu.h"
#include "ram.h"
#include "rom.h"
#include <fcntl.h> #include <fcntl.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <termios.h> #include <termios.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#define MACHINE_SPEED_HZ 1e6 // 1 MHz; #include "cpu.h"
#include "ram.h"
#include "rom.h"
static struct termios orig_termios; #define MACHINE_SPEED_HZ 1000000ULL // 1 MHz;
static struct timespec sleepTime; #define SYNC_CYCLES 100
struct termios orig_termios;
struct timespec emulationStart;
uint64_t totalCycles = 0;
uint64_t lastSyncCycles = 0;
void restore_terminal(void) { tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios); } void restore_terminal(void) { tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios); }
@@ -36,11 +41,13 @@ void set_nonblocking_input(void) {
} }
int main(void) { int main(void) {
uint8_t *ram = NULL;
CPU cpu;
printf("6502PC Emulator with MS Basic\n"); printf("6502PC Emulator with MS Basic\n");
printf("CTRL + G to exit\n"); printf("CTRL + G to exit\n");
uint8_t *ram = NULL; clock_gettime(CLOCK_MONOTONIC, &emulationStart);
CPU cpu;
set_nonblocking_input(); set_nonblocking_input();
@@ -51,44 +58,40 @@ int main(void) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* DEBUG */
// FILE *fp = fopen("/Users/Kili2/Documents/Projekte/6502pc/6502_65C02_functional_tests/6502_functional_test.bin", "rb");
// FILE *fp = fopen("/Users/Kili2/Documents/Projekte/6502pc/6502_65C02_functional_tests/6502_decimal_test.bin", "rb");
// FILE *fp = fopen("/mnt/c/Users/llego/source/repos/6502PC/6502_65C02_functional_tests/6502_functional_test.bin", "rb");
// FILE *fp = fopen("/mnt/c/Users/llego/source/repos/6502PC/6502_65C02_functional_tests/6502_decimal_test.bin", "rb");
/*
if (!fp) {
perror("fopen");
exit(EXIT_FAILURE);
}
fread(ram, 1, RAM_SIZE, fp);
if (ferror(fp)) {
perror("fread");
fclose(fp);
exit(EXIT_FAILURE);
}
fclose(fp);
*/
/* DEBUG END*/
initCPU(&cpu); initCPU(&cpu);
resetCPU(&cpu, rom); resetCPU(&cpu, rom);
while (1) { while (1) {
uint8_t sleep = runCycle(&cpu, ram, rom); uint8_t cycles = runCycle(&cpu, ram, rom);
if (sleep == 1) { totalCycles += cycles;
// No 1 cycle instruction exists
if (cycles == 1) {
printf("Illegal opcode $%02X at $%04X " printf("Illegal opcode $%02X at $%04X "
"A=$%02X X=$%02X Y=$%02X SP=$%02X\n", "A=$%02X X=$%02X Y=$%02X SP=$%02X\n",
ram[cpu.ProgrammeCounter - 1], cpu.ProgrammeCounter - 1, cpu.Accumulator, cpu.X, cpu.Y, cpu.StackPointer); ram[cpu.ProgrammeCounter - 1], cpu.ProgrammeCounter - 1, cpu.Accumulator, cpu.X, cpu.Y, cpu.StackPointer);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
sleepTime.tv_sec = 0;
sleepTime.tv_nsec = sleep * (1000 / MACHINE_SPEED_HZ); // Sleep if batch is full
nanosleep(&sleepTime, NULL); if (totalCycles - lastSyncCycles >= SYNC_CYCLES) {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint64_t elapsed_ns =
(uint64_t)(now.tv_sec - emulationStart.tv_sec) * 1000000000ULL + (uint64_t)(now.tv_nsec - emulationStart.tv_nsec);
uint64_t target_ns = totalCycles * 1000000000ULL / MACHINE_SPEED_HZ;
if (target_ns > elapsed_ns) {
uint64_t wait_ns = target_ns - elapsed_ns;
struct timespec wait = {.tv_sec = wait_ns / 1000000000ULL, .tv_nsec = wait_ns % 1000000000ULL};
nanosleep(&wait, NULL);
}
lastSyncCycles = totalCycles;
}
} }
destroyRAM(ram); destroyRAM(ram);
+5 -2
View File
@@ -1,13 +1,16 @@
#include "memoryMap.h" #include "memoryMap.h"
uint8_t readMemory(uint16_t address, uint8_t *ram, uint8_t *rom) { uint8_t readMemory(uint16_t address, uint8_t *ram, uint8_t *rom) {
if ((address < RAM_SIZE && address < IO_BASE) || address >= ROM_BASE) { // RAM/ROM
if (address < IO_BASE || address >= ROM_BASE) {
if (address >= ROM_BASE && ram[IO_BASE + ROM_BANKED_OUT] == 0) { if (address >= ROM_BASE && ram[IO_BASE + ROM_BANKED_OUT] == 0) {
return rom[address - ROM_BASE]; return rom[address - ROM_BASE];
} }
return ram[address]; return ram[address];
} else { }
// I/O
else {
uint16_t _address = address - IO_BASE; uint16_t _address = address - IO_BASE;
switch (_address) { switch (_address) {
case KEYBOARD_ADDRESS: { case KEYBOARD_ADDRESS: {
+2 -2
View File
@@ -1,9 +1,9 @@
#include "ram.h" #include "ram.h"
#include "io.h"
#include <stdlib.h> #include <stdlib.h>
#include "io.h"
int createRAM(uint8_t **ram) { int createRAM(uint8_t **ram) {
*ram = (uint8_t *)malloc(RAM_SIZE); *ram = (uint8_t *)malloc(RAM_SIZE);
+6 -7
View File
@@ -1,20 +1,23 @@
#include "rom.h" #include "rom.h"
#include "io.h"
#include <stdio.h> #include <stdio.h>
#include "io.h"
uint8_t rom[ROM_SIZE] = {0}; uint8_t rom[ROM_SIZE] = {0};
void initRom(uint8_t *rom) { void initRom(uint8_t *rom) {
FILE *fp = fopen("/mnt/c/Users/llego/source/repos/6502PC/msbasic/tmp/kilian.bin", "rb"); FILE *fp = fopen("msbasic/tmp/kilian.bin", "rb");
if (!fp) { if (!fp) {
perror("fopen"); perror("fopen");
return; return;
} }
DIAG_PUSH();
DIAG_IGNORE("-Wunused-result");
fread(rom, 1, ROM_SIZE, fp); fread(rom, 1, ROM_SIZE, fp);
DIAG_POP();
if (ferror(fp)) { if (ferror(fp)) {
perror("fread"); perror("fread");
fclose(fp); fclose(fp);
@@ -22,8 +25,4 @@ void initRom(uint8_t *rom) {
} }
fclose(fp); fclose(fp);
/* Reset Vector, BASIC at DF02 */
//rom[0xFFFC - ROM_BASE] = 0x02; // Lower byte base of ROM
//rom[0xFFFD - ROM_BASE] = 0xDF; // Upper byte of base of ROM
} }