diff --git a/Cargo.lock b/Cargo.lock index 70ce33d..8db4c14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1953,7 +1953,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "shrooms-vb-native" +name = "shrooms-vb" version = "0.1.0" dependencies = [ "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 5ce4bf1..855efdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "shrooms-vb-native" +name = "shrooms-vb" version = "0.1.0" edition = "2021" @@ -24,3 +24,6 @@ winit = "0.30" [build-dependencies] cc = "1" + +[profile.release] +lto = true \ No newline at end of file diff --git a/README.md b/README.md index 35758eb..1f18a68 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # Shrooms VB (native) -An SDL-based implementation of shrooms-vb. +A native implementation of shrooms-vb. Written in Rust, using winit, wgpu, and Dear ImGui. Should run on any major OS. ## Setup Install the following dependencies: - - `gcc` (or MinGW on Windows) (or whatever, just set `CC`) - - `pkg-config` - - sdl2 + - `cargo` Run ```sh -make build -``` \ No newline at end of file +cargo build --release +``` + +The executable will be in `target/release/shrooms-vb[.exe]` \ No newline at end of file diff --git a/assets.h b/assets.h deleted file mode 100644 index 3d8d26d..0000000 --- a/assets.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef SHROOMS_VB_NATIVE_ASSETS_ -#define SHROOMS_VB_NATIVE_ASSETS_ - -#include - -extern const uint8_t _binary_assets_lefteye_bin_start; -const uint8_t *LEFT_EYE_DEFAULT = &_binary_assets_lefteye_bin_start; - -extern const uint8_t _binary_assets_righteye_bin_start; -const uint8_t *RIGHT_EYE_DEFAULT = &_binary_assets_righteye_bin_start; - -#endif diff --git a/assets/lefteye.bin b/assets/lefteye.bin deleted file mode 100644 index f17761d..0000000 Binary files a/assets/lefteye.bin and /dev/null differ diff --git a/assets/righteye.bin b/assets/righteye.bin deleted file mode 100644 index d323a3c..0000000 Binary files a/assets/righteye.bin and /dev/null differ diff --git a/audio.c b/audio.c deleted file mode 100644 index 169886e..0000000 --- a/audio.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include - -void audioCallback(void *userdata, uint8_t *stream, int len) { - AudioContext *aud; - SDL_assert(len == 834 * 4); - - aud = userdata; - if (!aud->filled) { - /* too little data, play silence */ - SDL_memset4(stream, 0, 834); - return; - } - SDL_memcpy4(stream, aud->buffers[aud->current], 834); - ++aud->current; - aud->current %= 2; - aud->filled -= 1; -} - -int audioInit(AudioContext *aud) { - SDL_AudioSpec spec; - spec.freq = 41700; - spec.format = AUDIO_S16; - spec.channels = 2; - spec.samples = 834; - spec.callback = &audioCallback; - spec.userdata = aud; - - aud->id = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0); - aud->paused = true; - if (!aud->id) { - fprintf(stderr, "could not open audio device: %s\n", SDL_GetError()); - return -1; - } - aud->current = 0; - aud->filled = 0; - return 0; -} - -int audioUpdate(AudioContext *aud, void *data, uint32_t bytes) { - int filled; - if (!aud->id) return -1; - SDL_assert(bytes == 834 * 4); - - SDL_LockAudioDevice(aud->id); - if (aud->filled < 2) { - int next = (aud->current + aud->filled) % 2; - SDL_memcpy4(aud->buffers[next], data, bytes / 4); - aud->filled += 1; - } - filled = aud->filled; - SDL_UnlockAudioDevice(aud->id); - - if (aud->paused) { - SDL_PauseAudioDevice(aud->id, false); - aud->paused = false; - } - - while (filled > 1) { - SDL_Delay(0); - filled = aud->filled; - } - - return 0; -} \ No newline at end of file diff --git a/audio.h b/audio.h deleted file mode 100644 index 644724f..0000000 --- a/audio.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef SHROOMS_VB_NATIVE_AUDIO_ -#define SHROOMS_VB_NATIVE_AUDIO_ - -#include -#include - -typedef struct { - SDL_AudioDeviceID id; - bool paused; - uint32_t buffers[2][834]; - int current; - int filled; -} AudioContext; - -int audioInit(AudioContext *aud); -int audioUpdate(AudioContext *aud, void *data, uint32_t bytes); - -#endif \ No newline at end of file diff --git a/cli.c b/cli.c deleted file mode 100644 index 7328a09..0000000 --- a/cli.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -int parseCLIArgs(int argc, char **argv, CLIArgs *args) { - if (argc != 2) { - fprintf(stderr, "usage: %s /path/to/rom.vb\n", argv[0]); - return 1; - } - args->filename = argv[1]; - return 0; -} \ No newline at end of file diff --git a/cli.h b/cli.h deleted file mode 100644 index 580265d..0000000 --- a/cli.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef SHROOMS_VB_NATIVE_CLI_ -#define SHROOMS_VB_NATIVE_CLI_ - -typedef struct { - char *filename; -} CLIArgs; - -int parseCLIArgs(int argc, char **argv, CLIArgs *args); - -#endif \ No newline at end of file diff --git a/controller.c b/controller.c deleted file mode 100644 index 54979a4..0000000 --- a/controller.c +++ /dev/null @@ -1,65 +0,0 @@ -#include - -#define VB_PWR 0x0001 -#define VB_SGN 0x0002 -#define VB_A 0x0004 -#define VB_B 0x0008 -#define VB_RT 0x0010 -#define VB_LT 0x0020 -#define VB_RU 0x0040 -#define VB_RR 0x0080 -#define VB_LR 0x0100 -#define VB_LL 0x0200 -#define VB_LD 0x0400 -#define VB_LU 0x0800 -#define VB_STA 0x1000 -#define VB_SEL 0x2000 -#define VB_RL 0x4000 -#define VB_RD 0x8000 - -static uint16_t symToMask(SDL_KeyCode sym) { - switch (sym) { - default: return 0; - case SDLK_a: - return VB_SEL; - case SDLK_s: - return VB_STA; - case SDLK_d: - return VB_B; - case SDLK_f: - return VB_A; - case SDLK_e: - return VB_LT; - case SDLK_r: - return VB_RT; - case SDLK_i: - return VB_RU; - case SDLK_j: - return VB_RL; - case SDLK_k: - return VB_RD; - case SDLK_l: - return VB_RR; - case SDLK_UP: - return VB_LU; - case SDLK_LEFT: - return VB_LL; - case SDLK_DOWN: - return VB_LD; - case SDLK_RIGHT: - return VB_LR; - } -} - -void ctrlInit(ControllerState *ctrl) { - ctrl->keys = VB_SGN; -} -void ctrlKeyDown(ControllerState *ctrl, SDL_Keycode sym) { - ctrl->keys |= symToMask(sym); -} -void ctrlKeyUp(ControllerState *ctrl, SDL_Keycode sym) { - ctrl->keys &= ~symToMask(sym); -} -uint16_t ctrlKeys(ControllerState *ctrl) { - return ctrl->keys; -} \ No newline at end of file diff --git a/controller.h b/controller.h deleted file mode 100644 index fe9dabe..0000000 --- a/controller.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SHROOMS_VB_NATIVE_CONTROLLER_ -#define SHROOMS_VB_NATIVE_CONTROLLER_ - -#include -#include - -typedef struct { - uint16_t keys; -} ControllerState; - -void ctrlInit(ControllerState *ctrl); -void ctrlKeyDown(ControllerState *ctrl, SDL_Keycode sym); -void ctrlKeyUp(ControllerState *ctrl, SDL_Keycode sym); -uint16_t ctrlKeys(ControllerState *ctrl); - -#endif \ No newline at end of file diff --git a/game.c b/game.c deleted file mode 100644 index 3461611..0000000 --- a/game.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - GraphicsContext *gfx; - AudioContext aud; - int16_t audioBuffer[834 * 2]; -} GameState; - -int onFrame(VB *sim) { - static uint8_t leftEye[384*224]; - static uint8_t rightEye[384*224]; - GameState *state; - void *samples; - uint32_t samplePairs; - - state = vbGetUserData(sim); - - vbGetPixels(sim, leftEye, 1, 384, rightEye, 1, 384); - gfxUpdateLeftEye(state->gfx, leftEye); - gfxUpdateRightEye(state->gfx, rightEye); - - samples = vbGetSamples(sim, NULL, NULL, &samplePairs); - audioUpdate(&state->aud, samples, samplePairs * 4); - vbSetSamples(sim, samples, VB_S16, 834); - gfxRender(state->gfx); - return 1; -} - -#define MAX_STEP_CLOCKS 20000000 - -int runGame(VB *sim, GraphicsContext *gfx) { - uint32_t clocks; - SDL_Event event; - GameState state; - ControllerState ctrl; - - state.gfx = gfx; - audioInit(&state.aud); - vbSetSamples(sim, &state.audioBuffer, VB_S16, 834); - vbSetUserData(sim, &state); - vbSetFrameCallback(sim, &onFrame); - - ctrlInit(&ctrl); - - gfxUpdateLeftEye(gfx, LEFT_EYE_DEFAULT); - gfxUpdateRightEye(gfx, RIGHT_EYE_DEFAULT); - - while (1) { - clocks = MAX_STEP_CLOCKS; - vbEmulate(sim, &clocks); - - while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { - return 0; - } - if (event.type == SDL_KEYDOWN) { - ctrlKeyDown(&ctrl, event.key.keysym.sym); - } - if (event.type == SDL_KEYUP) { - ctrlKeyUp(&ctrl, event.key.keysym.sym); - } - } - vbSetKeys(sim, ctrlKeys(&ctrl)); - } -} diff --git a/game.h b/game.h deleted file mode 100644 index 9984eea..0000000 --- a/game.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef SHROOMS_VB_NATIVE_GAME_ -#define SHROOMS_VB_NATIVE_GAME_ - -#include "graphics.h" -#include "shrooms-vb-core/core/vb.h" - -int runGame(VB *sim, GraphicsContext *gfx); - -#endif \ No newline at end of file diff --git a/graphics.c b/graphics.c deleted file mode 100644 index 9aa589c..0000000 --- a/graphics.c +++ /dev/null @@ -1,92 +0,0 @@ -#include - -static void copyScreenTexture(uint8_t *dst, const uint8_t *src, int pitch) { - int x, y, i; - uint8_t color; - int delta = pitch / 384; - for (y = 0; y < 224; ++y) { - for (x = 0; x < 384; x += 1) { - color = src[(y * 384) + x]; - for (i = 0; i < delta; ++i) { - dst[(y * pitch) + (x * delta) + i] = color; - } - } - } -} - -int gfxInit(GraphicsContext *gfx) { - gfx->window = SDL_CreateWindow("Shrooms VB", - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - 1536, 896, SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI); - if (!gfx->window) { - fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); - return 1; - } - - gfx->renderer = SDL_CreateRenderer(gfx->window, -1, 0); - if (!gfx->renderer) { - fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); - goto cleanup_window; - } - - gfx->winSurface = SDL_GetWindowSurface(gfx->window); - if (!gfx->winSurface) { - fprintf(stderr, "Error getting surface: %s\n", SDL_GetError()); - goto cleanup_window; - } - - gfx->leftEye = SDL_CreateTexture(gfx->renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, 384, 224); - if (!gfx->leftEye) { - fprintf(stderr, "Error creating left eye texture: %s\n", SDL_GetError()); - goto cleanup_window; - } - SDL_SetTextureColorMod(gfx->leftEye, 0xff, 0, 0); - - gfx->rightEye = SDL_CreateTexture(gfx->renderer, SDL_PIXELFORMAT_RGB24, SDL_TEXTUREACCESS_STREAMING, 384, 224); - if (!gfx->rightEye) { - fprintf(stderr, "Error creating left eye texture: %s\n", SDL_GetError()); - goto cleanup_left_eye; - } - SDL_SetTextureColorMod(gfx->rightEye, 0, 0xc6, 0xf0); - SDL_SetTextureBlendMode(gfx->rightEye, SDL_BLENDMODE_ADD); - - return 0; - -cleanup_left_eye: - SDL_DestroyTexture(gfx->leftEye); -cleanup_window: - SDL_DestroyWindow(gfx->window); - return 1; -} - -void gfxDestroy(GraphicsContext *gfx) { - SDL_DestroyTexture(gfx->rightEye); - SDL_DestroyTexture(gfx->leftEye); - SDL_DestroyWindow(gfx->window); -} - -static void gfxUpdateEye(SDL_Texture *eye, const uint8_t *bytes) { - void *target; - int pitch; - if (SDL_LockTexture(eye, NULL, &target, &pitch)) { - fprintf(stderr, "Error locking buffer for eye: %s\n", SDL_GetError()); - return; - } - copyScreenTexture(target, bytes, pitch); - SDL_UnlockTexture(eye); -} - -void gfxUpdateLeftEye(GraphicsContext *gfx, const uint8_t *bytes) { - gfxUpdateEye(gfx->leftEye, bytes); -} -void gfxUpdateRightEye(GraphicsContext *gfx, const uint8_t *bytes) { - gfxUpdateEye(gfx->rightEye, bytes); -} - -void gfxRender(GraphicsContext *gfx) { - SDL_RenderClear(gfx->renderer); - SDL_RenderCopy(gfx->renderer, gfx->leftEye, NULL, NULL); - SDL_RenderCopy(gfx->renderer, gfx->rightEye, NULL, NULL); - SDL_RenderPresent(gfx->renderer); -} - diff --git a/graphics.h b/graphics.h deleted file mode 100644 index aa4485b..0000000 --- a/graphics.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef SHROOMS_VB_NATIVE_GRAPHICS_ -#define SHROOMS_VB_NATIVE_GRAPHICS_ - -#include - -typedef struct { - SDL_Window *window; - SDL_Surface *winSurface; - SDL_Renderer *renderer; - SDL_Texture *leftEye; - SDL_Texture *rightEye; -} GraphicsContext; - -int gfxInit(GraphicsContext *gfx); -void gfxDestroy(GraphicsContext *gfx); - -void gfxUpdateLeftEye(GraphicsContext *gfx, const uint8_t *bytes); -void gfxUpdateRightEye(GraphicsContext *gfx, const uint8_t *bytes); - -void gfxRender(GraphicsContext *gfx); - -#endif diff --git a/main.c b/main.c deleted file mode 100644 index eb7eedf..0000000 --- a/main.c +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include -#include -#include "shrooms-vb-core/core/vb.h" -#include - -uint8_t *readROM(char *filename, uint32_t *size) { - FILE *file = fopen(filename, "rb"); - uint8_t *rom; - long filesize; - - if (!file) { - perror("could not open file"); - return NULL; - } - - if (fseek(file, 0, SEEK_END)) { - perror("could not seek file end"); - return NULL; - } - filesize = ftell(file); - if (filesize == -1) { - perror("could not read file size"); - return NULL; - } - if (fseek(file, 0, SEEK_SET)) { - perror("could not seek file start"); - return NULL; - } - - *size = (uint32_t) filesize; - rom = malloc(*size); - if (!rom) { - perror("could not allocate ROM"); - return NULL; - } - fread(rom, 1, *size, file); - if (ferror(file)) { - perror("could not read file"); - return NULL; - } - if (fclose(file)) { - perror("could not close file"); - return NULL; - } - - return rom; -} - -int main(int argc, char **argv) { - VB *sim; - uint8_t *rom; - uint32_t romSize; - GraphicsContext gfx; - CLIArgs args; - int status; - - if (parseCLIArgs(argc, argv, &args)) { - return 1; - } - - rom = readROM(args.filename, &romSize); - if (!rom) { - return 1; - } - - sim = malloc(vbSizeOf()); - vbInit(sim); - vbSetCartROM(sim, rom, romSize); - - if (SDL_Init(SDL_INIT_EVERYTHING)) { - fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); - return 1; - } - - if (gfxInit(&gfx)) { - SDL_Quit(); - return 1; - } - - status = runGame(sim, &gfx); - SDL_Quit(); - return status; -} diff --git a/makefile b/makefile deleted file mode 100644 index 71115dc..0000000 --- a/makefile +++ /dev/null @@ -1,48 +0,0 @@ -CC?=gcc -LD?=ld -SHROOMSFLAGS=shrooms-vb-core/core/vb.c -I shrooms-vb-core/core -msys_version := $(if $(findstring Msys, $(shell uname -o)),$(word 1, $(subst ., ,$(shell uname -r))),0) - -ifeq ($(msys_version), 0) -SDL2FLAGS=$(shell pkg-config sdl2 --cflags --libs) -BINLINKFLAGS=-z noexecstack -else -SDL2FLAGS=$(shell pkg-config sdl2 --cflags --libs) -mwindows -mconsole -BINLINKFLAGS= -endif - -.PHONY: clean build -clean: - @rm -rf shrooms-vb output - -CFILES := $(foreach dir,./,$(notdir $(wildcard $(dir)/*.c))) -BINFILES := $(foreach dir,assets/,$(notdir $(wildcard $(dir)/*.bin))) - -COBJS := $(CFILES:%.c=output/%.o) -SHROOMSOBJS := output/vb.o -BINOBJS := $(BINFILES:%.bin=output/%.o) - -OFILES := $(COBJS) $(SHROOMSOBJS) $(BINOBJS) - -output/%.o: %.c - @mkdir -p output - @$(CC) -c -o $@ $< -I . \ - -I shrooms-vb-core/core $(SDL2FLAGS) \ - -O3 -flto -fno-strict-aliasing \ - -Werror -std=c90 -Wall -Wextra -Wpedantic - -output/vb.o: shrooms-vb-core/core/vb.c - @mkdir -p output - @$(CC) -c -o $@ $< -I . \ - -I shrooms-vb-core/core $(SDL2FLAGS) \ - -O3 -flto -fno-strict-aliasing \ - -Werror -std=c90 -Wall -Wextra -Wpedantic - -output/%.o: assets/%.bin - @mkdir -p output - @$(LD) -r -b binary $(BINLINKFLAGS) -o $@ $< - -shrooms-vb: $(OFILES) - @$(CC) -o $@ $(OFILES) $(SDL2FLAGS) -flto - -build: shrooms-vb \ No newline at end of file