diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/CrocParty.iml b/.idea/CrocParty.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/CrocParty.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..5eaf15e
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..675c11c
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..f9de7b7
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,15 @@
+cmake_minimum_required(VERSION 3.27)
+project(CrocParty C)
+
+set(CMAKE_C_STANDARD 11)
+
+add_subdirectory(vendored/sdl EXCLUDE_FROM_ALL)
+add_executable(CrocParty main.c
+ sdl_host.c
+ sdl_host.h
+ game.c
+ game.h
+ device.c
+ device.h
+)
+target_link_libraries(CrocParty PRIVATE SDL2::SDL2-static)
diff --git a/device.c b/device.c
new file mode 100644
index 0000000..d29db0c
--- /dev/null
+++ b/device.c
@@ -0,0 +1,3 @@
+#include "device.h"
+
+uint32_t device_pixels[DEVICE_H][DEVICE_W];
diff --git a/device.h b/device.h
new file mode 100644
index 0000000..61b7872
--- /dev/null
+++ b/device.h
@@ -0,0 +1,12 @@
+#ifndef CROCPARTY_DEVICE_H
+#define CROCPARTY_DEVICE_H
+
+#include
+
+// 240 x 135 is also cool
+#define DEVICE_W 128
+#define DEVICE_H 128
+
+extern uint32_t device_pixels[DEVICE_H][DEVICE_W];
+
+#endif //CROCPARTY_DEVICE_H
diff --git a/game.c b/game.c
new file mode 100644
index 0000000..9b9c065
--- /dev/null
+++ b/game.c
@@ -0,0 +1,29 @@
+#include "device.h"
+#include "game.h"
+
+uint32_t game_frame;
+
+void game_init() {
+ game_frame = 0;
+}
+
+void game_update() {
+ game_frame += 1;
+}
+
+void game_draw() {
+ for (int x = 0; x < DEVICE_W; x++) {
+ for (int y = 0; y < DEVICE_H; y++) {
+ uint32_t r = (x * 255)/DEVICE_W;
+ uint32_t g = (y * 255)/DEVICE_H;
+ uint32_t b = game_frame & 0xff;
+ if (x % 4 == 2 && y % 4 == 2) {
+ r = 255 - r;
+ g = 255 - g;
+ b = 255 - b;
+ }
+ uint32_t color = r << 24 | g << 16 | b << 8;
+ device_pixels[y][x] = color;
+ }
+ }
+}
diff --git a/game.h b/game.h
new file mode 100644
index 0000000..f4c7b99
--- /dev/null
+++ b/game.h
@@ -0,0 +1,8 @@
+#ifndef CROCPARTY_GAME_H
+#define CROCPARTY_GAME_H
+
+void game_init();
+void game_update();
+void game_draw();
+
+#endif //CROCPARTY_GAME_H
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..7f4fdad
--- /dev/null
+++ b/main.c
@@ -0,0 +1,9 @@
+#include "sdl_host.h"
+
+int main() {
+ // PYREX NOTE: You could, if you wanted, define another host with the same interface as sdl_host
+ // That would be pretty cool, right?
+ //
+ // (Such a host might be smaller and more platform-specific.)
+ return sdl_host_main();
+}
diff --git a/sdl_host.c b/sdl_host.c
new file mode 100644
index 0000000..cdb5f45
--- /dev/null
+++ b/sdl_host.c
@@ -0,0 +1,147 @@
+#include
+#include
+
+#include "sdl_host.h"
+#include "vendored/sdl/include/SDL.h"
+#include "game.h"
+#include "device.h"
+
+void sdl_host_suggest_dimensions(uint32_t* window_w, uint32_t* window_h);
+void sdl_host_loop();
+
+SDL_Window* sdl_host_window;
+SDL_Renderer* sdl_host_renderer;
+SDL_Texture* sdl_host_target;
+
+int sdl_host_main(void) {
+ int result = 0;
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {
+ printf("could not initialize SDL! sdl error: %s\n", SDL_GetError());
+ result = 1;
+ goto sdl_done;
+ }
+
+ uint32_t window_w, window_h;
+ sdl_host_suggest_dimensions(&window_w, &window_h);
+
+ // create window
+ sdl_host_window = SDL_CreateWindow(
+ "Croc Party!",
+ SDL_WINDOWPOS_CENTERED,
+ SDL_WINDOWPOS_CENTERED,
+ (int) window_w, (int) window_h,
+ SDL_WINDOW_SHOWN
+ );
+
+ if (sdl_host_window == NULL) {
+ printf("could not load window! sdl error: %s\n", SDL_GetError());
+ result = 1;
+ goto window_done;
+ }
+
+ // create renderer
+ sdl_host_renderer = SDL_CreateRenderer(sdl_host_window, -1, 0);
+ if (sdl_host_renderer == NULL) {
+ result = 1;
+ goto renderer_done;
+ }
+
+ // create target
+ sdl_host_target = SDL_CreateTexture(
+ sdl_host_renderer,
+ SDL_PIXELFORMAT_RGBA8888,
+ SDL_TEXTUREACCESS_STREAMING,
+ DEVICE_W, DEVICE_H
+ );
+
+ if (sdl_host_target == NULL) {
+ printf("could not create target texture! sdl error: %s\n", SDL_GetError());
+ result = 1;
+ goto target_done;
+ }
+
+ sdl_host_loop();
+
+ // renderer_cleanup:
+ SDL_DestroyRenderer(sdl_host_renderer);
+ sdl_host_renderer = NULL;
+ renderer_done: ;
+
+ // target_cleanup:
+ SDL_DestroyTexture(sdl_host_target);
+ sdl_host_target = NULL;
+ target_done: ;
+
+ // window_cleanup:
+ SDL_DestroyWindow(sdl_host_window);
+ sdl_host_window = NULL;
+ window_done: ;
+
+ // sdl_cleanup:
+ SDL_Quit();
+ sdl_done: ;
+
+ return result;
+}
+
+void sdl_host_suggest_dimensions(uint32_t* window_w, uint32_t* window_h) {
+ SDL_DisplayMode dm;
+ if (SDL_GetCurrentDisplayMode(0, &dm) != 0) {
+ printf("could not get current display mode: %s\n", SDL_GetError());
+ dm.w = 0;
+ dm.h = 0;
+ }
+
+ for (int scalar = 5; scalar >= 1; scalar--) {
+ uint32_t w = DEVICE_W * scalar;
+ uint32_t h = DEVICE_H * scalar;
+ if (w <= dm.w && h <= dm.h) {
+ *window_w = w;
+ *window_h = h;
+ return;
+ }
+ }
+
+ for (int scalar = 1; scalar <= 5; scalar++) {
+ uint32_t w = DEVICE_W / scalar;
+ uint32_t h = DEVICE_H / scalar;
+ if (w <= dm.w && h <= dm.h) {
+ *window_w = w;
+ *window_h = h;
+ return;
+ }
+ }
+
+ *window_w = DEVICE_W;
+ *window_h = DEVICE_H;
+}
+
+void sdl_host_loop() {
+ uint32_t ticks_per_frame = 1000/60;
+
+ game_init();
+ while (true) {
+ uint32_t frame_start = SDL_GetTicks();
+ uint32_t next_frame_start = frame_start + ticks_per_frame;
+
+ SDL_Event e;
+ while (SDL_PollEvent(&e)) {
+ if (e.type == SDL_QUIT) { goto quit; }
+ }
+
+ // trigger game logic
+ game_update();
+ game_draw();
+
+ SDL_UpdateTexture(sdl_host_target, NULL, &device_pixels, sizeof(device_pixels[0]));
+ SDL_RenderClear(sdl_host_renderer);
+ SDL_RenderCopy(sdl_host_renderer, sdl_host_target, NULL, NULL);
+ SDL_RenderPresent(sdl_host_renderer);
+
+ // hold off until next frame
+ while (SDL_GetTicks() < next_frame_start) {
+ SDL_Delay(1);
+ }
+ }
+ quit: ;
+}
\ No newline at end of file
diff --git a/sdl_host.h b/sdl_host.h
new file mode 100644
index 0000000..4b5bec9
--- /dev/null
+++ b/sdl_host.h
@@ -0,0 +1,6 @@
+#ifndef CROCPARTY_SDL_HOST_H
+#define CROCPARTY_SDL_HOST_H
+
+int sdl_host_main(void);
+
+#endif //CROCPARTY_SDL_HOST_H