Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions .github/workflows/wiki.yml

This file was deleted.

40 changes: 36 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,53 @@ SRC_MAIN = src/main.c $(SRC_COMMON)

FLAGS = -Wall -Wextra -Werror -g -std=c11 -pedantic

## Optional embedded image
# e.g. make build EMBED_IMAGE=images/2048.obj
EMBED_IMAGE ?=
EMBED_OBJ :=
EMBED_GLUE :=
ifneq ($(strip $(EMBED_IMAGE)),)
EMBED_OBJ := $(EMBED_IMAGE:.obj=.o)
EMBED_GLUE := images/embed_glue.o
endif

TEST_DIR = test

.PHONY: all build clean test
.PHONY: all build clean test distclean

all: build

build:
build: $(EMBED_OBJ) $(EMBED_GLUE)
mkdir -p $(DIR)
$(CC) $(INC) $(SRC_MAIN) -o $(BIN) $(FLAGS)
$(CC) $(INC) $(SRC_MAIN) $(EMBED_OBJ) $(EMBED_GLUE) -o $(BIN) $(FLAGS)

# Convert raw image to linkable object (ld -b binary)
%.o: %.obj
ld -r -b binary -o $@ $<

# Glue exposes vbo_image_start/end for the chosen image
images/embed_glue.o: $(EMBED_OBJ)
@stem=_binary_$$(echo $(EMBED_IMAGE) | sed 's/[^A-Za-z0-9_]/_/g'); \
mkdir -p images; \
printf '%s\n' \
'/* generated */' \
"extern const unsigned char $${stem}_start[];" \
"extern const unsigned char $${stem}_end[];" \
"const unsigned char* vbo_image_start = $${stem}_start;" \
"const unsigned char* vbo_image_end = $${stem}_end;" \
> images/embed_glue.c; \
$(CC) -c images/embed_glue.c -o images/embed_glue.o $(FLAGS)

clean:
rm -f $(BIN)
rm -f $(TEST_DIR)/test_utils
rm -f images/embed_glue.c images/embed_glue.o

distclean: clean
ifneq ($(strip $(EMBED_OBJ)),)
rm -f $(EMBED_OBJ)
endif

# Basic, explicit test target invoking compile lines for each test file
test:
$(CC) $(INC) $(TEST_DIR)/test_utils.c src/utils.c src/hardware.c -o $(TEST_DIR)/test_utils $(FLAGS)
$(TEST_DIR)/test_utils
Expand Down
2 changes: 2 additions & 0 deletions include/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
#include <stdio.h>
#include <stdint.h>
#include <signal.h>
#include <stddef.h>

void handle_interrupt(int signal);
void disable_input_buffering();
void restore_input_buffering();
void update_flags(uint16_t r);
void mem_write(uint16_t address, uint16_t val);
void read_image_file(FILE* file);
void read_image_buffer(const uint8_t* data, size_t size);

int read_image(const char* image_path);

Expand Down
27 changes: 20 additions & 7 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@
#include "utils.h"


int load_arguments(int argc, const char* argv[])
static int load_arguments(int argc, const char* argv[])
{
if (argc < 2)
{
printf("vbo [image-path] ...\n");
exit(2);
if (argc < 2) {
return -1; // no CLI images
}

for (int j = 1; j < argc; ++j)
{
if (!read_image(argv[j]))
Expand All @@ -40,9 +37,25 @@ int setup()
return 0;
}


// optional embedded image (weak)
extern const unsigned char* vbo_image_start __attribute__((weak));
extern const unsigned char* vbo_image_end __attribute__((weak));


int main(int argc, const char* argv[])
{
load_arguments(argc, argv);
int arg_status = load_arguments(argc, argv);

if (arg_status < 0) {
if (vbo_image_start && vbo_image_end && vbo_image_end > vbo_image_start) {
size_t size = (size_t)(vbo_image_end - vbo_image_start);
read_image_buffer(vbo_image_start, size);
} else {
printf("vbo [image-path] ...\n");
exit(2);
}
}

setup();

Expand Down
22 changes: 22 additions & 0 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,28 @@ void read_image_file(FILE* file)
}
}

// Load an image from an in-memory buffer containing the on-disk image format
void read_image_buffer(const uint8_t* data, size_t size)
{
if (data == NULL || size < sizeof(uint16_t)) {
fprintf(stderr, "Image buffer too small or null\n");
return;
}
// first two bytes: big-endian origin
uint16_t origin = (uint16_t)((data[0] << 8) | data[1]);

size_t bytes_remaining = size - sizeof(uint16_t);
size_t words = bytes_remaining / sizeof(uint16_t);
const uint8_t* p = data + sizeof(uint16_t);

uint16_t* dst = memory + origin;
size_t i;
for (i = 0; i < words && (origin + i) < MEMORY_MAX; ++i) {
uint16_t val = (uint16_t)((p[2*i] << 8) | p[2*i + 1]);
dst[i] = val;
}
}

int read_image(const char* image_path)
{
FILE* file = fopen(image_path, "rb");
Expand Down