diff --git a/.gitignore b/.gitignore index 178c82c..eb17b6f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ res/mai.data tools/ttf-convert tools/ttf-bitmap +tools/ttf_bitmap2 common/keyboard.cpp common/keyboard.hpp wordle/word_list.hpp \ No newline at end of file diff --git a/Makefile b/Makefile index 5aa96a8..8654775 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,9 @@ include $(LIB)/common.mk %.data.o: %.data $(BUILD_BINARY_O) +%.data.h: %.data + $(BUILD_BINARY_H) + %.pattern.o: %.pattern $(BUILD_BINARY_O) @@ -52,6 +55,8 @@ vdp2/nbg0.elf: vdp2/nbg0.o res/butterfly.data.o res/butterfly.data.pal.o vdp2/nbg0_16color.elf: vdp2/nbg0_16color.o res/kirby.data.o res/kirby.data.pal.o +vdp2/nbg0_font.elf: vdp2/nbg0_font.o font/hp_100lx_4bit.data.o + vdp2/color_calculation_ratio.elf: vdp2/color_calculation_ratio.o res/mai00.data.o res/mai.data.pal.o res/haohmaru.data.o res/haohmaru.data.pal.o res/forest.data.pal.o res/forest.pattern.o res/forest.tile.o vdp2/line_color_screen.elf: vdp2/line_color_screen.o $(LIBGCC) diff --git a/tools/ttf_bitmap2.cpp b/tools/ttf_bitmap2.cpp new file mode 100644 index 0000000..c61b3b8 --- /dev/null +++ b/tools/ttf_bitmap2.cpp @@ -0,0 +1,155 @@ +#include +#include +#include + +#include +#include FT_FREETYPE_H + +int +load_bitmap_char(FT_Face face, + FT_ULong char_code, + uint8_t * buf) +{ + FT_Error error; + FT_UInt glyph_index = FT_Get_Char_Index(face, char_code); + + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if (error) { + fprintf(stderr, "FT_Load_Glyph %s\n", FT_Error_String(error)); + return -1; + } + + printf("horiBearingX: %ld\n", face->glyph->metrics.horiBearingX >> 6); + printf("horiBearingY: %ld\n", face->glyph->metrics.horiBearingY >> 6); + printf("horiAdvance: %ld\n", face->glyph->metrics.horiAdvance >> 6); + printf("width: %ld\n", face->glyph->metrics.width >> 6); + printf("height: %ld\n", face->glyph->metrics.height >> 6); + + assert(face->glyph->format == FT_GLYPH_FORMAT_BITMAP); + assert(face->glyph->bitmap.num_grays == 2); + + for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) { + uint8_t * row = &face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch]; + for (int x = 0; x < (int)face->glyph->bitmap.width; x += 1) { + const int bit = (row[x / 8] >> (7 - (x % 8))) & 1; + //std::cerr << (bit ? "█" : " "); + buf[y * face->glyph->bitmap.width + x] = bit; + } + //std::cerr << "|\n"; + } + + return face->glyph->bitmap.rows * face->glyph->bitmap.width; +} + +int load_font(FT_Library * library, FT_Face * face, const char * font_file_path) +{ + FT_Error error; + + error = FT_Init_FreeType(library); + if (error) { + fprintf(stderr, "FT_Init_FreeType\n"); + return -1; + } + + error = FT_New_Face(*library, font_file_path, 0, face); + if (error) { + fprintf(stderr, "FT_New_Face\n"); + return -1; + } + + error = FT_Select_Size(*face, 0); + if (error) { + fprintf(stderr, "FT_Select_Size: %d: %s\n", error, FT_Error_String(error)); + return -1; + } + + return 0; +} + +void usage(const char * argv_0) +{ + printf("%s [start-hex] [end-hex] [font-width] [font-height] [font-file-path] [output-file-path]\n", argv_0); +} + +void pack_4bit(const uint8_t * src, int width, int height, int size, uint8_t * dst) +{ + int offset = 0; + while (offset < size) { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x += 2) { + int px0 = src[offset + y * width + x + 0]; + int px1 = src[offset + y * width + x + 1]; + dst[(offset / 2) + y * (width / 2) + (x / 2)] = (px0 << 4) | (px1 << 0); + } + } + offset += width * height; + } +} + +int main(int argc, const char * argv[]) +{ + if (argc != 7) { + usage(argv[0]); + return -1; + } + + char * endptr; + + int start_hex = strtol(argv[1], &endptr, 16); + assert(*endptr == 0); + int end_hex = strtol(argv[2], &endptr, 16); + assert(*endptr == 0); + + int font_width = strtol(argv[3], &endptr, 10); + assert(*endptr == 0); + int font_height = strtol(argv[4], &endptr, 10); + assert(*endptr == 0); + + const char * font_file_path = argv[5]; + const char * output_file_path = argv[6]; + + printf("start_hex %x\n", start_hex); + printf("end_hex %x\n", start_hex); + printf("font_width %d\n", font_width); + printf("font_height %d\n", font_height); + printf("font_file_path %s\n", font_file_path); + printf("output_file_path %s\n", output_file_path); + + FT_Library library; + FT_Face face; + int res; + res = load_font(&library, &face, font_file_path); + if (res < 0) + return -1; + + int texture_buf_size = font_width * font_height * ((end_hex - start_hex) + 1); + uint8_t * texture = (uint8_t *)malloc(texture_buf_size); + + int offset = 0; + + for (int char_code = start_hex; char_code <= end_hex; char_code++) { + assert(offset < texture_buf_size); + + res = load_bitmap_char(face, + char_code, + &texture[offset]); + if (res < 0) + return - 1; + + assert(res == font_width * font_height); + + offset += res; + } + + uint8_t * pack = (uint8_t *)malloc(texture_buf_size / 2); + pack_4bit(texture, font_width, font_height, offset, pack); + + FILE * out = fopen(output_file_path, "w"); + if (out == NULL) { + perror("fopen(w)"); + return -1; + } + //fwrite((void *)texture, texture_buf_size, 1, out); + fwrite((void *)pack, texture_buf_size / 2, 1, out); + fclose(out); +} diff --git a/vdp2/nbg0_font.cpp b/vdp2/nbg0_font.cpp new file mode 100644 index 0000000..69ed178 --- /dev/null +++ b/vdp2/nbg0_font.cpp @@ -0,0 +1,86 @@ +#include + +#include "vdp2.h" +#include "../common/vdp2_func.hpp" + +#include "font/hp_100lx_4bit.data.h" + +void cell_data() +{ + const uint32_t * start = reinterpret_cast(&_binary_font_hp_100lx_4bit_data_start); + const int size = reinterpret_cast(&_binary_font_hp_100lx_4bit_data_size); + + for (int i = 0; i < (size / 4); i++) { + vdp2.vram.u32[i] = start[i]; + } +} + +void palette_data() +{ + vdp2.cram.u16[0] = 0x0000; + vdp2.cram.u16[1] = 0xffff; +} + +void main() +{ + v_blank_in(); + + // DISP: Please make sure to change this bit from 0 to 1 during V blank. + vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE + | TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320); + + /* set the color mode to 5bits per channel, 1024 colors */ + vdp2.reg.RAMCTL = RAMCTL__CRMD__RGB_5BIT_1024 + | RAMCTL__VRAMD | RAMCTL__VRBMD; + + vdp2.reg.VRSIZE = 0; + + /* enable display of NBG0 */ + vdp2.reg.BGON = BGON__N0ON | BGON__N0TPON; + + /* set character format for NBG0 to palettized 16 color + set enable "cell format" for NBG0 + set character size for NBG0 to 1x1 cell */ + vdp2.reg.CHCTLA = CHCTLA__N0CHCN__16_COLOR + | CHCTLA__N0BMEN__CELL_FORMAT + | CHCTLA__N0CHSZ__1x1_CELL; + + /* plane size */ + vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1; + + /* map plane offset + 1-word: value of bit 6-0 * 0x2000 + 2-word: value of bit 5-0 * 0x4000 + */ + constexpr int plane_a = 1; + constexpr int plane_a_offset = plane_a * 0x4000; + + constexpr int page_size = 64 * 64 * 2; // N0PNB__1WORD (16-bit) + constexpr int plane_size = page_size * 1; + + vdp2.reg.CYCA0 = 0x0F44F99F; + vdp2.reg.CYCA1 = 0x0F44F99F; + vdp2.reg.CYCB0 = 0x0F44F99F; + vdp2.reg.CYCB1 = 0x0F44F99F; + + vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 + vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0 + + palette_data(); + cell_data(); + + vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD; + for (int i = 0; i < 64 * 64; i++) { + vdp2.vram.u32[(plane_a_offset / 4) + i] = ' ' - 0x20; + } + + const char * test = "conversion from 8"; + int ix = 0; + while (*test) { + uint8_t c = *test++; + vdp2.vram.u32[(plane_a_offset / 4) + ix++] = c - 0x20; + } + + while (1); +}