From 56c40d351673b99d27f6231ef1b9dc608af082fc Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Wed, 23 Aug 2023 23:36:02 -0400 Subject: [PATCH] png2font: add png2font tool --- graphics/hgr/hgr_font_4am/Makefile | 14 +- graphics/hgr/hgr_font_4am/font_vmw_1x8.s | 177 +++++++++ graphics/hgr/hgr_font_4am/font_vmw_8_test.s | 95 +++++ .../hgr/hgr_font_4am/fonts/a2_lowercase.png | Bin 0 -> 803 bytes utils/hgr-utils/Makefile | 20 +- utils/hgr-utils/png2font.c | 365 ++++++++++++++++++ 6 files changed, 665 insertions(+), 6 deletions(-) create mode 100644 graphics/hgr/hgr_font_4am/font_vmw_1x8.s create mode 100644 graphics/hgr/hgr_font_4am/font_vmw_8_test.s create mode 100644 graphics/hgr/hgr_font_4am/fonts/a2_lowercase.png create mode 100644 utils/hgr-utils/png2font.c diff --git a/graphics/hgr/hgr_font_4am/Makefile b/graphics/hgr/hgr_font_4am/Makefile index e3919c79..060d0622 100644 --- a/graphics/hgr/hgr_font_4am/Makefile +++ b/graphics/hgr/hgr_font_4am/Makefile @@ -45,14 +45,24 @@ FONT_VMW_10_TEST: font_vmw_10_test.o ld65 -o FONT_VMW_10_TEST font_vmw_10_test.o -C $(LINKER_SCRIPTS)/apple2_6000.inc font_vmw_10_test.o: font_vmw_10_test.s \ - font_4am_condensed.s font_4am_condensed_data.s + font_vmw_condensed.s font_vmw_condensed_data.s ca65 -o font_vmw_10_test.o font_vmw_10_test.s -l font_vmw_10_test.lst +### + +FONT_VMW_8_TEST: font_vmw_8_test.o + ld65 -o FONT_VMW_8_TEST font_vmw_8_test.o -C $(LINKER_SCRIPTS)/apple2_6000.inc + +font_vmw_8_test.o: font_vmw_8_test.s \ + font_4am_condensed.s font_4am_condensed_data.s + ca65 -o font_vmw_8_test.o font_vmw_8_test.s -l font_vmw_8_test.lst + + ### clean: - rm -f *~ *.o *.lst HELLO BIOS_TEST FONT_4AM_TEST + rm -f *~ *.o *.lst HELLO BIOS_TEST FONT_4AM_TEST FONT_VMW_10_TEST FONT_VMW_8_TEST diff --git a/graphics/hgr/hgr_font_4am/font_vmw_1x8.s b/graphics/hgr/hgr_font_4am/font_vmw_1x8.s new file mode 100644 index 00000000..cc6157ad --- /dev/null +++ b/graphics/hgr/hgr_font_4am/font_vmw_1x8.s @@ -0,0 +1,177 @@ +;license:MIT +;(c) 2023 by 4am +; +; drawing routines for Million Perfect Tiles Condensed +; +; Public functions: +; - DrawCondensedString +; + +; VMW: commented, reformatted, minor changes, ca65 assembly + +;------------------------------------------------------------------------------ +; DrawCondensedString +; +; in: A/Y points to zero terminated string, with x-pos and y-pos at start +; out: clobbers all registers & flags +;------------------------------------------------------------------------------ +DrawCondensedString: + + ; store the string location + + sta OUTL + sty OUTH + + ldy #0 + lda (OUTL), Y ; get xpos + sta CH ; save the X column offset + iny + + lda (OUTL),Y ; get ypos + tay + + ; add two to string pointer + clc + lda OUTL + adc #2 + sta dcb_loop+1 + lda #0 + adc OUTH + sta dcb_loop+2 + + ; row0 + + lda hposn_low, Y ; get low memory offset + clc + adc CH ; add in x-coord + sta dcb_row0+4 + lda hposn_high, Y ; get high memory offset + sta dcb_row0+5 ; save it out + iny ; go to next row + + ; row1 + + lda hposn_low, Y + adc CH + sta dcb_row1+4 + lda hposn_high, Y + sta dcb_row1+5 + iny + + ; row2 + + lda hposn_low, Y + adc CH + sta dcb_row2+4 + lda hposn_high, Y + sta dcb_row2+5 + iny + + ; row3 + + lda hposn_low, Y + adc CH + sta dcb_row3+4 + lda hposn_high, Y + sta dcb_row3+5 + iny + + ; row4 + + lda hposn_low, Y + adc CH + sta dcb_row4+4 + lda hposn_high, Y + sta dcb_row4+5 + iny + + ; row5 + + lda hposn_low, Y + adc CH + sta dcb_row5+4 + lda hposn_high, Y + sta dcb_row5+5 + iny + + ; row6 + + lda hposn_low, Y + adc CH + sta dcb_row6+4 + lda hposn_high, Y + sta dcb_row6+5 + iny + + ; row7 + + lda hposn_low, Y + adc CH + sta dcb_row7+4 + lda hposn_high, Y + sta dcb_row7+5 + iny + + ; row8 + + lda hposn_low, Y + adc CH + sta dcb_row8+4 + lda hposn_high, Y + sta dcb_row8+5 + iny + + ; row9 + + lda hposn_low, Y + adc CH + sta dcb_row9+4 + lda hposn_high, Y + sta dcb_row9+5 + + ldx #0 +dcb_loop: +dcb_loop_smc: + ldy $FDFD, X ; load next char into Y + beq dcb_done + + ; unrolled loop to write out each line + +dcb_row0: + lda CondensedRow0-$19, Y ; get 1-byte font row + sta $FDFD, X ; write out to graphics mem +dcb_row1: + lda CondensedRow1-$19, Y + sta $FDFD, X +dcb_row2: + lda CondensedRow2-$19, Y + sta $FDFD, X +dcb_row3: + lda CondensedRow3-$19, Y + sta $FDFD, X +dcb_row4: + lda CondensedRow4-$19, Y + sta $FDFD, X +dcb_row5: + lda CondensedRow5-$19, Y + sta $FDFD, X +dcb_row6: + lda CondensedRow6-$19, Y + sta $FDFD, X +dcb_row7: + lda CondensedRow7-$19, Y + sta $FDFD, X +dcb_row8: + lda CondensedRow8-$19, Y + sta $FDFD, X +dcb_row9: + lda CondensedRow9-$19, Y + sta $FDFD, X + + inx ; move to next + bpl dcb_loop + +dcb_done: + + rts + diff --git a/graphics/hgr/hgr_font_4am/font_vmw_8_test.s b/graphics/hgr/hgr_font_4am/font_vmw_8_test.s new file mode 100644 index 00000000..5d0183eb --- /dev/null +++ b/graphics/hgr/hgr_font_4am/font_vmw_8_test.s @@ -0,0 +1,95 @@ +; Fake BIOS screen +; for another project + +.include "zp.inc" +.include "hardware.inc" + + +bios_test: + ;=================== + ; set graphics mode + ;=================== + jsr HOME + + bit HIRES + bit FULLGR + bit SET_GR + bit PAGE1 + + jsr build_tables + + ;=================== + ; Load graphics + ;=================== + + lda #graphics_data + sta ZX0_src+1 + + lda #$20 ; temporarily load to $2000 + + jsr full_decomp + + ; test 1 + + lda #test1 + jsr DrawCondensedString + + ; test 2 + + lda #test2 + jsr DrawCondensedString + + ; test 3 + + lda #test3 + jsr DrawCondensedString + + ; test 4 + + lda #test4 + jsr DrawCondensedString + + ; test 5 + + lda #test5 + jsr DrawCondensedString + + + +end: + jmp end + + +test1: + ; 0123456789012345678901234567890123456789 + .byte 0,100,"PACK MY BOX WITH FIVE DOZEN LIQUOR JUGS!",0 +test2: + .byte 0,150,"pack my box with five dozen liquor jugs?",0 +test3: + .byte 9,80,"This is a HGR font test.",0 +test4: + .byte 0,170,"0123456789)(*&^%$#@!`~<>,./';:[]{}\|_+=",0 +test5: + .byte 0,180,"@/\/\/\/\______ |",0 + + .include "font_vmw_condensed.s" + .include "font_vmw_condensed_data.s" + + .include "zx02_optim.s" + +graphics_data: + .incbin "graphics/a2_energy.hgr.zx02" + +hposn_low = $1713 ; 0xC0 bytes (lifetime, used by DrawLargeCharacter) +hposn_high = $1800 ; 0xC0 bytes (lifetime, used by DrawLargeCharacter) + + .include "hgr_table.s" + + diff --git a/graphics/hgr/hgr_font_4am/fonts/a2_lowercase.png b/graphics/hgr/hgr_font_4am/fonts/a2_lowercase.png new file mode 100644 index 0000000000000000000000000000000000000000..a8b8098ae0919217c11502683435266a20cb3e83 GIT binary patch literal 803 zcmV+;1Kj+HP)EX>4Tx04R}tkv&MmKpe$i(~3nZ4t5Z6$WWcyMMWHI6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx6k5c1aNLh~_a1le0HIZ5niWa{nr@rf zbV|$@R>l5Tgb_ptafD@N8FP}9f$#XbM}V()37+MD?$0r(7A*z@MB*efOq+OvcxKZ! zIPVijSw&Wf&xzwEU6A;Z>x##3oXai?JTq$Mvh&1IVzJ!AN)NM&sS!^T$5c(Hd?D|# z%6W^kR%@`%J^2eGMSW$N>omuZ#v+y=L4<+^s;I$6f>xar3t8Gv`S?d&zeFyDTvae~ zET9ezvg-%`gWug+rKw3TDUt&EUL5CR9O&N#+D*s#K6ae;2@re+uJo?I-U4PnNpE(w z*by+a4P0DzHDwRD+yO?O4B3=jDM(W&m4Np%`lbRfdF)P{9icx&Pf} zwXS13Kr(o5u=eMN#+bHNQH<95dh|#SGj^DEKT3otwKDU+z{-@W8EPw4CG!~dE==_> zI?KPArE`_fbxq~hOn#X5oTeS7N2IRI6Xr}4X$$ieCVOS#XU-~dn(Bn9(_>iW;K}Pm1(DD+IyRN{%JbflzEzp z&NBB+Rbd7m6~dfbdw=z>nkg~Q /* For FILE I/O */ +#include /* For strncmp */ +#include /* for open() */ +#include /* for lseek() */ +#include /* for file modes */ +#include /* free() */ + +#include + +#define OUTPUT_ORIGINAL 0 +#define OUTPUT_INTERLEAVE 1 +#define OUTPUT_BINARY 2 + +static int debug=0; + + +static int print_fancy_byte(int value) { + + int i,reversed; + + /* 0001 0111 -> X011 1010 */ + /* 7654 3210 -> 01 2345 */ + reversed=0; + for(i=0;i<8;i++) { + reversed|=(1<<(i-2))*(!!(value&(1<<(7-i)))); + } + + printf("\t.byte $%02X\t; ",reversed); + + for(i=0;i<5;i++) { + printf("%c",((1<<(4-i))&value)?'1':'0'); + } + printf(" X"); + for(i=0;i<7;i++) { + if (i==3) printf(" "); + printf("%c",((1<<(6-i))&reversed)?'1':'0'); + } + + printf("\n"); + return 0; +} + +static int print_interleave_byte(int value,int y) { + + int i,reversed; + + /* 0001 0111 -> X011 1010 */ + /* 7654 3210 -> 01 2345 */ + reversed=0; + for(i=0;i<8;i++) { + reversed|=(1<<(i-2))*(!!(value&(1<<(7-i)))); + } + + printf("\t.byte $%02X\t ; ",reversed); + if ((y>0x20) && (y<0x7f)) printf("%c",y); + printf("\n"); + + return 0; + +} +static int convert_color(int color) { + + int c=0; + + switch(color) { + + /* These use the questionable palette my older code used */ + /* Also handle the newer one */ + /* Bitflipped because HGR is backwards, woz is crazy */ + case 0x000000: c=0; break; /* black1 */ + case 0x1bcb01: c=2; break; /* bright green */ + case 0x14f53c: c=2; break; /* bright green */ + case 0xe434fe: c=1; break; /* magenta */ + case 0xe31e60: c=1; break; /* magenta */ + case 0xffffff: c=3; break; /* white1 */ + case 0xcd5b01: c=6; break; /* orange */ + case 0xff6a3c: c=6; break; /* orange */ + case 0x1b9afe: c=5; break; /* medium blue */ + case 0x14cffd: c=5; break; /* medium blue */ + + case 0x010101: c=4; break; /* black2 */ + case 0xfefefe: c=7; break; /* white2 */ + + default: + fprintf(stderr,"Unknown color %x\n",color); + break; + } + + return c; +} + + + +/* expects a PNG */ +static int loadpng(char *filename, + unsigned char **image_ptr, int *xsize, int *ysize) { + + int x,y; + int color; + FILE *infile; + unsigned char *image,*out_ptr; + int width, height; + int a2_color; + + png_byte bit_depth; + png_structp png_ptr; + png_infop info_ptr; + png_bytep *row_pointers; + png_byte color_type; + int row_bytes,bytes_per_pixel; + + unsigned char header[8]; + + /* open file and test for it being a png */ + infile = fopen(filename, "rb"); + if (infile==NULL) { + fprintf(stderr,"Error! Could not open %s\n",filename); + return -1; + } + + /* Check the header */ + fread(header, 1, 8, infile); + if (png_sig_cmp(header, 0, 8)) { + fprintf(stderr,"Error! %s is not a PNG file\n",filename); + return -1; + } + + /* initialize stuff */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fprintf(stderr,"Error create_read_struct\n"); + exit(-1); + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + fprintf(stderr,"Error png_create_info_struct\n"); + exit(-1); + } + + png_init_io(png_ptr, infile); + png_set_sig_bytes(png_ptr, 8); + + png_read_info(png_ptr, info_ptr); + + width = png_get_image_width(png_ptr, info_ptr); + height = png_get_image_height(png_ptr, info_ptr); + *xsize=width; + *ysize=height; + + color_type = png_get_color_type(png_ptr, info_ptr); + bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + if (width!=280) { + fprintf(stderr,"Unknown width %d\n",width); + return -1; + } + + if (height!=192) { + fprintf(stderr,"Unknown height %d\n",height); + return -1; + } + + image=calloc(width*height,sizeof(unsigned char)); + if (image==NULL) { + fprintf(stderr,"Error allocating image\n"); + return -1; + } + + if (debug) { + fprintf(stderr,"PNG: width=%d height=%d depth=%d\n", + width,height,bit_depth); + if (color_type==PNG_COLOR_TYPE_RGB) { + fprintf(stderr,"Type RGB\n"); + } + else if (color_type==PNG_COLOR_TYPE_RGB_ALPHA) { + fprintf(stderr,"Type RGBA\n"); + } + else if (color_type==PNG_COLOR_TYPE_PALETTE) { + fprintf(stderr,"Type palette\n"); + } + } + + /* If palette, expand to RGB automatically */ + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_expand(png_ptr); + } + + png_read_update_info(png_ptr, info_ptr); + + + row_bytes = png_get_rowbytes(png_ptr, info_ptr); + // *pChannels = (int)png_get_channels(png_ptr, info_ptr); + bytes_per_pixel=row_bytes/width; + + if (debug) { + fprintf(stderr,"Rowbytes=%d bytes per pixel=%d\n", + row_bytes,row_bytes/width); + } + + row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height); + for (y=0; y=argc) { + printf("ERROR: Was expecting filename!\n"); + exit(1); + } + + filename=strdup(argv[optind]); + +// memset(apple2_image,0,8192); + + if (loadpng(filename,&image,&xsize,&ysize)<0) { + fprintf(stderr,"Error loading png!\n"); + exit(-1); + } + + fprintf(stderr,"Loaded image %d by %d\n",xsize,ysize); + + /* for now, assume 5x8 font starting at 14,8 */ + for(row=0;row<4;row++) { + for(col=0;col<32;col++) { + for(y=0;y<8;y++) { + temp=0; + for(x=0;x<7;x++) { + if (image[ (((row*8)+y+8)*280)+(col*7)+x+14]) { + temp=temp|(1<<(6-x)); + } + } + font_data[(row*32)+col][y]=temp; + } + } + } + +// fwrite(apple2_image,8192,sizeof(unsigned char),stdout); + + /* old-fashioned output */ + if (output_type==OUTPUT_ORIGINAL) { + printf("hgr_font:\n"); + for(c=0x20;c<0x80;c++) { + printf("; %c $%02X\n",c,c); + for(y=0;y<8;y++) { + print_fancy_byte(font_data[c][y]); + } + } + } + else if (output_type==OUTPUT_INTERLEAVE) { + for(row=0;row<8;row++) { + printf("CondensedRow%d:\n",row); + for(y=0x19;y<0x80;y++) { + print_interleave_byte(font_data[y][row],y); + } + } + } + else if (output_type==OUTPUT_BINARY) { + fprintf(stderr,"ERROR! Binary not implemented yet\n"); + } + else { + fprintf(stderr,"ERROR! Unknown output\n"); + } + return 0; +}