summaryrefslogtreecommitdiffstats
path: root/meta/recover.c
diff options
context:
space:
mode:
authorLouis Burda <quent.burda@gmail.com>2025-01-17 23:45:10 +0100
committerLouis Burda <quent.burda@gmail.com>2025-01-17 23:45:10 +0100
commitcf5fa862dd80bc1fb5faa525aa6873c5e755dbe8 (patch)
treedb7a3e6a5bf0b3a4eca1b35fe7f0c3244a6690c2 /meta/recover.c
downloadnullcon2023-bmpass-master.tar.gz
nullcon2023-bmpass-master.zip
Add final challenge filesHEADmaster
Diffstat (limited to 'meta/recover.c')
-rw-r--r--meta/recover.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/meta/recover.c b/meta/recover.c
new file mode 100644
index 0000000..54574b6
--- /dev/null
+++ b/meta/recover.c
@@ -0,0 +1,150 @@
+#include "raylib.h"
+
+#include <err.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#define BLOCKSIZE 16
+#define BESTN 4
+
+struct block {
+ uint8_t data[BLOCKSIZE];
+ uint32_t cnt;
+};
+
+uint8_t *
+read_file(const char *filename, size_t *size)
+{
+ uint8_t *buf;
+ FILE *f;
+
+ f = fopen(filename, "r");
+ if (!f) err(1, "fopen");
+
+ fseek(f, 0, SEEK_END);
+ *size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ buf = malloc(*size);
+ if (!buf) err(1, "malloc");
+
+ if (!fread(buf, *size, 1, f))
+ err(1, "fread");
+
+ fclose(f);
+
+ return buf;
+}
+
+void
+update(struct block *blocks, struct block *bestblocks,
+ size_t *blockslen, uint8_t *img, size_t imglen)
+{
+ struct block cmp, tmp;
+ size_t tmpcnt;
+ size_t i, k;
+
+ memset(bestblocks, 0, BESTN * sizeof(struct block));
+ *blockslen = 0;
+ for (i = 0; i < imglen - BLOCKSIZE + 1; i += BLOCKSIZE) {
+ for (k = 0; k < *blockslen; k++) {
+ if (!memcmp(blocks[k].data, &img[i], BLOCKSIZE)) {
+ blocks[k].cnt += 1;
+ break;
+ }
+ }
+ if (k == *blockslen) {
+ memcpy(blocks[k].data, &img[i], BLOCKSIZE);
+ blocks[k].cnt = 1;
+ *blockslen += 1;
+ }
+
+ memcpy(&cmp, &blocks[k], sizeof(struct block));
+ for (k = 0; k < BESTN; k++) {
+ if (cmp.cnt > bestblocks[k].cnt || !bestblocks[k].cnt) {
+ memcpy(&tmp, &bestblocks[k], sizeof(struct block));
+ memcpy(&bestblocks[k], &cmp, sizeof(struct block));
+ memcpy(&cmp, &tmp, sizeof(struct block));
+ }
+ }
+ }
+}
+
+
+int
+main(int argc, const char **argv)
+{
+ const int wwidth = 1920;
+ const int wheight = 1080;
+ struct block bestblocks[BESTN];
+ struct block *blocks;
+ char textbuf[256];
+ size_t blockslen;
+ size_t imgoff, imglen;
+ size_t width, height;
+ size_t x, y, pos, i;
+ uint8_t *img;
+
+ if (argc < 2) return 1;
+
+ img = read_file(argv[1], &imglen);
+
+ blocks = malloc(imglen / BLOCKSIZE * sizeof(struct block));
+ if (!blocks) err(1, "malloc");
+
+ InitWindow(wwidth, wheight, "bmpass");
+
+ update(blocks, bestblocks, &blockslen, img, imglen);
+
+ width = wwidth;
+ imgoff = 0;
+ while (!WindowShouldClose()) {
+ if (IsKeyDown(KEY_LEFT) && width > 0)
+ width -= 1;
+ else if (IsKeyDown(KEY_RIGHT))
+ width += 1;
+ else if (IsKeyDown(KEY_DOWN) && imgoff > 0)
+ imgoff -= BLOCKSIZE;
+ else if (IsKeyDown(KEY_UP))
+ imgoff += BLOCKSIZE;
+ else if (IsKeyDown(KEY_ESCAPE))
+ break;
+
+ BeginDrawing();
+
+ ClearBackground(GRAY);
+
+ height = (imglen - imgoff) / width;
+ for (y = 0; y < height; y++) {
+ if (y >= wheight) continue;
+ for (x = 0; x < width; x++) {
+ if (x >= wwidth) continue;
+ pos = (imgoff + y * width + x)
+ / BLOCKSIZE * BLOCKSIZE;
+ if (pos + BLOCKSIZE >= imglen) continue;
+ for (i = 0; i < BESTN; i++) {
+ if (!memcmp(bestblocks[i].data,
+ img + pos, BLOCKSIZE))
+ break;
+ }
+ if (i != BESTN)
+ DrawPixel(x, wheight - 1 - y, BLACK);
+ else
+ DrawPixel(x, wheight - 1 - y, WHITE);
+ }
+ }
+
+ snprintf(textbuf, sizeof(textbuf), "imgoff %lu", imgoff);
+ DrawText(textbuf, 10, wheight - 40, 20, BLACK);
+
+ snprintf(textbuf, sizeof(textbuf), "width %lu", width);
+ DrawText(textbuf, 10, wheight - 20, 20, BLACK);
+
+ EndDrawing();
+ }
+
+ CloseWindow();
+}