dawnos is cool and i like to write emulators so i wrote a shoddy emulator!!!
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <byteswap.h>
#include <SDL.h>
#define MEMSIZE (512 * 1024 * 1024)
#define CPU0FLAGS 0x13EE0000
#define CPU0PC 0x13EE0008
#define CPU_RUNNING 1
#define CPU_STOP_REQUESTED 2
#define CPU_STOPPED 4
#define DISPLAY_LOC (256 * 1024 * 1024)
#define DISPLAY_ON 0x13FFEFB0
#define TIMER 0x13FFFFF0
#define MOUSE_X 0x13FFF7D0
#define MOUSE_Y 0x13FFF7D8
#define MOUSE_BUTTON(v) (0x13FFF7A0 + (v == 3 ? 1 : v == 2 ? 2 : 0) * 8)
#define KEYBOARD 0x13FFF7F0
static void *mem;
static uint64_t mread(uint64_t off)
{
return __bswap_64(*(uint64_t *)(mem + off));
}
static void mwrite(uint64_t val, uint64_t off)
{
*(uint64_t *)(mem + off) = __bswap_64(val);
}
static void mouse_motion(int x, int y)
{
mwrite((double)x / (double)1024 * (double)((uint64_t)1 << 32), MOUSE_X);
mwrite((double)y / (double)512 * (double)((uint64_t)1 << 32), MOUSE_Y);
}
static void mouse_button(int which, int state)
{
mwrite(state, MOUSE_BUTTON(which));
}
static int key_convert(int code)
{
switch (code)
{
case SDLK_BACKSPACE: return 9;
case SDLK_RETURN: return 13;
case SDLK_UP: return 14;
case SDLK_LEFT: return 15;
case SDLK_DOWN: return 16;
case SDLK_RIGHT: return 17;
case SDLK_ESCAPE: return 27;
default: return code;
}
}
static void key_down(int code)
{
mwrite(key_convert(code), KEYBOARD);
}
static uint64_t cpu0pc;
static void cpu0(void)
{
uint64_t restore = cpu0pc;
uint64_t a_addr = mread(cpu0pc);
uint64_t b_addr = mread(cpu0pc + 8);
cpu0pc = mread(cpu0pc + 16);
int64_t s = (int64_t)mread(b_addr) - (int64_t)mread(a_addr);
mwrite(s, b_addr);
if (s > 0) cpu0pc = restore + 24;
}
int main(int argc, char *argv[])
{
if (argc < 2) return 1;
FILE *f = fopen(argv[1], "rb");
if (!f) return 1;
mem = malloc(MEMSIZE);
if (!mem) return 1;
memset(mem, 0, MEMSIZE);
memset(mem + MEMSIZE - 4096, 255, 4096);
if (!fread(mem, 1, MEMSIZE, f)) return 1;
fclose(f);
if (SDL_Init(SDL_INIT_VIDEO)) return 1;
SDL_Window *window = SDL_CreateWindow("SUBLEQ1", 0, 0, 1024, 512, 0);
if (!window) goto die1;
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
if (!renderer) goto die2;
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, 1024, 512);
if (!texture) goto die3;
cpu0pc = mread(CPU0PC);
mwrite(CPU_RUNNING, CPU0FLAGS);
SDL_Event e;
uint64_t t = SDL_GetTicks64();
for (;;)
{
while (SDL_PollEvent(&e) != 0)
{
switch (e.type)
{
case SDL_QUIT: goto die2;
case SDL_MOUSEMOTION: mouse_motion(e.motion.x, e.motion.y); break;
case SDL_MOUSEBUTTONUP: mouse_button(e.button.button, 0); break;
case SDL_MOUSEBUTTONDOWN: mouse_button(e.button.button, 1); break;
case SDL_KEYDOWN: key_down(e.key.keysym.sym); break;
}
}
while (SDL_GetTicks64() < t + 32)
{
for (int i = 0; i < 1024; i++) cpu0();
}
t = SDL_GetTicks64();
mwrite((uint64_t)((double)t / (double)1000 * (double)((uint64_t)1 << 32)), TIMER);
uint64_t on = mread(DISPLAY_ON);
if (on == 0)
{
SDL_UpdateTexture(texture, NULL, mem + DISPLAY_LOC, 1024 * 3);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
}
}
die3:
SDL_DestroyTexture(texture);
die2:
SDL_DestroyRenderer(renderer);
die1:
SDL_DestroyWindow(window);
SDL_Quit();
}
it had multicore at some point but it kept race conditioning on memory access and didnt really make it faster (atleast on my craptop) so i scrapped it
BYE!!!