From 24a7a0c7157c6b2f1d12a36d1fb9b2eb7ae4b828 Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Mon, 13 Jan 2025 23:15:37 -0800 Subject: [PATCH] Add message overlay support --- Makefile | 1 + src/charbits.h | 147 ++++++++++++++++++++++++++++++++++++++++++++++ src/overlay.c | 62 +++++++++++++++++++ src/overlay.h | 25 ++++++++ src/render.h | 2 + src/sdl_overlay.c | 135 ++++++++++++++++++++++++++++++++++++++++++ src/sdl_overlay.h | 26 ++++++++ src/sdl_render.c | 10 ++++ 8 files changed, 408 insertions(+) create mode 100644 src/charbits.h create mode 100644 src/overlay.c create mode 100644 src/overlay.h create mode 100644 src/sdl_overlay.c create mode 100644 src/sdl_overlay.h diff --git a/Makefile b/Makefile index 3f6a790..dc65291 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ SRC_SRCS_1 += cart.c mapper.c SRC_SRCS_1 += apu.c audio.c SRC_SRCS_1 += file.c save.c SRC_SRCS_1 += sdl_render.c sdl_input.c sdl_audio.c sdl_timer.c +SRC_SRCS_1 += overlay.c sdl_overlay.c PLAT_SRCS_1 = filemap.c diff --git a/src/charbits.h b/src/charbits.h new file mode 100644 index 0000000..205defd --- /dev/null +++ b/src/charbits.h @@ -0,0 +1,147 @@ +static const char chars[] = "\x7f!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`{|}~"; + +static const int char_w = 10U; +static const int char_h = 10U; +static const int charbit_size = (1U + ((char_w * char_h * 2) + 7) / 8); +static const int char_count = (sizeof(chars) - 1); + +static const uint8_t charbits[1794] = { + 0x09, 0x55, 0x55, 0x90, 0xaa, 0x16, 0x59, 0x69, 0x91, 0xa5, 0x16, 0x99, 0x66, + 0x91, 0x5a, 0x16, 0x69, 0x65, 0x91, 0xaa, 0x16, 0x55, 0x55, 0x41, 0x55, 0x15, + 0x07, 0x50, 0x05, 0x00, 0x69, 0x01, 0x94, 0x16, 0x40, 0x6a, 0x01, 0xa4, 0x15, + 0x40, 0x5a, 0x01, 0x55, 0x05, 0x90, 0x56, 0x00, 0x55, 0x01, 0x40, 0x15, 0x00, + 0x08, 0x55, 0x15, 0x90, 0xa6, 0x05, 0x69, 0x5a, 0x90, 0xa6, 0x05, 0x55, 0x55, + 0x40, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x54, 0x55, 0x40, 0x9a, 0x16, 0xa5, 0x69, 0x91, 0xaa, 0x5a, 0xa5, 0x69, + 0x95, 0xaa, 0x5a, 0xa5, 0x69, 0x45, 0x9a, 0x56, 0x54, 0x55, 0x01, 0x55, 0x15, + 0x09, 0x50, 0x05, 0x40, 0x69, 0x05, 0xa5, 0x6a, 0x91, 0x56, 0x15, 0xa5, 0x5a, + 0x51, 0x95, 0x16, 0xa9, 0x5a, 0x51, 0x69, 0x15, 0x54, 0x55, 0x00, 0x55, 0x01, + 0x0a, 0x00, 0x00, 0x50, 0x45, 0x15, 0x69, 0xa5, 0x95, 0x96, 0x56, 0x55, 0x5a, + 0x45, 0x69, 0x15, 0xa5, 0xa5, 0x95, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x0a, 0x50, 0x15, 0x40, 0xa9, 0x05, 0xa4, 0x69, 0x41, 0x9a, 0x16, 0xa5, 0x5a, + 0x91, 0x96, 0x5a, 0x69, 0x6a, 0x55, 0x6a, 0x5a, 0x54, 0x55, 0x05, 0x55, 0x55, + 0x05, 0x55, 0x00, 0x90, 0x16, 0x00, 0x69, 0x01, 0x90, 0x16, 0x00, 0x55, 0x01, + 0x40, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x54, 0x01, 0x50, 0x5a, 0x00, 0x69, 0x05, 0x90, 0x56, 0x00, 0x69, 0x01, + 0x90, 0x16, 0x00, 0x69, 0x01, 0x50, 0x5a, 0x00, 0x54, 0x05, 0x00, 0x55, 0x00, + 0x06, 0x55, 0x00, 0x90, 0x16, 0x00, 0xa5, 0x05, 0x40, 0x5a, 0x00, 0xa4, 0x05, + 0x40, 0x5a, 0x00, 0xa5, 0x05, 0x90, 0x56, 0x00, 0x55, 0x01, 0x40, 0x05, 0x00, + 0x0a, 0x00, 0x00, 0x40, 0x55, 0x05, 0xa4, 0x69, 0x51, 0xa9, 0x15, 0xa9, 0xaa, + 0x55, 0xa9, 0x55, 0xa4, 0x69, 0x45, 0x55, 0x15, 0x50, 0x55, 0x01, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x50, 0x16, 0x00, 0xa9, 0x05, + 0x50, 0x56, 0x00, 0x54, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, + 0x40, 0x5a, 0x00, 0xa5, 0x05, 0x90, 0x56, 0x00, 0x55, 0x05, 0x40, 0x15, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x15, 0x00, 0xa9, 0x05, + 0x50, 0x55, 0x00, 0x54, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x15, 0x00, 0xa4, 0x05, 0x40, 0x5a, 0x00, 0x54, 0x05, 0x00, 0x55, 0x00, + 0x07, 0x50, 0x05, 0x00, 0x69, 0x01, 0x94, 0x16, 0x40, 0x5a, 0x01, 0xa4, 0x05, + 0x50, 0x5a, 0x00, 0x69, 0x05, 0x90, 0x16, 0x00, 0x55, 0x01, 0x40, 0x15, 0x00, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x96, 0x5a, 0x69, 0xa6, + 0x95, 0x5a, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x09, 0x50, 0x05, 0x40, 0x69, 0x01, 0xa4, 0x16, 0x40, 0x69, 0x01, 0x90, 0x16, + 0x00, 0x69, 0x01, 0x95, 0x56, 0x90, 0xaa, 0x16, 0x55, 0x55, 0x41, 0x55, 0x15, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x96, 0x5a, 0x55, 0x6a, + 0x45, 0xa9, 0x55, 0xa5, 0x56, 0x91, 0xaa, 0x5a, 0x55, 0x55, 0x45, 0x55, 0x55, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x55, 0x55, 0x5a, 0x54, 0x6a, + 0x55, 0x55, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x0a, 0x00, 0x55, 0x00, 0x94, 0x16, 0x50, 0x6a, 0x41, 0xa9, 0x16, 0xa5, 0x69, + 0x91, 0x96, 0x16, 0xa9, 0xaa, 0x55, 0x95, 0x56, 0x54, 0x55, 0x05, 0x40, 0x15, + 0x0a, 0x55, 0x55, 0x95, 0xaa, 0x5a, 0x69, 0x55, 0x95, 0xaa, 0x56, 0x55, 0xa5, + 0x55, 0x55, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x0a, 0x50, 0x15, 0x40, 0xa9, 0x05, 0xa5, 0x55, 0x90, 0x56, 0x05, 0xa9, 0x6a, + 0x91, 0x56, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x0a, 0x55, 0x55, 0x91, 0xaa, 0x5a, 0x55, 0x69, 0x45, 0x95, 0x56, 0x40, 0x5a, + 0x01, 0xa5, 0x15, 0x90, 0x56, 0x00, 0x69, 0x05, 0x50, 0x15, 0x00, 0x54, 0x01, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x5a, 0x5a, 0xa5, 0x6a, + 0x95, 0x96, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0xa5, 0xaa, + 0x45, 0x55, 0x5a, 0x50, 0x69, 0x05, 0xa9, 0x55, 0x50, 0x55, 0x01, 0x54, 0x05, + 0x05, 0x00, 0x00, 0x50, 0x05, 0x00, 0x69, 0x01, 0x90, 0x16, 0x00, 0x55, 0x01, + 0x90, 0x16, 0x00, 0x69, 0x01, 0x50, 0x15, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x40, 0x15, 0x00, 0xa4, 0x05, 0x40, 0x5a, 0x00, 0x54, 0x05, + 0x40, 0x5a, 0x00, 0xa5, 0x05, 0x90, 0x56, 0x00, 0x55, 0x05, 0x40, 0x15, 0x00, + 0x08, 0x40, 0x15, 0x00, 0xa5, 0x05, 0x94, 0x56, 0x50, 0x5a, 0x05, 0x69, 0x15, + 0x50, 0x5a, 0x00, 0x94, 0x16, 0x00, 0xa5, 0x05, 0x40, 0x55, 0x00, 0x50, 0x05, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x01, 0x90, 0x5a, 0x00, 0x55, 0x05, + 0x90, 0x5a, 0x00, 0x55, 0x05, 0x40, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x08, 0x55, 0x00, 0x90, 0x16, 0x00, 0xa5, 0x05, 0x40, 0x69, 0x01, 0x50, 0x5a, + 0x40, 0x69, 0x05, 0xa5, 0x55, 0x90, 0x56, 0x01, 0x55, 0x05, 0x40, 0x15, 0x00, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x55, 0x55, 0x5a, 0x54, 0x6a, + 0x05, 0x69, 0x55, 0x50, 0x55, 0x01, 0x69, 0x01, 0x50, 0x15, 0x00, 0x54, 0x01, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0xa9, 0x59, 0x99, 0x99, + 0x95, 0xa9, 0x5a, 0x69, 0x55, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x01, 0x55, 0x15, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x69, 0xa5, + 0x95, 0xaa, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x0a, 0x55, 0x55, 0x90, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0xa9, 0x6a, + 0x95, 0x56, 0x5a, 0x69, 0xa5, 0x95, 0xaa, 0x56, 0x55, 0x55, 0x45, 0x55, 0x15, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x55, 0x69, 0x55, + 0x95, 0x56, 0x15, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x0a, 0x55, 0x15, 0x90, 0xaa, 0x05, 0x69, 0x69, 0x91, 0x56, 0x5a, 0x69, 0xa5, + 0x95, 0x56, 0x5a, 0x69, 0x69, 0x95, 0xaa, 0x55, 0x55, 0x55, 0x41, 0x55, 0x05, + 0x0a, 0x55, 0x55, 0x91, 0xaa, 0x5a, 0x69, 0x55, 0x95, 0x56, 0x55, 0xa9, 0x6a, + 0x91, 0x56, 0x15, 0x69, 0x55, 0x91, 0xaa, 0x5a, 0x55, 0x55, 0x45, 0x55, 0x55, + 0x0a, 0x55, 0x55, 0x91, 0xaa, 0x5a, 0x69, 0x55, 0x95, 0x56, 0x55, 0xa9, 0x6a, + 0x91, 0x56, 0x15, 0x69, 0x55, 0x91, 0x16, 0x00, 0x55, 0x01, 0x40, 0x15, 0x00, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x55, 0x69, 0xa9, + 0x95, 0x56, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x59, 0x54, 0x55, 0x05, 0x55, 0x55, + 0x0a, 0x55, 0x54, 0x91, 0x56, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0xa9, 0xaa, + 0x95, 0x56, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x05, 0x55, 0x00, 0x90, 0x16, 0x00, 0x69, 0x01, 0x90, 0x16, 0x00, 0x69, 0x01, + 0x90, 0x16, 0x00, 0x69, 0x01, 0x90, 0x16, 0x00, 0x55, 0x01, 0x40, 0x15, 0x00, + 0x0a, 0x00, 0x54, 0x01, 0x40, 0x5a, 0x00, 0xa4, 0x05, 0x40, 0x5a, 0x55, 0xa5, + 0x95, 0x56, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x0a, 0x55, 0x54, 0x91, 0x56, 0x5a, 0x69, 0x69, 0x95, 0xa6, 0x55, 0xa9, 0x56, + 0x91, 0xa6, 0x05, 0x69, 0x69, 0x91, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x09, 0x55, 0x00, 0x90, 0x16, 0x00, 0x69, 0x01, 0x90, 0x16, 0x00, 0x69, 0x01, + 0x90, 0x16, 0x00, 0x69, 0x55, 0x90, 0xaa, 0x16, 0x55, 0x55, 0x41, 0x55, 0x15, + 0x0a, 0x55, 0x54, 0x91, 0x56, 0x5a, 0xa9, 0xa9, 0x95, 0xaa, 0x5a, 0x69, 0xa6, + 0x95, 0x56, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x0a, 0x55, 0x54, 0x91, 0x56, 0x5a, 0xa9, 0xa5, 0x95, 0x6a, 0x5a, 0x69, 0xaa, + 0x95, 0x96, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x69, 0xa5, + 0x95, 0x56, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x0a, 0x55, 0x55, 0x90, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x69, 0xa5, + 0x95, 0xaa, 0x56, 0x69, 0x55, 0x95, 0x56, 0x15, 0x55, 0x01, 0x40, 0x15, 0x00, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x69, 0xa5, + 0x95, 0x56, 0x5a, 0x69, 0x69, 0x55, 0xaa, 0x5a, 0x54, 0x55, 0x05, 0x55, 0x55, + 0x0a, 0x55, 0x55, 0x90, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0xa9, 0x6a, + 0x95, 0x56, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x0a, 0x54, 0x55, 0x50, 0xaa, 0x16, 0x69, 0xa5, 0x95, 0x56, 0x55, 0xa5, 0x6a, + 0x55, 0x55, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x09, 0x55, 0x55, 0x90, 0xaa, 0x16, 0x95, 0x56, 0x01, 0x69, 0x15, 0x90, 0x16, + 0x00, 0x69, 0x01, 0x90, 0x16, 0x00, 0x69, 0x01, 0x50, 0x15, 0x00, 0x54, 0x01, + 0x0a, 0x55, 0x54, 0x91, 0x56, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x69, 0xa5, + 0x95, 0x56, 0x5a, 0x69, 0xa5, 0x55, 0xaa, 0x56, 0x54, 0x55, 0x05, 0x55, 0x15, + 0x0a, 0x55, 0x54, 0x91, 0x56, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x69, 0xa5, + 0x55, 0x9a, 0x56, 0x94, 0x5a, 0x05, 0x65, 0x15, 0x40, 0x55, 0x00, 0x50, 0x01, + 0x0a, 0x55, 0x54, 0x91, 0x56, 0x5a, 0x69, 0xa5, 0x95, 0x56, 0x5a, 0x69, 0xa6, + 0x95, 0xaa, 0x5a, 0xa9, 0xa9, 0x95, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x0a, 0x55, 0x54, 0x91, 0x56, 0x5a, 0xa9, 0xa9, 0x55, 0xaa, 0x56, 0x94, 0x5a, + 0x55, 0xaa, 0x16, 0xa9, 0xa9, 0x95, 0x56, 0x5a, 0x55, 0x55, 0x45, 0x15, 0x55, + 0x09, 0x55, 0x55, 0x90, 0x96, 0x16, 0x69, 0x69, 0x91, 0x96, 0x16, 0xa5, 0x5a, + 0x41, 0x69, 0x15, 0x90, 0x56, 0x00, 0x69, 0x01, 0x50, 0x15, 0x00, 0x54, 0x01, + 0x0a, 0x55, 0x55, 0x91, 0xaa, 0x5a, 0x55, 0xa9, 0x05, 0xa5, 0x56, 0x94, 0x5a, + 0x55, 0x6a, 0x15, 0xa9, 0x55, 0x91, 0xaa, 0x5a, 0x55, 0x55, 0x45, 0x55, 0x55, + 0x06, 0x55, 0x01, 0x90, 0x5a, 0x00, 0x69, 0x05, 0x90, 0x56, 0x00, 0x69, 0x01, + 0x90, 0x16, 0x00, 0x69, 0x01, 0x90, 0x5a, 0x00, 0x55, 0x05, 0x40, 0x55, 0x00, + 0x07, 0x55, 0x00, 0x90, 0x16, 0x00, 0x69, 0x01, 0x50, 0x5a, 0x00, 0xa4, 0x05, + 0x40, 0x5a, 0x00, 0x94, 0x16, 0x00, 0x69, 0x01, 0x50, 0x15, 0x00, 0x54, 0x01, + 0x06, 0x55, 0x01, 0x90, 0x5a, 0x00, 0xa5, 0x05, 0x40, 0x5a, 0x00, 0xa4, 0x05, + 0x40, 0x5a, 0x00, 0xa5, 0x05, 0x90, 0x5a, 0x00, 0x55, 0x05, 0x40, 0x55, 0x00, + 0x08, 0x50, 0x01, 0x40, 0x59, 0x00, 0xa5, 0x16, 0x90, 0xa6, 0x05, 0x59, 0x59, + 0x50, 0x55, 0x05, 0x54, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x55, 0x55, 0x91, 0xaa, 0x5a, 0x55, 0x55, 0x45, 0x55, 0x55, + 0x07, 0x55, 0x00, 0x90, 0x16, 0x00, 0xa5, 0x05, 0x40, 0x69, 0x01, 0x50, 0x15, + 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x50, 0x05, 0x40, 0x69, 0x01, 0xa4, 0x15, 0x50, 0x5a, 0x01, 0x69, 0x05, + 0x50, 0x5a, 0x00, 0xa4, 0x05, 0x40, 0x69, 0x01, 0x50, 0x15, 0x00, 0x54, 0x01, + 0x04, 0x15, 0x00, 0x90, 0x05, 0x00, 0x59, 0x00, 0x90, 0x05, 0x00, 0x59, 0x00, + 0x90, 0x05, 0x00, 0x59, 0x00, 0x90, 0x05, 0x00, 0x55, 0x00, 0x40, 0x05, 0x00, + 0x07, 0x55, 0x00, 0x90, 0x16, 0x00, 0xa5, 0x05, 0x40, 0x5a, 0x00, 0x94, 0x16, + 0x40, 0x5a, 0x01, 0xa5, 0x15, 0x90, 0x56, 0x00, 0x55, 0x05, 0x40, 0x15, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x51, 0x6a, 0x5a, 0x69, 0x6a, + 0x55, 0x55, 0x55, 0x54, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; diff --git a/src/overlay.c b/src/overlay.c new file mode 100644 index 0000000..e9b0eeb --- /dev/null +++ b/src/overlay.c @@ -0,0 +1,62 @@ +#include +#include + +#include "overlay.h" + + +int overlay_init(Overlay* overlay) { + overlay->messages = NULL; + overlay->next_id = 0; + return 0; +} + +int overlay_clear(Overlay* overlay) { + int n_cleared = 0; + for ( overlay_message* message = overlay->messages; + NULL != message; + message = message->next) { + free(message->string); + free(message); + ++n_cleared; + } + overlay_init(overlay); + return n_cleared; +} + +int overlay_clear_message(Overlay* overlay, int id) { + int result = -1; + overlay_message* last = NULL; + overlay_message* message = overlay->messages; + for ( ; + NULL != message && message->id != id; + last = message, message = message->next + ); + if (NULL != message) { + result = 0; + if (NULL == last) { + overlay->messages = message->next; + } else { + last->next = message->next; + } + free(message->string); + free(message); + } + return result; +} + +int overlay_add_message(Overlay* overlay, + const char* string, int expiry) { + overlay_message* message = calloc(1, sizeof(*message)); + message->string = strdup(string); + message->id = ++(overlay->next_id); + message->expiry = expiry; + message->next = NULL; + if (NULL == overlay->messages) { + overlay->messages = message; + } else { + overlay_message* last = overlay->messages; + for ( ; NULL != last->next; last = last->next); + last->next = message; + } + return message->id; +} diff --git a/src/overlay.h b/src/overlay.h new file mode 100644 index 0000000..712bd5b --- /dev/null +++ b/src/overlay.h @@ -0,0 +1,25 @@ +#ifndef NESE_OVERLAY_H_ +#define NESE_OVERLAY_H_ + + +typedef struct overlay_message_t { + char* string; + int id; + int expiry; + struct overlay_message_t* next; +} overlay_message; + + +typedef struct { + overlay_message* messages; + int next_id; +} Overlay; + + +int overlay_init(Overlay*); +int overlay_add_message(Overlay*, const char*, int expiry); +int overlay_clear_message(Overlay*, int id); +int overlay_clear(Overlay*); + + +#endif // NESE_OVERLAY_H_ diff --git a/src/render.h b/src/render.h index b51fab1..c74222a 100644 --- a/src/render.h +++ b/src/render.h @@ -2,12 +2,14 @@ #define NES_RENDER_H_ #include "ppu.h" +#include "overlay.h" typedef struct nes_Renderer_t { int (*init)(struct nes_Renderer_t*); void (*done)(struct nes_Renderer_t*); int (*render)(struct nes_Renderer_t*, nes_ppu*); + Overlay overlay; void* data; } nes_Renderer; diff --git a/src/sdl_overlay.c b/src/sdl_overlay.c new file mode 100644 index 0000000..95ce8a1 --- /dev/null +++ b/src/sdl_overlay.c @@ -0,0 +1,135 @@ +#include "sdl_overlay.h" + +#include "charbits.h" + + +typedef struct { + const uint8_t* bits; + uint8_t shift; +} bit_buffer; + +void make_bit_buffer(bit_buffer* buf, const uint8_t* bits) { + buf->bits = bits; + buf->shift = 0; +} + +uint8_t get_bits(bit_buffer* buf) { + uint8_t val = ((buf->bits[0] >> buf->shift) & 3); + if (buf->shift == 6) { + buf->shift = 0; + buf->bits++; + } else { + buf->shift += 2; + } + return val; +} + +static const SDL_Color pal[2] = { + {0, 0, 0}, {255, 255, 255} +}; + +static SDL_Surface* create_char_surface(const uint8_t* bits) { + int w = *bits++; + bit_buffer buf = {0}; + make_bit_buffer(&buf, bits); + + SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat( + 0, w, char_h, 8, SDL_PIXELFORMAT_INDEX8 + ); + SDL_SetPaletteColors(surface->format->palette, pal, 1U, 2U); + SDL_SetColorKey(surface, SDL_TRUE, 0); + + uint8_t* line = surface->pixels; + for (int y = char_h; y > 0; --y) { + uint8_t* dst = line; + for (int x = w; x > 0; --x) { + *dst++ = get_bits(&buf); + } + for (int x = (char_w - w); x > 0; --x) get_bits(&buf); + line += surface->pitch; + } + + return surface; +} + +int sdl_overlay_font_init(sdl_overlay_font* font) { + font->chars = chars; + font->charbits = charbits; + font->char_count = char_count; + font->surfaces = calloc(char_count, sizeof(SDL_Surface*)); + for (int i = 0; i < font->char_count; ++i) { + font->surfaces[i] = create_char_surface( + &font->charbits[i * charbit_size] + ); + } + return 0; +} + +void sdl_overlay_font_done(sdl_overlay_font* font) { + for (int i = 0; i < font->char_count; ++i) { + SDL_FreeSurface(font->surfaces[i]); + } +} + +#define overlay_start_x (char_w / 2) +#define overlay_start_y (char_h / 2) + +static inline int char_index(char c) { + if (c >= 'a' && c <= 'z') c += ('A' - 'a'); + if (c > ' ' && c < 'a') return (c - ' '); + if (c >= '{' && c <= '~') return (65 + c - '{'); + return 0; +} + +static void render_string(SDL_Surface* target, + int x, int y, + sdl_overlay_font* font, + const char* string) { + SDL_Rect rect = { + .x = x, + .y = y, + .w = char_w, + .h = char_h, + }; + + for (const char* c = string; *c; ++c) { + if (*c == ' ') { + rect.x += (char_w / 2) - 1; + } else { + SDL_Surface* surface = font->surfaces[ + char_index(*c) + ]; + + SDL_BlitSurface(surface, NULL, target, &rect); + + rect.x += (surface->w - 1); + } + } +} + +int sdl_overlay_frame(Overlay* overlay, sdl_overlay_font* font, + SDL_Surface* target) { + int y = overlay_start_y; + overlay_message* last = NULL, *next = NULL; + for ( overlay_message* message = overlay->messages; + NULL != message; + last = message, message = next) { + next = message->next; + + render_string(target, overlay_start_x, y, + font, message->string); + y += (char_h + 1); + + if (message->expiry > 0 && --(message->expiry) == 0) { + if (NULL == last) { + overlay->messages = message->next; + } else { + last->next = message->next; + } + free(message->string); + free(message); + } + } + + return 0; +} diff --git a/src/sdl_overlay.h b/src/sdl_overlay.h new file mode 100644 index 0000000..6e3f39f --- /dev/null +++ b/src/sdl_overlay.h @@ -0,0 +1,26 @@ +#ifndef NESE_SDL_OVERLAY_ +#define NESE_SDL_OVERLAY_ + +#include + +#include + +#include "overlay.h" + + +typedef struct { + const char* chars; + const uint8_t* charbits; + int char_count; + SDL_Surface** surfaces; +} sdl_overlay_font; + + +int sdl_overlay_font_init(sdl_overlay_font*); + +void sdl_overlay_font_done(sdl_overlay_font*); + +int sdl_overlay_frame(Overlay*, sdl_overlay_font*, SDL_Surface*); + + +#endif // NESE_SDL_OVERLAY_ diff --git a/src/sdl_render.c b/src/sdl_render.c index 97ee959..00acb3b 100644 --- a/src/sdl_render.c +++ b/src/sdl_render.c @@ -5,6 +5,7 @@ #include "render.h" #include "ppu.h" #include "mapper.h" +#include "sdl_overlay.h" static SDL_Color nes_palette[64] = { @@ -44,6 +45,7 @@ typedef struct { SDL_Surface* foreground; SDL_Surface* sprite; SDL_Surface* target; + sdl_overlay_font font; } sdl_render_data; static sdl_render_data the_render_data = {0}; @@ -51,6 +53,11 @@ static sdl_render_data the_render_data = {0}; static int sdl_render_init(nes_Renderer* rend) { sdl_render_data* data = &the_render_data; + + overlay_init(&rend->overlay); + // TODO: Cleanup + sdl_overlay_font_init(&data->font); + int status = SDL_Init(SDL_INIT_VIDEO); if (0 != status) { @@ -566,6 +573,9 @@ static int sdl_render(nes_Renderer* rend, nes_ppu* ppu) { } else { REND_LOG("Scanline %3d -> Postrender\n", ppu->scanline); + sdl_overlay_frame(&rend->overlay, &data->font, + data->target); + SDL_Texture* texture = SDL_CreateTextureFromSurface( data->renderer, data->target );