Initial commit

This commit is contained in:
2025-06-03 01:15:32 +02:00
commit c77b143f77
7 changed files with 8255 additions and 0 deletions

BIN
assets/music.wav Normal file

Binary file not shown.

2
assets/resources.rc Normal file
View File

@ -0,0 +1,2 @@
VIDEO GIF "video.gif"
AUDIO WAVE "music.wav"

BIN
assets/video.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

26
meson.build Normal file
View File

@ -0,0 +1,26 @@
project('goku', 'c')
cc = meson.get_compiler('c')
winmm = cc.find_library('winmm')
windows = import('windows')
resources = windows.compile_resources('assets/resources.rc')
executable(
'goku',
[
files(
'src/main.c',
'src/stb_image.c',
'gifdec/gifdec.c',
),
resources,
],
include_directories: ['.'],
dependencies: [
dependency('openmp'),
winmm,
],
)

237
src/main.c Normal file
View File

@ -0,0 +1,237 @@
#include <windows.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include "stb_image.h"
#if 0
static void PrintLastError() {
DWORD errorCode = GetLastError(); // Get the last error code
if (errorCode == 0) {
printf("No error occurred.\n");
return;
}
LPVOID lpMsgBuf;
DWORD bufLen;
// Format the message
bufLen = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&lpMsgBuf,
0, NULL);
// Print the error message
if (bufLen) {
printf("Error %d: %s", errorCode, (LPSTR)lpMsgBuf);
LocalFree(lpMsgBuf); // Free the buffer allocated by FormatMessage
} else {
printf("Failed to format message for error %d.\n", errorCode);
}
}
#endif
int main()
{
// Enable console colors
system("color");
// Get %TEMP% path
char tempPathDir[MAX_PATH];
GetTempPath2(MAX_PATH, tempPathDir);
// Get temporary name
char resPath[MAX_PATH];
GetTempFileName(tempPathDir, TEXT("virus"), 0, resPath);
// Get the current module handle
HMODULE thisExe = GetModuleHandle(NULL);
// Find resource
HRSRC resHandle = FindResourceA(thisExe, "VIDEO", "GIF");
// Get video resource
HGLOBAL resDataHandle = LoadResource(thisExe, resHandle);
// Get resource size
DWORD resSize = SizeofResource(thisExe, resHandle);
// Load resource data
void* resData = LockResource(resDataHandle);
// Load GIF
int *gifDelays, gifWidth, gifHeight, gifLength, gifComp;
uint8_t* gif = stbi_load_gif_from_memory(resData, resSize, &gifDelays, &gifWidth, &gifHeight, &gifLength, &gifComp, 3);
if (!gif)
puts(stbi_failure_reason());
// Unload resource data
UnlockResource(resDataHandle);
// Get console handle
HANDLE cmd = GetStdHandle(STD_OUTPUT_HANDLE);
// Get the handle to the desktop window
HWND desktop = GetDesktopWindow();
// Get the device context for the desktop
HDC desktopDC = GetDC(desktop);
// Get the screen width and height
int screenWidth = GetDeviceCaps(desktopDC, HORZRES);
int screenHeight = GetDeviceCaps(desktopDC, VERTRES);
// Release the device context
ReleaseDC(desktop, desktopDC);
// Prepare data
CONSOLE_SCREEN_BUFFER_INFO csbi;
int start_time;
int end_time;
int delta;
int gifPos;
int stride;
int cmdWidth, cmdHeight;
int oldCmdWidth = 0;
int oldCmdHeight = 0;
bool full_render = true;
bool skipped;
int lastx, lasty;
uint8_t* frame;
uint8_t* displayBuf = malloc(screenWidth * screenHeight * 3); // Working frame data
uint8_t* screenBuf = malloc(screenWidth * screenHeight * 3); // Present frame data
char* renderBuf = malloc(screenWidth * screenHeight * 40); // Render frame data
char* renderBufCur;
const float fGifWidth = (float)gifWidth;
const float fGifHeight = (float)gifHeight;
// display and screen buffers are oversized, to avoid resizing at runtime.
// Screen resolution SHOULD be enough...
// Rewind gif and play music
main_start:
gifPos = 0;
PlaySound(TEXT("AUDIO"), thisExe, SND_RESOURCE|SND_LOOP|SND_ASYNC);
main_loop:
// Prepare delta
start_time = GetTickCount();
// Get Console Size
GetConsoleScreenBufferInfo(cmd, &csbi);
cmdWidth = csbi.srWindow.Right - csbi.srWindow.Left + 1;
cmdHeight = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
cmdHeight *= 2;
stride = cmdWidth * 3;
// If resized, do full render
if (cmdWidth != oldCmdWidth || cmdHeight != oldCmdHeight)
full_render = true;
oldCmdWidth = cmdWidth;
oldCmdHeight = cmdHeight;
// Select frame
frame = gif + (gifWidth * gifHeight * 3 * gifPos);
// Project frame to display buffer
int by;
for (by = 0; by < cmdHeight; by++)
{
int bx;
for (bx = 0; bx < cmdWidth; bx++)
{
int gx = (int)(fGifWidth / cmdWidth * bx + 0.5f);
int gy = (int)(fGifHeight / cmdHeight * by + 0.5f);
int displayOffset = (by * cmdWidth + bx) * 3;
int gifOffset = (gy * gifWidth + gx) * 3;
displayBuf[displayOffset + 0] = frame[gifOffset + 0];
displayBuf[displayOffset + 1] = frame[gifOffset + 1];
displayBuf[displayOffset + 2] = frame[gifOffset + 2];
}
}
// Render to console
skipped = true;
renderBufCur = renderBuf;
lastx = -1;
lasty = -1;
for (int by = 0; by < cmdHeight; by+=2)
for (int bx = 0; bx < cmdWidth; bx++)
{
// Check if pixel needs rendering
bool render_needed = false;
int offset = (by * cmdWidth + bx) * 3;
uint8_t dRed = displayBuf[offset + 0];
uint8_t dGreen = displayBuf[offset + 1];
uint8_t dBlue = displayBuf[offset + 2];
uint8_t sRed = screenBuf[offset + 0];
uint8_t sGreen = screenBuf[offset + 1];
uint8_t sBlue = screenBuf[offset + 2];
uint8_t dRedNxt = displayBuf[offset + stride + 0];
uint8_t dGreenNxt = displayBuf[offset + stride + 1];
uint8_t dBlueNxt = displayBuf[offset + stride + 2];
uint8_t sRedNxt = screenBuf[offset + stride + 0];
uint8_t sGreenNxt = screenBuf[offset + stride + 1];
uint8_t sBlueNxt = screenBuf[offset + stride + 2];
if (full_render || dRed != sRed || dGreen != sGreen || dBlue != sBlue)
{
render_needed = true;
}
// If render not needed, skip
if (!render_needed)
continue;
// Move cursor to correct pos
if (bx != lastx+1 || by != lasty)
renderBufCur += sprintf(renderBufCur, "\x1B[%d;%dH", by>>1, bx+1);
// Render pixel
renderBufCur += sprintf(
renderBufCur,
"\x1B[38;2;%d;%d;%dm\x1B[48;2;%d;%d;%dm\xDF",
dRed,
dGreen,
dBlue,
dRedNxt,
dGreenNxt,
dBlueNxt
);
lastx = bx;
lasty = by;
}
*renderBufCur = '\0';
full_render = false;
// Swap buffers
void* tempBuf = displayBuf;
displayBuf = screenBuf;
screenBuf = tempBuf;
// Display rendered frame
printf("%s", renderBuf);
// Compute delta
end_time = GetTickCount();
delta = end_time - start_time;
// Sleep
int sleep_time = gifDelays[gifPos] - delta;
if (sleep_time > 0)
Sleep(sleep_time);
// Switch frame
if (++gifPos == gifLength)
goto main_start;
// Repeat
goto main_loop;
}

2
src/stb_image.c Normal file
View File

@ -0,0 +1,2 @@
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

7988
src/stb_image.h Normal file

File diff suppressed because it is too large Load Diff