From 8df808ea763530e391112406a047b187f395aa7c Mon Sep 17 00:00:00 2001 From: Rezmason Date: Sun, 5 Jun 2022 23:19:03 -0700 Subject: [PATCH] Began work on the C port. To my knowledge, everything is working except the graphics code. The C API doesn't include bitmap compositing functions out-of-the-box. --- playdate/matrix_c/CMakeLists.txt | 43 +++ .../matrix_c/Source/images/fade-gradient.png | Bin 0 -> 2853 bytes .../matrix_c/Source/images/matrix-glyphs.png | Bin 0 -> 17408 bytes playdate/matrix_c/main.c | 288 ++++++++++++++++++ playdate/matrix_c/pdxinfo | 8 + 5 files changed, 339 insertions(+) create mode 100644 playdate/matrix_c/CMakeLists.txt create mode 100644 playdate/matrix_c/Source/images/fade-gradient.png create mode 100644 playdate/matrix_c/Source/images/matrix-glyphs.png create mode 100644 playdate/matrix_c/main.c create mode 100644 playdate/matrix_c/pdxinfo diff --git a/playdate/matrix_c/CMakeLists.txt b/playdate/matrix_c/CMakeLists.txt new file mode 100644 index 0000000..69dca7b --- /dev/null +++ b/playdate/matrix_c/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.14) +set(CMAKE_C_STANDARD 11) + +set(ENVSDK $ENV{PLAYDATE_SDK_PATH}) + +if (NOT ${ENVSDK} STREQUAL "") + # Convert path from Windows + file(TO_CMAKE_PATH ${ENVSDK} SDK) +else() + execute_process( + COMMAND bash -c "egrep '^\\s*SDKRoot' $HOME/.Playdate/config" + COMMAND head -n 1 + COMMAND cut -c9- + OUTPUT_VARIABLE SDK + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() + +if (NOT EXISTS ${SDK}) + message(FATAL_ERROR "SDK Path not found; set ENV value PLAYDATE_SDK_PATH") + return() +endif() + +set(CMAKE_CONFIGURATION_TYPES "Debug;Release") +set(CMAKE_XCODE_GENERATE_SCHEME TRUE) + +# Game Name Customization +set(PLAYDATE_GAME_NAME ThePlaytrix) +set(PLAYDATE_GAME_DEVICE ThePlaytrix_DEVICE) + +project(${PLAYDATE_GAME_NAME} C ASM) + +file(GLOB IMAGES + "Source/images/*" +) + +if (TOOLCHAIN STREQUAL "armgcc") + add_executable(${PLAYDATE_GAME_DEVICE} ${SDK}/C_API/buildsupport/setup.c main.c) +else() + add_library(${PLAYDATE_GAME_NAME} SHARED main.c ${IMAGES}) +endif() + +include(${SDK}/C_API/buildsupport/playdate_game.cmake) diff --git a/playdate/matrix_c/Source/images/fade-gradient.png b/playdate/matrix_c/Source/images/fade-gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..7c8f97fd9f38a1dc6431889f3e84f8fe6553ba9d GIT binary patch literal 2853 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 S6R1Gxeq`BRTxN+!XzK66h=7X# literal 0 HcmV?d00001 diff --git a/playdate/matrix_c/Source/images/matrix-glyphs.png b/playdate/matrix_c/Source/images/matrix-glyphs.png new file mode 100644 index 0000000000000000000000000000000000000000..b328c0822fc94f4727a3332c0daefc39e0e2422a GIT binary patch literal 17408 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 +#include +#include + +#include "pd_api.h" + +typedef struct { + int x; + int y; + int fadeIndex; + int glyphIndex; + float glyphCycle; + float columnSpeedOffset; + float columnTimeOffset; +} Cell; + +typedef struct { + int width; + int height; + int rowBytes; + int hasMask; + uint8_t *data; +} BitmapView; + +static PlaydateAPI* pd = NULL; + +static const int glyphWidth = 20; +static int numColumns; +static int numRows; +static int numCells; + +static const int numGlyphs = 133; +static const int numFades = 32; + +static const float minSpeed = 0.15; +static const float maxSpeed = 1; +static float time = 0; +static float speed = maxSpeed; + +static float sineTable[360]; +static float wobbleA; +static float wobbleB; + +static LCDBitmap **glyphs = NULL; +static Cell *cells = NULL; + +static float randf() { + return (float)rand() / (float)(RAND_MAX); +} + +static BitmapView* getBitmapView(LCDBitmap *bitmap) +{ + BitmapView *bv = pd->system->realloc(NULL, sizeof(BitmapView)); + pd->graphics->getBitmapData( + bitmap, + &(bv->width), + &(bv->height), + &(bv->rowBytes), + &(bv->hasMask), + &(bv->data) + ); + + return bv; +} + +static void freeBitmapView(BitmapView *bv) +{ + pd->system->realloc(bv, 0); +} + +static void logBitmapViewToConsole(BitmapView *bv) +{ + pd->system->logToConsole("bitmap: %i x %i %s", bv->width, bv->height, bv->hasMask ? "transparent" : ""); + + int dataSize = bv->rowBytes * bv->height; + + { + char line[bv->rowBytes * 8 + 1]; + for (int l = 0; l < bv->width; l++) { + line[l] = (l % 8 == 0) ? '|' : '_'; + } + for (int l = bv->width; l < bv->rowBytes * 8; l++) { + line[l] = 'x'; + } + line[bv->rowBytes * 8] = '\0'; + + pd->system->logToConsole("+%s+", line); + } + + int i = 0; + for (int y = 0; y < bv->height; y++) { + + char line[bv->rowBytes * 8 + 1]; + for (int l = 0; l < bv->rowBytes * 8; l++) { + line[l] = ' '; + } + line[bv->rowBytes * 8] = '\0'; + + int l = 0; + for (int x = 0; x < bv->rowBytes; x++) { + int byte = bv->data[i]; + int maskByte = bv->hasMask ? bv->data[i + dataSize] : 0xFF; + for (int j = 0; j < 8; j++) { + int bit = (byte >> (7 - j)) & 1; + int maskBit = (maskByte >> (7 - j)) & 1; + if (maskBit) { + line[l] = bit ? '#' : '.'; + } else { + line[l] = bit ? '?' : ' '; + } + l++; + } + i++; + } + + pd->system->logToConsole("[%s]", line); + } +} + +static void init() +{ + srand(pd->system->getSecondsSinceEpoch(NULL)); + + wobbleA = sqrt(2) / 50; + wobbleB = sqrt(5) / 50; + + int screenWidth = pd->display->getWidth(); + int screenHeight = pd->display->getHeight(); + numColumns = screenWidth / glyphWidth; + numRows = screenHeight / glyphWidth; + numCells = numColumns * numRows; + + for (int i = 0; i < 360; i++) + { + sineTable[i] = sin(M_PI / 180 * i); + } + + const char *outErr = NULL; + LCDBitmap *glyphSpritesheet = pd->graphics->loadBitmap("images/matrix-glyphs", &outErr); + BitmapView *glyphSpritesheetBV = getBitmapView(glyphSpritesheet); + + int spritesheetColumns = floor(glyphSpritesheetBV->width / glyphWidth); + + LCDBitmap *fadeGradient = pd->graphics->loadBitmap("images/fade-gradient", &outErr); + BitmapView *fadeGradientBV = getBitmapView(fadeGradient); + + glyphs = pd->system->realloc(NULL, sizeof(LCDBitmap *) * numGlyphs * numFades); + + LCDBitmap *glyph = pd->graphics->newBitmap(glyphWidth, glyphWidth, kColorBlack); + + for (int i = 0; i < numGlyphs; i++) { + int column = i % spritesheetColumns; + int row = i / spritesheetColumns; + /* + pd->graphics.lockFocus(glyph) + glyphSpritesheet:draw(-column * glyphWidth, -row * glyphWidth) + pd->graphics.unlockFocus() + glyphs[i] = {} + for j = 1, numFades do + local fade = (j - 1) / (numFades - 1) + local variant = glyph:copy() + glyphs[i][j] = variant + pd->graphics.lockFocus(variant) + fadeGradient:draw(fade * (glyphWidth - fadeGradient.width), 0) + pd->graphics.unlockFocus() + end + */ + } + + pd->graphics->drawBitmap(glyphSpritesheet, 0, 20, kBitmapUnflipped); + pd->graphics->drawBitmap(fadeGradient, 0, 0, kBitmapUnflipped); + + pd->graphics->freeBitmap(glyphSpritesheet); + freeBitmapView(glyphSpritesheetBV); + pd->graphics->freeBitmap(fadeGradient); + freeBitmapView(fadeGradientBV); + + cells = pd->system->realloc(NULL, sizeof(Cell) * numCells); + + int i = 0; + for (int x = 0; x < numColumns; x++) { + float columnTimeOffset = randf() * 1000; + float columnSpeedOffset = random() * 0.5 + 0.5; + for (int y = 0; y < numRows; y++) { + Cell *cell = &cells[i]; + i++; + + cell->x = x; + cell->y = y; + cell->glyphCycle = random(); + cell->columnTimeOffset = columnTimeOffset; + cell->columnSpeedOffset = columnSpeedOffset; + cell->glyphIndex = rand() % numGlyphs; + cell->fadeIndex = -1; + } + } +} + +static int update(void* ud) +{ + float delta; + if (pd->system->isCrankDocked()) { + speed += 0.07; + if (speed > maxSpeed) { + speed = maxSpeed; + } + delta = pd->system->getElapsedTime() * speed; + } else { + speed -= 0.07; + if (speed < minSpeed) { + speed = minSpeed; + } + delta = pd->system->getElapsedTime() * speed + pd->system->getCrankChange() * 2 / 360; + } + pd->system->resetElapsedTime(); + time += delta; + + for (int i = 0; i < numCells; i++) { + int mustDraw = 0; + Cell *cell = &cells[i]; + + float cellTime = cell->y * -0.03 + cell->columnTimeOffset + time * cell->columnSpeedOffset; + float brightness = 4 * fmod( + cellTime + + 0.3 * sineTable[(int)(fmod(wobbleA * cellTime, 360))] + + 0.2 * sineTable[(int)(fmod(wobbleB * cellTime, 360))], + 1 + ); + int fadeIndex = brightness * numFades; + + if (fadeIndex < 1) fadeIndex = 1; + if (fadeIndex > numFades) fadeIndex = numFades; + if (cell->fadeIndex != fadeIndex) { + cell->fadeIndex = fadeIndex; + mustDraw = 1; + } + + cell->glyphCycle = cell->glyphCycle + delta * 2; + if (cell->glyphCycle > 1) { + cell->glyphCycle = fmod(cell->glyphCycle, 1); + int glyphIndex = (cell->glyphIndex + (rand() % 20)) % numGlyphs; + if (cell->glyphIndex != glyphIndex) { + cell->glyphIndex = glyphIndex; + if (fadeIndex < numFades) { + mustDraw = 1; + } + } + } + + if (mustDraw) { + /* + pd->graphics->drawBitmap( + glyphs[cell->glyphIndex * numFades + cell->fadeIndex], + (cell->x - 1) * glyphWidth, + (cell->y - 1) * glyphWidth, + kBitmapUnflipped + ); + */ + } + } + + return 1; +} + +#ifdef _WINDLL +__declspec(dllexport) +#endif +int eventHandler(PlaydateAPI* playdate, PDSystemEvent event, uint32_t arg) +{ + if ( event == kEventInit ) + { + pd = playdate; + pd->display->setRefreshRate(0); + pd->system->setUpdateCallback(update, NULL); + init(); + pd->system->resetElapsedTime(); + } + + return 0; +} diff --git a/playdate/matrix_c/pdxinfo b/playdate/matrix_c/pdxinfo new file mode 100644 index 0000000..c98e9cd --- /dev/null +++ b/playdate/matrix_c/pdxinfo @@ -0,0 +1,8 @@ +name=The Playtrix +author=Rezmason +description=A familiar animation of mysterious raining symbols. +bundleID=net.rezmason.theplaytrix +version=1.0 +buildNumber=1 +imagePath=path/to/launcher/assets +launchSoundPath=path/to/launch/sound/file