Some changes
This commit is contained in:
144
main.c
144
main.c
@@ -1,11 +1,13 @@
|
||||
#include <SDL2/SDL.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
#include "util/font.h"
|
||||
#include "assembler/assembler.h"
|
||||
#include "util/texteditor.h"
|
||||
#include "util/hexdump.h"
|
||||
#include "util/cpustatusui.h"
|
||||
#include "peripherals/peripheraldata.h"
|
||||
|
||||
//Screen dimension constants
|
||||
const int SCREEN_WIDTH = 1280;
|
||||
@@ -13,8 +15,11 @@ const int SCREEN_HEIGHT = 720;
|
||||
const int targetFPS = 60;
|
||||
const int delayNeeded = 1000 / targetFPS;
|
||||
|
||||
#define TARGET_CYCLE_TIME_NS 15625 // 15.625 µs per cycle for 64 kHz
|
||||
|
||||
//The window we'll be rendering to
|
||||
SDL_Window *window = NULL;
|
||||
volatile bool running = true;
|
||||
|
||||
//The surface contained by the window
|
||||
SDL_Renderer *renderer = NULL;
|
||||
@@ -44,6 +49,71 @@ TextEditor editors[editorCount];
|
||||
unsigned long frames = 0;
|
||||
bool cursor = true;
|
||||
|
||||
pthread_t cpu_thread;
|
||||
pthread_mutex_t cpu_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void msleep(unsigned int milliseconds) {
|
||||
struct timespec ts;
|
||||
ts.tv_sec = milliseconds / 1000;
|
||||
ts.tv_nsec = (milliseconds % 1000) * 1000000;
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
void *cpu_loop(void *arg) {
|
||||
uint64_t last_tick = SDL_GetTicks64();
|
||||
uint64_t last_speed_check = last_tick;;
|
||||
uint64_t step_count = 0;
|
||||
struct timespec start, end, sleep_time;
|
||||
while (running) {
|
||||
pthread_mutex_lock(&cpu_mutex);
|
||||
|
||||
if (!(cpu.mode & (CPU_MODE_PAUSED | CPU_MODE_HALTED | CPU_MODE_ERROR))) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &start); // Get start time
|
||||
step(&cpu);
|
||||
clock_gettime(CLOCK_MONOTONIC, &end); // Get end time
|
||||
// Compute step duration in nanoseconds
|
||||
uint64_t step_duration_ns = (end.tv_sec - start.tv_sec) * 1000000000ULL +
|
||||
(end.tv_nsec - start.tv_nsec);
|
||||
|
||||
// Compute remaining time to maintain 64 kHz
|
||||
if (step_duration_ns < TARGET_CYCLE_TIME_NS) {
|
||||
uint64_t remaining_ns = TARGET_CYCLE_TIME_NS - step_duration_ns;
|
||||
sleep_time.tv_sec = 0;
|
||||
sleep_time.tv_nsec = remaining_ns;
|
||||
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &sleep_time, NULL);
|
||||
}
|
||||
|
||||
step_count++;
|
||||
} else {
|
||||
pthread_mutex_unlock(&cpu_mutex);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
if (cpu.mode & CPU_MODE_SECOND) {
|
||||
pthread_mutex_unlock(&cpu_mutex);
|
||||
msleep(1000);
|
||||
continue;
|
||||
} else if (cpu.mode & CPU_MODE_FRAME) {
|
||||
uint64_t frame_duration = SDL_GetTicks64() - last_tick;
|
||||
if (frame_duration < delayNeeded) {
|
||||
pthread_mutex_unlock(&cpu_mutex);
|
||||
msleep(delayNeeded - frame_duration);
|
||||
continue;
|
||||
}
|
||||
last_tick = SDL_GetTicks64();
|
||||
}
|
||||
// Print speed every second
|
||||
uint64_t now = SDL_GetTicks64();
|
||||
if (now - last_speed_check >= 1000) {
|
||||
printf("CPU Max Speed: %lu Hz\n", step_count);
|
||||
step_count = 0;
|
||||
last_speed_check = now;
|
||||
}
|
||||
pthread_mutex_unlock(&cpu_mutex);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *read_file_as_string(const char *filename) {
|
||||
FILE *file = fopen(filename, "rb"); // Open file in binary mode
|
||||
if (file == NULL) {
|
||||
@@ -91,7 +161,10 @@ void compile(bool erase) {
|
||||
|
||||
int init() {
|
||||
//Initialize SDL
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, NULL);
|
||||
SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1");
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
|
||||
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
|
||||
return 1;
|
||||
}
|
||||
@@ -116,6 +189,24 @@ int init() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&audioData, 0, sizeof(AudioData));
|
||||
|
||||
SDL_AudioSpec spec = {0};
|
||||
spec.freq = SAMPLE_RATE;
|
||||
spec.format = AUDIO_F32SYS;
|
||||
spec.channels = 1;
|
||||
spec.samples = 4096;
|
||||
spec.callback = audio_callback;
|
||||
spec.userdata = &audioData;
|
||||
|
||||
SDL_AudioDeviceID dev = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0);
|
||||
if (dev == 0) {
|
||||
printf("Failed to open audio: %s\n", SDL_GetError());
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
SDL_PauseAudioDevice(dev, 0);
|
||||
|
||||
SDL_Rect viewport = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT};
|
||||
SDL_RenderSetViewport(renderer, &viewport);
|
||||
|
||||
@@ -126,7 +217,6 @@ int init() {
|
||||
init_editor(&codeEditor, &smallFont, 10, 80, renderer, 35, 1000, 48, false);
|
||||
init_editor(&memoryViewer, &smallerFont, 738, 80, renderer, 59, MEM_SIZE / 16 + 2, 70, true);
|
||||
SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, NULL);
|
||||
for (int i = 0; i < editorCount; i++) {
|
||||
generate_string_display(&codeEditor, renderer);
|
||||
}
|
||||
@@ -150,18 +240,22 @@ int render() {
|
||||
rect2.w = 0;
|
||||
rect2.h = 0;
|
||||
|
||||
SDL_QueryTexture(cpuStatsTexture, NULL, NULL, &rect2.w, &rect2.h);
|
||||
if (cpuStatsTexture) {
|
||||
SDL_QueryTexture(cpuStatsTexture, NULL, NULL, &rect2.w, &rect2.h);
|
||||
|
||||
SDL_RenderCopy(renderer, cpuStatsTexture, NULL, &rect2);
|
||||
SDL_RenderCopy(renderer, cpuStatsTexture, NULL, &rect2);
|
||||
}
|
||||
|
||||
rect2.x = 100;
|
||||
rect2.y = 46;
|
||||
rect2.w = 0;
|
||||
rect2.h = 0;
|
||||
|
||||
SDL_QueryTexture(cpuStateTexture, NULL, NULL, &rect2.w, &rect2.h);
|
||||
if (cpuStateTexture) {
|
||||
SDL_QueryTexture(cpuStateTexture, NULL, NULL, &rect2.w, &rect2.h);
|
||||
|
||||
SDL_RenderCopy(renderer, cpuStateTexture, NULL, &rect2);
|
||||
SDL_RenderCopy(renderer, cpuStateTexture, NULL, &rect2);
|
||||
}
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
frames++;
|
||||
@@ -289,6 +383,11 @@ int processEvent(SDL_Event e) {
|
||||
int newWidth = e.window.data1;
|
||||
int newHeight = e.window.data2;
|
||||
|
||||
for (int editorIndex = 0; editorIndex < editorCount; editorIndex++) {
|
||||
generate_string_display(&editors[editorIndex], renderer);
|
||||
}
|
||||
updateState(true);
|
||||
|
||||
// Adjust the viewport to match the new window size;
|
||||
SDL_Rect viewport = {0, 0, newWidth, newHeight};
|
||||
SDL_RenderSetViewport(renderer, &viewport);
|
||||
@@ -346,11 +445,18 @@ int processEvent(SDL_Event e) {
|
||||
updateState(false);
|
||||
return 1;
|
||||
case SDLK_F8:
|
||||
if (++cpuSpeedTemp == 3) {
|
||||
cpuSpeedTemp = 0;
|
||||
if (cpu.mode & CPU_MODE_STEP) {
|
||||
cpu.mode &= ~CPU_MODE_STEP;
|
||||
cpu.mode |= CPU_MODE_SECOND;
|
||||
} else if (cpu.mode & CPU_MODE_SECOND) {
|
||||
cpu.mode &= ~CPU_MODE_SECOND;
|
||||
cpu.mode |= CPU_MODE_FRAME;
|
||||
} else if (cpu.mode & CPU_MODE_FRAME) {
|
||||
cpu.mode &= ~CPU_MODE_FRAME;
|
||||
// No specific mode set, defaults to none
|
||||
} else {
|
||||
cpu.mode |= CPU_MODE_STEP; // Restart cycle
|
||||
}
|
||||
cpu.mode &= ~(CPU_MODE_SECOND | CPU_MODE_STEP);
|
||||
cpu.mode |= cpuSpeedTemp << 4;
|
||||
updateState(false);
|
||||
return 1;
|
||||
case SDLK_F5:
|
||||
@@ -367,6 +473,7 @@ int processEvent(SDL_Event e) {
|
||||
cpu.mode |= CPU_MODE_PAUSED;
|
||||
if (keyMod & (KMOD_CTRL | KMOD_SHIFT)) {
|
||||
cpu.mode |= CPU_MODE_HALTED;
|
||||
cpu.pc = 0;
|
||||
}
|
||||
updateState(false);
|
||||
break;
|
||||
@@ -376,10 +483,16 @@ int processEvent(SDL_Event e) {
|
||||
FILE *fptr;
|
||||
char fname[20];
|
||||
snprintf(fname, sizeof(fname), "riscb%lu.bsm", time(NULL));
|
||||
fptr = fopen(fname, "w");
|
||||
fptr = fopen(fname, "wb");
|
||||
generate_string(&editors[0]);
|
||||
fputs(editors[0].outputString, fptr);
|
||||
fclose(fptr);
|
||||
if (keyMod & KMOD_SHIFT) {
|
||||
snprintf(fname, sizeof(fname), "riscb%lu.mem", time(NULL));
|
||||
fptr = fopen(fname, "wb");
|
||||
fwrite(cpu.memory, sizeof(cpu.memory[0]), MEM_SIZE, fptr);
|
||||
fclose(fptr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
@@ -391,7 +504,7 @@ int processEvent(SDL_Event e) {
|
||||
sscanf(editors[0].lines[editors[0].cursor_line].text, "%s", fname);
|
||||
toLowerCase(fname);
|
||||
strcat(fname, ".bsm");
|
||||
fptr = fopen(fname, "r");
|
||||
fptr = fopen(fname, "rb");
|
||||
if (fptr) {
|
||||
char *prog = read_file_as_string(fname);
|
||||
toUpperCase(prog);
|
||||
@@ -465,11 +578,12 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[])
|
||||
|
||||
//Hack to get window to stay up
|
||||
SDL_Event e;
|
||||
bool running = true;
|
||||
Uint64 start;
|
||||
Uint64 end;
|
||||
pthread_create(&cpu_thread, NULL, cpu_loop, NULL);
|
||||
while (running) {
|
||||
start = SDL_GetTicks64();
|
||||
pthread_mutex_lock(&cpu_mutex);
|
||||
while (SDL_PollEvent(&e)) {
|
||||
running = processEvent(e);
|
||||
}
|
||||
@@ -495,12 +609,11 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[])
|
||||
updateState(false);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&cpu_mutex);
|
||||
end = SDL_GetTicks64();
|
||||
const unsigned long timeNeeded = end - start;
|
||||
if (timeNeeded < delayNeeded) {
|
||||
SDL_Delay(delayNeeded - timeNeeded);
|
||||
} else {
|
||||
printf("%lu\n", timeNeeded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,6 +630,7 @@ int main(__attribute__((unused)) int argc, __attribute__((unused)) char *args[])
|
||||
if (cpuStatsTexture) SDL_DestroyTexture(cpuStatsTexture);
|
||||
if (cpuStateTexture) SDL_DestroyTexture(cpuStateTexture);
|
||||
|
||||
pthread_join(cpu_thread, NULL);
|
||||
if (renderer) SDL_DestroyRenderer(renderer);
|
||||
if (window) SDL_DestroyWindow(window);
|
||||
|
||||
|
Reference in New Issue
Block a user