From de919cd1f7cad331d87f507f292ff83d4565290e Mon Sep 17 00:00:00 2001 From: gered Date: Sat, 6 Mar 2021 19:11:23 -0500 Subject: [PATCH] initial commit --- .gitignore | 6 + Makefile | 106 ++++++++++++++++ README.md | 10 ++ src/gxfb.c | 338 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/gxfb.h | 36 ++++++ src/main.c | 72 +++++++++++ src/vgafont.c | 133 ++++++++++++++++++++ src/vgafont.h | 7 ++ 8 files changed, 708 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 src/gxfb.c create mode 100644 src/gxfb.h create mode 100644 src/main.c create mode 100644 src/vgafont.c create mode 100644 src/vgafont.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6df2ab3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +obj/ +.idea/ +*.dol +*.elf +*.map + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c3b8ce2 --- /dev/null +++ b/Makefile @@ -0,0 +1,106 @@ +ifeq ($(strip $(DEVKITPRO)),) +$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro") +endif +ifeq ($(strip $(DEVKITPPC)),) +$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") +endif + +# ------------------------------------------------------------------------------ +TARGET := gc-gx-fb + +# ------------------------------------------------------------------------------ +# source file location(s), include/lib dirs, libraries to use +SRC_DIR := src +INCLUDE_DIRS := + +LIB_DIRS = -L$(LIBOGC_LIB_DIR) +LIBS = -ldb $(PLATFORM_LIBS) + +# ------------------------------------------------------------------------------ +# compiler/linker flags + +INCLUDES = -I$(DEVKITPRO)/libogc/include $(foreach dir,$(INCLUDE_DIRS),-I$(dir)) + +CFLAGS = -g -O0 $(MACHDEP) $(INCLUDES) +CXXFLAGS = $(CFLAGS) +AFLAGS = +LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map $(LIB_DIRS) $(LIBS) + +# ------------------------------------------------------------------------------ +# finding all source files to be compiled and where to place object files + +SRC_FILES := $(shell find $(SRC_DIR) -type f) +SRC_FILES := $(filter $(addprefix %, .cpp .c .s), $(SRC_FILES)) + +OBJ_DIR := obj +OBJ_FILES := $(addprefix $(OBJ_DIR)/, $(addsuffix .o, $(SRC_FILES))) +OBJ_DIRS := $(sort $(dir $(OBJ_FILES))) + +DEPS_DIR := $(OBJ_DIR) +DEPENDS := $(OBJ_FILES:.o=.d) + +# ------------------------------------------------------------------------------ + +.SUFFIXES: +.PHONY: clean run + +all: $(TARGET).dol + +$(TARGET).dol: $(TARGET).elf + +$(TARGET).elf: $(OBJ_FILES) + +clean: + rm -f $(TARGET).dol + rm -f $(TARGET).elf + rm -f $(TARGET).elf.map + rm -rf $(OBJ_DIR) + +run: $(TARGET).dol + $(DEVKITPRO)/tools/bin/wiiload $(TARGET).dol + +# ------------------------------------------------------------------------------ +# compiler/toolchain related stuff + +ifeq ($(PLATFORM),cube) +MACHDEP = -DGEKKO -mogc -mcpu=750 -meabi -mhard-float +LIBOGC_LIB_DIR = $(DEVKITPRO)/libogc/lib/cube +PLATFORM_LIBS = -lfat -logc -lm +else +MACHDEP = -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float +LIBOGC_LIB_DIR = $(DEVKITPRO)/libogc/lib/wii +PLATFORM_LIBS = -lwiiuse -lbte -lfat -logc -lm +endif + +CC := $(DEVKITPPC)/bin/powerpc-eabi-gcc +CXX := $(DEVKITPPC)/bin/powerpc-eabi-g++ +AS := $(DEVKITPPC)/bin/powerpc-eabi-as +LD := $(DEVKITPPC)/bin/powerpc-eabi-gcc +OBJCOPY := $(DEVKITPPC)/bin/powerpc-eabi-objcopy +ELF2DOL := $(DEVKITPRO)/tools/bin/elf2dol +BIN2S := $(DEVKITPRO)/tools/bin/bin2s + +# ------------------------------------------------------------------------------ +# standard compilation for the supported source file types, and binary linking + +$(OBJ_DIR)/%.cpp.o: %.cpp + @mkdir -p $(dir $@) + $(CXX) -MMD -MP -MF $(DEPS_DIR)/$*.d $(CXXFLAGS) -c $< -o $@ + +$(OBJ_DIR)/%.c.o: %.c + @mkdir -p $(dir $@) + $(CC) -MMD -MP -MF $(DEPS_DIR)/$*.d $(CFLAGS) -c $< -o $@ + +$(OBJ_DIR)/%.s.o: %s + @mkdir -p $(dir $@) + $(CC) -MMD -MP -MF $(DEPS_DIR)/$*.d -x assembler-with-cpp $(AFLAGS) -c$< -o $@ + +%.elf: + $(LD) $^ $(LDFLAGS) -o $@ + +%.dol: %.elf + $(ELF2DOL) $< $@ + +# ------------------------------------------------------------------------------ + +-include $(DEPENDS) diff --git a/README.md b/README.md new file mode 100644 index 0000000..8d077c4 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Gamecube GX-based RGB Framebuffer Example + +Just a simple example of using a GX ARGB-format texture as a means to render a "software" pixel framebuffer +quickly. Most applications won't care about such a thing, but this can be nice if you want low-level per-pixel access +in your code (e.g. MS-DOS Mode 13h style). + +If you want to access pixels using RGB, this is significantly better than using the XFB/EFB buffer, where the pixel +data uses YUV color space. + +Probably there could be a number of improvements made to this ... I'm not well versed in the GX API. diff --git a/src/gxfb.c b/src/gxfb.c new file mode 100644 index 0000000..d082f11 --- /dev/null +++ b/src/gxfb.c @@ -0,0 +1,338 @@ +#include "gxfb.h" + +#include +#include +#include +#include + +#include "vgafont.h" + +#define DEFAULT_FIFO_SIZE 256 * 1024 + +u32 *framebuffer = NULL; +int framebuffer_width = 0; +int framebuffer_height = 0; +int framebuffer_left; +int framebuffer_top; +int framebuffer_right; +int framebuffer_bottom; +size_t framebuffer_size = 0; + +static u32 *xfb[2] = { NULL, NULL }; +static int current_xfb = 0; +static void *gpfifo = NULL; + +static size_t texture_image_size = 0; +static u32 *texture_image = NULL; +static GXTexObj texture; + +static int quad_x_offset = 0; +static int quad_y_offset = 0; + +static Mtx44 perspective; +static Mtx modelview; + +static char printf_buffer[1024]; + +static void gx_copyxfb(void) { + GX_CopyDisp(xfb[current_xfb], GX_TRUE); + VIDEO_SetNextFramebuffer(xfb[current_xfb]); + current_xfb ^= 1; +} + +static void video_init(GXRModeObj *rmode) { + VIDEO_Init(); + + xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); + xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); + + VIDEO_Configure(rmode); + VIDEO_SetNextFramebuffer(xfb[0]); + VIDEO_SetBlack(FALSE); + VIDEO_Flush(); + VIDEO_WaitVSync(); + if (rmode->viTVMode & VI_NON_INTERLACE) + VIDEO_WaitVSync(); + + current_xfb = 1; +} + +static void gx_init(GXRModeObj *rmode, GXColor clearColor) { + gpfifo = aligned_alloc(32, DEFAULT_FIFO_SIZE); + memset(gpfifo, 0, DEFAULT_FIFO_SIZE); + + GX_Init(gpfifo, DEFAULT_FIFO_SIZE); + + GX_SetCopyClear(clearColor, GX_MAX_Z24); + + GX_InvVtxCache(); + GX_ClearVtxDesc(); + + // define various view properties, like the viewport, scissor(clipping), efb/xfb dimensions, filters ... + GX_SetViewport(0, 0, rmode->fbWidth, rmode->efbHeight, 0, 1); + GX_SetDispCopyYScale((f32) rmode->xfbHeight / (f32) rmode->efbHeight); + GX_SetScissor(0, 0, rmode->fbWidth, rmode->efbHeight); + GX_SetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight); + GX_SetDispCopyDst(rmode->fbWidth, rmode->xfbHeight); + GX_SetCopyFilter(rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->vfilter); + GX_SetFieldMode(rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE)); + + if (rmode->aa) + GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); + else + GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); + + GX_SetCullMode(GX_CULL_NONE); + gx_copyxfb(); + GX_SetDispCopyGamma(GX_GM_1_0); + + GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + GX_SetColorUpdate(GX_TRUE); +} + +static void gx_init_texture(int width, int height) { + texture_image_size = width * height * 4; + texture_image = aligned_alloc(32, texture_image_size); + memset(texture_image, 0, texture_image_size); + + GX_InvalidateTexAll(); + GX_InitTexObj(&texture, texture_image, width, height, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE); + GX_InitTexObjFilterMode(&texture, GX_NEAR, GX_NEAR); + GX_LoadTexObj(&texture, GX_TEXMAP0); +} + +static void gx_init_vertex_format(void) { + // 2D X/Y + texture coordinates + + GX_ClearVtxDesc(); + GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); + GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_F32, 0); + GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); + + GX_SetNumChans(1); + GX_SetNumTexGens(1); + GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE); + GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY); +} + +static void gx_init_projection(GXRModeObj *rmode) { + // TODO: this is really only going to be appropriate for 240p-equivalent modes ... + guOrtho(perspective, 0, rmode->efbHeight - 1, 0, (rmode->fbWidth / 2) - 1, 0, 300); + GX_LoadProjectionMtx(perspective, GX_ORTHOGRAPHIC); +} + +static void copy_framebuffer_to_texture(void) { + // gamecube/wii texture memory is organized in 32-byte tiles. for 32-bit ARGB-format textures, as we are using, + // this means the 32-bit space comprises a 4x4 tile. so we need to copy our contiguous 2d source framebuffer + // and convert it on the fly to this 4x4 tile layout. + // however, one extra wrinkle is that for 32-bit ARGB-format textures, the 32-byte tile size actually only is + // large enough to hold half of a 4x4 tile. so, what the gamecube hardware does instead for 32-bit ARGB format is + // to split the pixels into two halves. the first 32-byte 4x4 tile holds pixel data containing alpha+red only, and + // the second 32-byte 4x4 tile holds pixel data containing green+blue only. + + // reading 4 source ARGB-format pixel rows per iteration + u16 *src_1 = (u16*)&framebuffer[0]; + u16 *src_2 = (u16*)&framebuffer[framebuffer_width]; + u16 *src_3 = (u16*)&framebuffer[framebuffer_width * 2]; + u16 *src_4 = (u16*)&framebuffer[framebuffer_width * 3]; + + // destination 16-bit AR-format (alpha+red) pixel destination rows + u16 *dst_ar_1 = (u16*)&texture_image[0]; + u16 *dst_ar_2 = (u16*)&texture_image[8/4]; + u16 *dst_ar_3 = (u16*)&texture_image[16/4]; + u16 *dst_ar_4 = (u16*)&texture_image[24/4]; + + // destination 16-bit GB-format (green+blue) pixel destination rows + u16 *dst_gb_1 = (u16*)&texture_image[32/4]; + u16 *dst_gb_2 = (u16*)&texture_image[40/4]; + u16 *dst_gb_3 = (u16*)&texture_image[48/4]; + u16 *dst_gb_4 = (u16*)&texture_image[56/4]; + + // work through the framebuffer in 4x4 pixel chunks + for (int y = 0; y < framebuffer_height; y += 4) { + for (int x = 0; x < framebuffer_width; x += 4) { + // each loop iteration copies an entire 4x4 pixel chunk + + // column 1 for all 4 rows + dst_ar_1[0] = src_1[0]; dst_gb_1[0] = src_1[1]; + dst_ar_2[0] = src_2[0]; dst_gb_2[0] = src_2[1]; + dst_ar_3[0] = src_3[0]; dst_gb_3[0] = src_3[1]; + dst_ar_4[0] = src_4[0]; dst_gb_4[0] = src_4[1]; + + // column 2 for all 4 rows + dst_ar_1[1] = src_1[2]; dst_gb_1[1] = src_1[3]; + dst_ar_2[1] = src_2[2]; dst_gb_2[1] = src_2[3]; + dst_ar_3[1] = src_3[2]; dst_gb_3[1] = src_3[3]; + dst_ar_4[1] = src_4[2]; dst_gb_4[1] = src_4[3]; + + // column 3 for all 4 rows + dst_ar_1[2] = src_1[4]; dst_gb_1[2] = src_1[5]; + dst_ar_2[2] = src_2[4]; dst_gb_2[2] = src_2[5]; + dst_ar_3[2] = src_3[4]; dst_gb_3[2] = src_3[5]; + dst_ar_4[2] = src_4[4]; dst_gb_4[2] = src_4[5]; + + // column 4 for all 4 rows + dst_ar_1[3] = src_1[6]; dst_gb_1[3] = src_1[7]; + dst_ar_2[3] = src_2[6]; dst_gb_2[3] = src_2[7]; + dst_ar_3[3] = src_3[6]; dst_gb_3[3] = src_3[7]; + dst_ar_4[3] = src_4[6]; dst_gb_4[3] = src_4[7]; + + // move right to the next 4x4 tile for source and dest + + src_1 += 8; + src_2 += 8; + src_3 += 8; + src_4 += 8; + + dst_ar_1 += 32; + dst_ar_2 += 32; + dst_ar_3 += 32; + dst_ar_4 += 32; + dst_gb_1 += 32; + dst_gb_2 += 32; + dst_gb_3 += 32; + dst_gb_4 += 32; + } + + // move down to the next 4x4 tile row for source (dest will be correct already) + src_1 += (framebuffer_width * 2) * 3; + src_2 += (framebuffer_width * 2) * 3; + src_3 += (framebuffer_width * 2) * 3; + src_4 += (framebuffer_width * 2) * 3; + } +} + +int fb_init(GXRModeObj *rmode, int width, int height) { + if (framebuffer) + return 1; + if (!rmode) + return 1; + if (width <= 0 || width > (rmode->fbWidth / 2)) + return 1; + if (height <= 0 || height > rmode->efbHeight) + return 1; + + video_init(rmode); + + GXColor clearColor = { .r = 0, .g = 0, .b = 0, .a = 0xff }; + gx_init(rmode, clearColor); + + gx_init_texture(width, height); + gx_init_vertex_format(); + gx_init_projection(rmode); + + // allocate application-accessible framebuffer. ARGB-format pixels + framebuffer_size = width * height * 4; + framebuffer = aligned_alloc(32, framebuffer_size); + framebuffer_width = width; + framebuffer_height = height; + framebuffer_left = 0; + framebuffer_top = 0; + framebuffer_right = framebuffer_width - 1; + framebuffer_bottom = framebuffer_height - 1; + memset(framebuffer, 0, framebuffer_size); + + // x/y offset for rending the quad. + // this will center it on screen if the framebuffer is smaller than the screen mode + quad_x_offset = ((rmode->fbWidth / 2) - width) / 2; + quad_y_offset = ((rmode->efbHeight) - height) / 2; + + // set up constant modelview matrix for rending our quad with + guMtxIdentity(modelview); + guMtxTransApply(modelview, modelview, 0.0, 0.0, -5.0); + GX_LoadPosMtxImm(modelview, GX_PNMTX0); + + return 0; +} + +void fb_flip(int wait_vsync) { + // update the texture's pixel data with the contents of the application-accessible framebuffer + copy_framebuffer_to_texture(); + DCFlushRange(texture_image, texture_image_size); + + // render the framebuffer-textured quad + GX_InvVtxCache(); + GX_InvalidateTexAll(); + + GX_Begin(GX_QUADS, GX_VTXFMT0, 4); + GX_Position2f32(quad_x_offset, quad_y_offset); + GX_TexCoord2f32(0.0, 0.0); + GX_Position2f32(quad_x_offset + framebuffer_width - 1, quad_y_offset); + GX_TexCoord2f32(1.0, 0.0); + GX_Position2f32(quad_x_offset + framebuffer_width - 1, quad_y_offset + framebuffer_height - 1); + GX_TexCoord2f32(1.0, 1.0); + GX_Position2f32(quad_x_offset, quad_y_offset + framebuffer_height - 1); + GX_TexCoord2f32(0.0, 1.0); + GX_End(); + + GX_DrawDone(); + + gx_copyxfb(); + GX_Flush(); + + VIDEO_Flush(); + if (wait_vsync) { + VIDEO_WaitVSync(); + } +} + +void fb_clear(u32 color) { + for (u32 i = 0; i < framebuffer_size; ++i) { + framebuffer[i] = color; + } +} + +static void blit_char(char c, int x, int y, u32 color) { + const u8 *work_char; + u8 bit_mask = 0x80; + u32 *ptr; + + work_char = &vgafont[(unsigned char)c * 8]; + + ptr = fb_pixel_ptr(x, y); + + for (int yc = 0; yc < 8; ++yc) { + bit_mask = 0x80; + for (int xc = 0; xc < 8; ++xc) { + if ((*work_char & bit_mask)) + ptr[xc] = color; + + bit_mask = (bit_mask >> 1); + } + + ptr += framebuffer_width; + ++work_char; + } +} + +void fb_printf(int x, int y, u32 color, const char *format, ...) { + va_list args; + va_start(args, format); + vsnprintf(printf_buffer, 1023, format, args); + va_end(args); + + printf_buffer[1023] = 0; + + int dx = x; + int dy = y; + + for (char *c = printf_buffer; *c; ++c) { + switch (*c) { + case '\n': + dx = x; + dy += 8; + break; + case '\r': + break; + case ' ': + dx += 8; + break; + default: + blit_char(*c, dx, dy, color); + dx += 8; + break; + } + } +} diff --git a/src/gxfb.h b/src/gxfb.h new file mode 100644 index 0000000..4ab84ae --- /dev/null +++ b/src/gxfb.h @@ -0,0 +1,36 @@ +#ifndef GXFB_H_INCLUDED +#define GXFB_H_INCLUDED + +#include + +#define RGB(r, g, b) ((255 << 24) | ((r) << 16) | ((g) << 8) | (b)) + +extern u32 *framebuffer; +extern int framebuffer_width; +extern int framebuffer_height; +extern int framebuffer_left; +extern int framebuffer_top; +extern int framebuffer_right; +extern int framebuffer_bottom; +extern size_t framebuffer_size; + +int fb_init(GXRModeObj *rmode, int width, int height); +void fb_flip(int wait_vsync); + +void fb_clear(u32 color); + +static inline u32* fb_pixel_ptr(int x, int y) { + return framebuffer + (y * framebuffer_width) + x; +} + +static inline void fb_pset(int x, int y, u32 color) { + *fb_pixel_ptr(x, y) = color; +} + +static inline u32 fb_pget(int x, int y) { + return *fb_pixel_ptr(x, y); +} + +void fb_printf(int x, int y, u32 color, const char *format, ...); + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..46aa622 --- /dev/null +++ b/src/main.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +#include "gxfb.h" + +int main(int argc, char *argv[]) { + DEBUG_Init(GDBSTUB_DEVICE_USB, 1); + //_break(); + + GXRModeObj *rmode; + s32 videoFormat = CONF_GetVideo(); + if (videoFormat == CONF_VIDEO_NTSC) + rmode = &TVNtsc240Ds; + else if (videoFormat == CONF_VIDEO_PAL) + rmode = &TVPal264Ds; + else if (videoFormat == CONF_VIDEO_MPAL) + rmode = &TVMpal240Ds; + else + return 1; + + if (fb_init(rmode, 320, 240)) + return 1; + + PAD_Init(); + + int x = 100, y = 100; + + while (1) { + PAD_ScanPads(); + + u32 pressed = PAD_ButtonsDown(0); + u32 held = PAD_ButtonsHeld(0); + + if (pressed & PAD_BUTTON_START) { + exit(0); + } + + if (held & PAD_BUTTON_UP) { + --y; + if (y < 0) + y = 0; + } + if (held & PAD_BUTTON_DOWN) { + ++y; + if (y > framebuffer_bottom) + y = framebuffer_bottom; + } + if (held & PAD_BUTTON_LEFT) { + --x; + if (x < 0) + x = 0; + } + if (held & PAD_BUTTON_RIGHT) { + ++x; + if (x > framebuffer_right) + x = framebuffer_right; + } + + fb_clear(RGB(32, 64, 128)); + + fb_printf(30, 30, RGB(255, 255, 0), "hello, world!"); + fb_printf(30, 40, RGB(255, 0, 255), "x = %d, y = %d\n", x, y); + + fb_pset(x, y, RGB(255, 255, 255)); + + fb_flip(true); + } + + return 0; +} diff --git a/src/vgafont.c b/src/vgafont.c new file mode 100644 index 0000000..afc3871 --- /dev/null +++ b/src/vgafont.c @@ -0,0 +1,133 @@ +const unsigned char vgafont[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, + 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, + 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, + 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, + 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, + 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, + 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, + 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, + 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, + 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, + 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, + 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, + 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x78, 0x78, 0x30, 0x00, 0x30, 0x00, + 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, + 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, + 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, + 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, + 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, + 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, + 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, + 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, + 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, + 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, + 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, + 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, + 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x7e, 0x00, + 0x7e, 0x60, 0x60, 0x78, 0x60, 0x60, 0x60, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, + 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, + 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7e, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, + 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, + 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, + 0xfc, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, + 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, + 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, + 0xfe, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, + 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, + 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, + 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, + 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, + 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, + 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, + 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, + 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, + 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, + 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, + 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, + 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x0c, 0x06, 0x7c, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0x7e, 0x81, 0x3c, 0x06, 0x3e, 0x66, 0x3b, 0x00, + 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, + 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0x78, 0x0c, 0x38, + 0x7e, 0x81, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, + 0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0xc6, 0x10, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, + 0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, 0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, + 0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, 0x78, 0x84, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, + 0x78, 0x84, 0x00, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, + 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, + 0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x30, 0xfc, 0x30, + 0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc3, 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, + 0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, + 0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x76, 0x00, + 0x00, 0xf8, 0x00, 0xb8, 0xcc, 0xcc, 0xcc, 0x00, 0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00, + 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, + 0x18, 0x00, 0x18, 0x18, 0x30, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, 0xc6, 0xcc, 0xd8, 0x36, 0x6b, 0xc2, 0x84, 0x0f, + 0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6d, 0xcf, 0x03, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00, + 0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00, 0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00, + 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, + 0xdb, 0xf6, 0xdb, 0x6f, 0xdb, 0x7e, 0xd7, 0xed, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, + 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, + 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, + 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, + 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00, 0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0, + 0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, + 0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00, + 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00, + 0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00, + 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00, 0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00, + 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0, + 0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, + 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00, + 0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00, + 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, + 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, + 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, + 0x58, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x70, 0x98, 0x30, 0x60, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + +}; + +const int vgafont_size = sizeof(vgafont); diff --git a/src/vgafont.h b/src/vgafont.h new file mode 100644 index 0000000..ac65064 --- /dev/null +++ b/src/vgafont.h @@ -0,0 +1,7 @@ +#ifndef VGAFONT_H_INCLUDED +#define VGAFONT_H_INCLUDED + +extern const unsigned char vgafont[]; +extern const int vgafont_size; + +#endif