Introduce decimal point font (#314)
* Introduce decimal point font * Add png of font * Add getting a decimal point str from int * Move font out of utils * Clang format * set Readme.md as main page in docs * Add font generator * kind of fix font * Fix image oddities * Added pip install pillow to build_ci_workflow * Added ensurepip * Update Docker/CI for font generation * Fix CI * Fix CI forreal * Another CI fix * Fix directory name for rom * Adjust directory * Dummy commit for test * Revert "Dummy commit for test" This reverts commit b607085c1322c824d2fdd800ab3c3700389ad3a6. * dos2unix and update .gitignore * Delete the generated font file * Delete the generated font file * remove dot from font * Update include/font.h Co-authored-by: MeirGavish <meir.gavish@gmail.com> --------- Co-authored-by: MeirGavish <meir.gavish@gmail.com>
This commit is contained in:
@@ -51,14 +51,14 @@ jobs:
|
|||||||
|
|
||||||
- name: Load or pull images
|
- name: Load or pull images
|
||||||
run: |
|
run: |
|
||||||
if [ -f /tmp/docker-cache/balatro.tar ]; then
|
if [ -f /tmp/docker-cache/gbalatro.tar ]; then
|
||||||
echo "Loading Image"
|
echo "Loading Image"
|
||||||
docker load -i /tmp/docker-cache/balatro.tar
|
docker load -i /tmp/docker-cache/gbalatro.tar
|
||||||
else
|
else
|
||||||
echo "Pulling Image"
|
echo "Pulling Image"
|
||||||
docker compose pull balatro
|
docker compose build gbalatro
|
||||||
mkdir -p /tmp/docker-cache
|
mkdir -p /tmp/docker-cache
|
||||||
docker save $(docker compose config | grep image: | awk '{print $2}') -o /tmp/docker-cache/balatro.tar
|
docker save $(docker compose config | grep image: | awk '{print $2}') -o /tmp/docker-cache/gbalatro.tar
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Export UID/GID for Compose
|
- name: Export UID/GID for Compose
|
||||||
@@ -67,7 +67,7 @@ jobs:
|
|||||||
echo "GID=$(id -g)" >> "$GITHUB_ENV"
|
echo "GID=$(id -g)" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
- name: Build the project
|
- name: Build the project
|
||||||
run: docker compose -f docker-compose.yml run --rm balatro sh -c "make -j$(nproc) && ./scripts/get_memory_map.sh"
|
run: docker compose -f docker-compose.yml run --rm gbalatro sh -c "make -j$(nproc) && ./scripts/get_memory_map.sh"
|
||||||
|
|
||||||
- name: 'Upload Artifact'
|
- name: 'Upload Artifact'
|
||||||
if: ${{ inputs.upload-build-artifact }}
|
if: ${{ inputs.upload-build-artifact }}
|
||||||
|
|||||||
+15
-15
@@ -1,15 +1,15 @@
|
|||||||
/.vscode
|
/.vscode
|
||||||
/.idea
|
/.idea
|
||||||
/build
|
/build
|
||||||
/.vs
|
/.vs
|
||||||
_codeql_detected_source_root
|
_codeql_detected_source_root
|
||||||
*.sln
|
*.sln
|
||||||
*.vcxproj*
|
*.vcxproj*
|
||||||
/balatro-gba/x64/**
|
/balatro-gba/x64/**
|
||||||
/tests/bitset/build
|
/tests/bitset/build
|
||||||
/tests/list/build
|
/tests/list/build
|
||||||
/tests/pool/build
|
/tests/pool/build
|
||||||
doc
|
doc
|
||||||
tests/util/.vscode
|
tests/util/.vscode
|
||||||
tests/util/build
|
tests/util/build
|
||||||
audio/*.bak
|
audio/*.bak
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
FROM devkitpro/devkitarm:20251117
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
python3-pil
|
||||||
@@ -3016,3 +3016,5 @@ MSCGEN_TOOL =
|
|||||||
MSCFILE_DIRS =
|
MSCFILE_DIRS =
|
||||||
|
|
||||||
EXCLUDE = build tests graphics audio doc scripts
|
EXCLUDE = build tests graphics audio doc scripts
|
||||||
|
|
||||||
|
USE_MDFILE_AS_MAINPAGE = README.md
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ INCLUDES := include
|
|||||||
DATA :=
|
DATA :=
|
||||||
MUSIC := audio
|
MUSIC := audio
|
||||||
GRAPHICS := graphics
|
GRAPHICS := graphics
|
||||||
|
FONT := font
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
@@ -82,7 +83,8 @@ export OUTPUT := $(CURDIR)/$(BUILD)/$(TARGET)
|
|||||||
|
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||||
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))
|
$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(FONT),$(CURDIR)/$(dir)) \
|
||||||
|
|
||||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
@@ -90,6 +92,7 @@ CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
|||||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
|
PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png)))
|
||||||
|
FONTFILES := $(foreach dir,$(FONT),$(notdir $(wildcard $(dir)/*.png)))
|
||||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
ifneq ($(strip $(MUSIC)),)
|
ifneq ($(strip $(MUSIC)),)
|
||||||
@@ -117,7 +120,9 @@ export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
|||||||
|
|
||||||
export OFILES_GRAPHICS := $(PNGFILES:.png=.o)
|
export OFILES_GRAPHICS := $(PNGFILES:.png=.o)
|
||||||
|
|
||||||
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) $(OFILES_GRAPHICS)
|
export OFILES_FONT := $(FONTFILES:.png=.o)
|
||||||
|
|
||||||
|
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) $(OFILES_GRAPHICS) $(OFILES_FONT)
|
||||||
|
|
||||||
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) $(PNGFILES:.png=.h)
|
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) $(PNGFILES:.png=.h)
|
||||||
|
|
||||||
@@ -130,17 +135,22 @@ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
|||||||
.PHONY: $(BUILD) clean
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
$(BUILD):
|
$(BUILD): build/gbalatro_sys8.s
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@[ -d $@ ] || mkdir -p $@
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
@echo "$(GIT_HASH)$(GIT_DIRTY)" > $@/githash.txt
|
@echo "$(GIT_HASH)$(GIT_DIRTY)" > $@/githash.txt
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
build/%.s: $(FONT)/%.png
|
||||||
|
@echo Building font
|
||||||
|
@mkdir -p $(BUILD)
|
||||||
|
@python3 scripts/generate_font.py -i $< -o $@
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).gba
|
@rm -fr $(BUILD) $(TARGET).elf $(TARGET).gba
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all: $(BUILD)
|
all: $(BUILD)
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -1,6 +1,9 @@
|
|||||||
services:
|
services:
|
||||||
balatro:
|
gbalatro:
|
||||||
image: devkitpro/devkitarm:latest
|
image: gbalatro:dev
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.gbalatro
|
||||||
working_dir: /balatro-gba
|
working_dir: /balatro-gba
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/balatro-gba
|
- ./:/balatro-gba
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* @file font.h
|
||||||
|
*
|
||||||
|
* @brief Utility file to interact with custom font
|
||||||
|
*/
|
||||||
|
#ifndef FONT_H
|
||||||
|
#define FONT_H
|
||||||
|
|
||||||
|
#include <tonc.h>
|
||||||
|
|
||||||
|
extern const TFont gbalatro_sys8Font;
|
||||||
|
extern const unsigned int gbalatro_sys8Glyphs[192];
|
||||||
|
|
||||||
|
/** @name Decimal Point Fonts
|
||||||
|
* @brief A set of macros to map the fonts decimal-point values (e.g. ".1")
|
||||||
|
* to their replaced characters.
|
||||||
|
*
|
||||||
|
* "FP#" -> Font "Point" "number"
|
||||||
|
*
|
||||||
|
* This is used at compile time directly with the help of libtonc's XSTR() macro
|
||||||
|
* **Note**: This should **ONLY** be used with the XSTR() macro, otherwise it
|
||||||
|
* is undefined behavior.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* ```c
|
||||||
|
* tte_printf("Testing " XSTR(FP0_CHAR) " Something!");
|
||||||
|
* ```
|
||||||
|
* prints "Testing .0 Something!"
|
||||||
|
*
|
||||||
|
* The map is the following:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* '&' == '.0'
|
||||||
|
* '^' == '.1'
|
||||||
|
* '{' == '.2'
|
||||||
|
* '}' == '.3'
|
||||||
|
* '|' == '.4'
|
||||||
|
* '`' == '.5'
|
||||||
|
* '<' == '.6'
|
||||||
|
* '>' == '.7'
|
||||||
|
* '_' == '.8'
|
||||||
|
* ';' == '.9'
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define FP0_CHAR & // .0
|
||||||
|
#define FP1_CHAR ^ // .1
|
||||||
|
#define FP2_CHAR { // .2
|
||||||
|
#define FP3_CHAR } // .3
|
||||||
|
#define FP4_CHAR | // .4
|
||||||
|
#define FP5_CHAR ` // .5
|
||||||
|
#define FP6_CHAR < // .6
|
||||||
|
#define FP7_CHAR > // .7
|
||||||
|
#define FP8_CHAR _ // .8
|
||||||
|
#define FP9_CHAR ; // .9
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the decimal point string equivalent of 0-9 from integer param.
|
||||||
|
*
|
||||||
|
* @param val Value between 0-9 to get ".0" to ".9" equivalents. Note that
|
||||||
|
* if a value outside of range is passed it will perform '% 10'
|
||||||
|
* on that value and the last decimal digit will be used.
|
||||||
|
*
|
||||||
|
* @return A char* to the string values of '.0' to '.9'
|
||||||
|
*/
|
||||||
|
const char* get_font_point_str(int val);
|
||||||
|
|
||||||
|
#endif // FONT_H
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from PIL import Image, ImageOps
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
CHAR_WIDTH = 8
|
||||||
|
CHAR_HEIGHT = 8
|
||||||
|
NUM_VERT_CHARS = 6
|
||||||
|
NUM_HORZ_CHARS = 16
|
||||||
|
WORD_SIZE = 32
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("-i", "--input", required=True, help="input file")
|
||||||
|
parser.add_argument("-o", "--output", required=True, help="output file")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
in_path = args.input
|
||||||
|
out_path = args.output
|
||||||
|
|
||||||
|
# The font is stored in a 4-bit colormap png and is made of a grid of
|
||||||
|
# 16x6 characters:
|
||||||
|
# |-------------16---------------|
|
||||||
|
# | [][][][][][][][][][][][][][][][]
|
||||||
|
# | [][][][][][][][][][][][][][][][]
|
||||||
|
# 6 [][][][][][][][][][][][][][][][]
|
||||||
|
# | [][][][][][][][][][][][][][][][]
|
||||||
|
# | [][][][][][][][][][][][][][][][]
|
||||||
|
# | [][][][][][][][][][][][][][][][]
|
||||||
|
#
|
||||||
|
# Each character is a bitmap of 8x8 pixels.
|
||||||
|
#
|
||||||
|
# For example, the ! :
|
||||||
|
#
|
||||||
|
# ___00___
|
||||||
|
# ___00___
|
||||||
|
# ___00___
|
||||||
|
# ___00___
|
||||||
|
# ___00___
|
||||||
|
# ___00___
|
||||||
|
# ________
|
||||||
|
# ___00___
|
||||||
|
#
|
||||||
|
# The font file is organized to go character-by-character and left-to-right
|
||||||
|
|
||||||
|
img = Image.open(in_path)
|
||||||
|
img = img.convert("P")
|
||||||
|
img = img.convert('1')
|
||||||
|
img = ImageOps.invert(img)
|
||||||
|
|
||||||
|
glyphs = []
|
||||||
|
for char_y in range(NUM_VERT_CHARS):
|
||||||
|
for char_x in range(NUM_HORZ_CHARS):
|
||||||
|
# Get the 8x8 crop area at our current character in the image
|
||||||
|
pix_x = char_x * CHAR_WIDTH
|
||||||
|
pix_y = char_y * CHAR_HEIGHT
|
||||||
|
crop_area = (pix_x, pix_y, pix_x + CHAR_WIDTH, pix_y + CHAR_HEIGHT)
|
||||||
|
|
||||||
|
pixel_block_img = img.crop(crop_area)
|
||||||
|
pixels = list(pixel_block_img.getdata())
|
||||||
|
|
||||||
|
word0 = 0
|
||||||
|
word1 = 0
|
||||||
|
for i, pixel in enumerate(pixels):
|
||||||
|
bit = 1 if pixel > 0 else 0
|
||||||
|
if i < WORD_SIZE:
|
||||||
|
word0 = word0 | (bit << i)
|
||||||
|
else:
|
||||||
|
word1 = word1 | (bit << (i - WORD_SIZE))
|
||||||
|
glyphs.append((word0, word1))
|
||||||
|
|
||||||
|
NUM_WORDS_IN_ROW = 8
|
||||||
|
first = True
|
||||||
|
|
||||||
|
with open(out_path, "w") as out:
|
||||||
|
out.write("""
|
||||||
|
|
||||||
|
@{{BLOCK(gbalatro_sys8)
|
||||||
|
|
||||||
|
.section .rodata
|
||||||
|
.align 2
|
||||||
|
.global gbalatro_sys8Font
|
||||||
|
gbalatro_sys8Font:
|
||||||
|
.word gbalatro_sys8Glyphs, 0, 0
|
||||||
|
.hword 32, 96
|
||||||
|
.byte 8, 8
|
||||||
|
.byte 8, 8
|
||||||
|
.hword 8
|
||||||
|
.byte 1, 0
|
||||||
|
|
||||||
|
.section .rodata
|
||||||
|
.align 2
|
||||||
|
.global gbalatro_sys8Glyphs @ 768 bytes (192 unsigned ints)
|
||||||
|
gbalatro_sys8Glyphs:
|
||||||
|
""")
|
||||||
|
|
||||||
|
for i, glyph in enumerate(glyphs):
|
||||||
|
if first:
|
||||||
|
out.write(" .word ")
|
||||||
|
first = False
|
||||||
|
|
||||||
|
out.write(f"0x{glyph[0]:08X},0x{glyph[1]:08X}")
|
||||||
|
|
||||||
|
# This checks to see if we have reached NUM_WORDS_IN_ROW words, (divided by
|
||||||
|
# 2 because that's the number of entries in each char[])
|
||||||
|
if (((i + 1) % (NUM_WORDS_IN_ROW // 2)) == 0):
|
||||||
|
out.write("\n")
|
||||||
|
if i != (len(glyphs) - 1):
|
||||||
|
out.write(" .word ")
|
||||||
|
else:
|
||||||
|
out.write(",")
|
||||||
|
|
||||||
|
|
||||||
|
out.write("\n")
|
||||||
|
out.write("\n")
|
||||||
|
out.write('@}}BLOCK(gbalatro_sys8)\n')
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include "font.h"
|
||||||
|
|
||||||
|
#include "tonc.h"
|
||||||
|
|
||||||
|
static const char* s_font_point_lookup[] = {
|
||||||
|
XSTR(FP0_CHAR),
|
||||||
|
XSTR(FP1_CHAR),
|
||||||
|
XSTR(FP2_CHAR),
|
||||||
|
XSTR(FP3_CHAR),
|
||||||
|
XSTR(FP4_CHAR),
|
||||||
|
XSTR(FP5_CHAR),
|
||||||
|
XSTR(FP6_CHAR),
|
||||||
|
XSTR(FP7_CHAR),
|
||||||
|
XSTR(FP8_CHAR),
|
||||||
|
XSTR(FP9_CHAR),
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* get_font_point_str(int val)
|
||||||
|
{
|
||||||
|
val = ABS(val) % 10;
|
||||||
|
return s_font_point_lookup[val];
|
||||||
|
}
|
||||||
+2
-1
@@ -1,6 +1,7 @@
|
|||||||
#include "affine_background.h"
|
#include "affine_background.h"
|
||||||
#include "blind.h"
|
#include "blind.h"
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
|
#include "font.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "graphic_utils.h"
|
#include "graphic_utils.h"
|
||||||
#include "joker.h"
|
#include "joker.h"
|
||||||
@@ -31,7 +32,7 @@ void init()
|
|||||||
0,
|
0,
|
||||||
CLR_WHITE,
|
CLR_WHITE,
|
||||||
TTE_BIT_UNPACK_OFFSET,
|
TTE_BIT_UNPACK_OFFSET,
|
||||||
NULL,
|
&gbalatro_sys8Font,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
tte_erase_screen();
|
tte_erase_screen();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "splash_screen.h"
|
#include "splash_screen.h"
|
||||||
|
|
||||||
|
#include "font.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "graphic_utils.h"
|
#include "graphic_utils.h"
|
||||||
#include "maxmod.h"
|
#include "maxmod.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user