8 Bit fonts from C64 games

Previous topic - Next topic

fuzzy70

Quote!!!!! Could you share the source? I haven't found a font yet and being an Amiga fan still, I'd absolutely love to use an Amiga font in my game!

Sure, the reading of the font into types/array etc is complete, which was fun thanks to me forgetting that the Amiga was Big Endian & PC is Little Endian so data was not adding up right  :D.

I just need to finish off the code to plot the character & to tidy up the code a bit, its not messy but would like to put my functions in the type as to keep it more self contained.

BTW as it stands it will only convert normal b&w bitmap fonts, colour fonts are on the to-do list.  So are compugraphic/agfa when I track down some decent documentation as nothing useful in the RKM that I have found :(

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Ruidesco


fuzzy70

#17
Here is the basic Amiga font convertor r0ber7. Like I said it is still a work in hand project & the functions etc will be added into the TYPE as to make it a self contained unit. There are some extra variables & some debugging stuff in the code as well which will obviously be gone in the final version.

As it stands it will read a normal black & white Amiga bitmap font & display all the available chars on the screen ready to be saved out. Only the code to save the bitmap needs to be added ideally at the end of the printcharset sub which is just a simple createscreen & savesprite addition.

I was unsure if you was after the grid type format to use with GLB's print or a straight image strip format for your own print routine (if you are using one)

To use it just set the directory that contains the font files & change the open command to the file to open. Do not load a .font file as this does not contain the font data only stuff that's useful for an Amiga itself, the numbered files in their directories like 8,12 etc are the files that contain all the data. Also do not try to load a colour or compugraphic/agfa scable font as the data structures & functions are not yet implemented  ;)

I did have a couple of PD fonts that gave me trouble but they either wouldn't load on my Amiga (both real & emulator) or where packed in some way like powerpacker etc. I got the latter to work by opening them in a font editor on my Amiga & saving them straight out again.

Here is the code below & have also attached the code & some fonts as well.

Enjoy

Lee

Code (glbasic) Select
// --------------------------------- //
// Project: AmigafontReader
// Start: Friday, November 18, 2011
// IDE Version: 10.159

TYPE TAmigaFont
Ysize%
Style%
Flags%
Xsize%
Baseline%
Boldsmear%
Accessors%
LoChar%
HiChar%
CharData%
Modulo%
CharLoc%
CharSpace%
CharKern%
DataLength%
TotalLength%
TotalChars%
ENDTYPE

TYPE TAmigaGlyph
Width%
Height%
PointData%[]
ENDTYPE

GLOBAL ReadByteData%,Loop%,fh%,fw%,fl%=0,IsFileValid%=FALSE
GLOBAL GlyphLocation%[],GlyphWidth%[],GlyphSpace%[],GlyphKern%[],FontData%[]
GLOBAL WidestChar%
GLOBAL Font[] AS TAmigaFont
GLOBAL Glyph[] AS TAmigaGlyph
GLOBAL Fi AS TAmigaFont
LOCAL dir$

GETFONTSIZE fh,fw

DIM GlyphLocation[256]
DIM GlyphWidth[256]
DIM GlyphSpace[256]
DIM GlyphKern[256]

SETSCREEN 1024,768,0
SYSTEMPOINTER TRUE
// Note to myself. GLB uses "/" directory seperators not pc "\"

SETCURRENTDIR("media/2001") // go to media files
OPENFILE (1,"8",TRUE)

GOSUB validitycheck
IF IsFileValid
GOSUB getfontdetails
GOSUB printdetails
GOSUB readindata
ENDIF
CLOSEFILE 1

//printglyph(20,600,125)
GOSUB printcharset

SHOWSCREEN
MOUSEWAIT

SUB printcharset:
LOCAL GridX%=0,GridY%=0,GridStep%,Char%=0


GridStep=WidestChar+2
FOR GridY=0 TO 15*GridStep STEP GridStep
FOR GridX=0 TO 15*GridStep STEP GridStep
printglyph(GridX,GridY,Char%)

INC Char%,1
NEXT
NEXT
ENDSUB


FUNCTION printglyph: X%,Y%,Chr%,FontNo%=0
LOCAL ValidChar%=FALSE
LOCAL PointX%,PointY%,Bit%,YLine%=0
LOCAL GlyphW%,GlyphH%,GlyphL%

IF Chr<Font[FontNo].LoChar OR Chr>Font[FontNo].HiChar
RETURN ValidChar
ENDIF

GlyphW=GlyphWidth[Chr]
GlyphH=Font[FontNo].Ysize
GlyphL=GlyphLocation[Chr]

//CREATESCREEN 1,10,GlyphW,GlyphH
//USESCREEN 1
FOR PointY=0 TO GlyphH-1
FOR PointX=0 TO GlyphW-1
Bit=FontData[GlyphL+PointX+YLine]
IF Bit THEN SETPIXEL PointX+X,PointY+Y,RGB(255,255,255)
NEXT
INC YLine,Font[FontNo].Modulo*8
NEXT
//USESCREEN -1
//DRAWSPRITE 10,X,Y
ENDFUNCTION


SUB validitycheck:
LOCAL ValidFont%=(ASL(0x1a,16))+(ASL(0x0f,8))+0x80 // 0x1a0f80 is fontfile ID????
FILESEEK 1,49,0
IF ValidFont=readAmigabytes(3)
IsFileValid=TRUE
DEBUG "Font file is Valid"+"\n"
ELSE
DEBUG "Not a valid fontfile"+"\n"
ENDIF
ENDSUB

SUB getfontdetails:
FILESEEK 1,110,0
Fi.Ysize%=readAmigabytes(2)
Fi.Style%=readAmigabytes(1)
Fi.Flags%=readAmigabytes(1)
Fi.Xsize%=readAmigabytes(2)
Fi.Baseline%=readAmigabytes(2)
Fi.Boldsmear%=readAmigabytes(2)
Fi.Accessors%=readAmigabytes(2)
Fi.LoChar%=readAmigabytes(1)
Fi.HiChar%=readAmigabytes(1)
Fi.CharData%=readAmigabytes(4)
Fi.Modulo%=readAmigabytes(2)
Fi.CharLoc%=readAmigabytes(4)
Fi.CharSpace%=readAmigabytes(4)
Fi.CharKern%=readAmigabytes(4)
Fi.DataLength%=Fi.Modulo%*Fi.Ysize%
Fi.TotalChars%=Fi.HiChar%-Fi.LoChar%+2

// Next 3 Lines not needed for reading or plotting, purely for debugging
Fi.TotalLength%=(Fi.Modulo%*Fi.Ysize%+(Fi.HiChar%-Fi.LoChar%+2)*4)/2
IF Fi.CharSpace%<>0 THEN Fi.TotalLength%=Fi.TotalLength%+(Fi.HiChar%-Fi.LoChar%+2)
IF Fi.CharKern%<>0 THEN Fi.TotalLength%=Fi.TotalLength%+(Fi.HiChar%-Fi.LoChar%+2)
DIMPUSH Font[],Fi
ENDSUB

SUB printdetails:      //Used while debugging
DEBUG "Ysize%="+Font[0].Ysize%+"\n"
DEBUG "Style%="+Font[0].Style%+"\n"
DEBUG "Flags%="+Font[0].Flags%+"\n"
DEBUG "Xsize%="+Font[0].Xsize%+"\n"
DEBUG "Baseline%="+Font[0].Baseline%+"\n"
DEBUG "Boldsmear%="+Font[0].Boldsmear%+"\n"
DEBUG "Accessors%="+Font[0].Accessors%+"\n"
DEBUG "LoChar%="+Font[0].LoChar%+"\n"
DEBUG "HiChar%="+Font[0].HiChar%+"\n"
DEBUG "CharData%="+Font[0].CharData%+"\n"
DEBUG "Modulo%="+Font[0].Modulo%+"\n"
DEBUG "CharLoc%="+Font[0].CharLoc%+"\n"
DEBUG "CharSpace%="+Font[0].CharSpace%+"\n"
DEBUG "CharKern%="+Font[0].CharKern%+"\n"
DEBUG "DataLength%="+Font[0].DataLength%+"\n"
DEBUG "TotalLength%="+Font[0].TotalLength%+"\n"
DEBUG "TotalChars%="+Font[0].TotalChars%+"\n"
ENDSUB

SUB readindata:
// Amiga glpyhs are bitpacked so kerning, pixel data etc are stored sperately
// Example:
// loc1       loc2       loc3       loc4      etc
// V          V          V          V         V
// <width1>   <width2>   <width3>   <width4>
// <data1 >   <data2 >   <data3 >   <data4 >  <etc...> till end of characters then starts the next line
// <space1 >  <space2 >  <space3 >  <space4 >
//
// .######.   #######.   .#######   #######.
// #......#   #......#   #.......   #......#
// #......#   #......#   #.......   #......#
// ########   #######.   #.......   #......#
// #......#   #......#   #.......   #......#
// #......#   #......#   #.......   #......#
// #......#   #######.   .#######   #######.
// ........   ........   ........   ........
//        > <        > <        > <        > <
//       kern1      kern2      kern3      kern4


LOCAL GetWidestChar%=0,BitLoop%, BitSet%, BitMask%,FdCount%=0

// Read in font Location Data
// Amiga LONG, 1st word is where the location in FontData of the 1st pixel
// per glpyh is. 2nd word is the width in pixels of that glpyh
// NOTE: the width of the glyph excludes any spacing, thats stored elsewhere
FILESEEK 1,Font[0].CharLoc+32,0
FOR Loop=Font[0].LoChar TO Font[0].HiChar
ReadByteData=readAmigabytes(2)
GlyphLocation[Loop]=ReadByteData // Location in FontData
ReadByteData=readAmigabytes(2)
GlyphWidth[Loop]=ReadByteData // Width of glpyh
IF ReadByteData>GetWidestChar THEN GetWidestChar=ReadByteData
NEXT
WidestChar=GetWidestChar // The glpyh Xsize stored in the file is an average width

// Read in font Kern data
// Amgia kerning is not the same as Typography kerning
// Basically this is the amount of pixels after the glpyh
// used to space/seperate the glpyhs
// NOTE: not all fontfiles have this data
IF Font[0].CharKern%<>0
FILESEEK 1,Font[0].CharKern+32,0
FOR Loop=Font[0].LoChar TO Font[0].HiChar
ReadByteData=readAmigabytes(2)
GlyphKern[Loop]=ReadByteData
NEXT
ENDIF

// Read in font Space Data
// Essentially the same as the above but instead of amount
// of pixels to leave after a glpyh this is the amount of
// pixels of the glpyh data including the space
// NOTE: not all fontfiles have this data
IF Font[0].CharSpace%<>0
FILESEEK 1,Font[0].CharSpace+32,0
FOR Loop=Font[0].LoChar TO Font[0].HiChar
ReadByteData=readAmigabytes(2)
GlyphSpace[Loop]=ReadByteData
NEXT
ENDIF


// Read in the Fontdata (The actual pixels)
// top line of every glpyh is stored then the 2nd line etc
// this reads in a byte then stores each bit seperate in the
// Fontdata array.
REDIM FontData[Font[0].DataLength*8]
FILESEEK 1,Font[0].CharData+32,0
//  LOCAL dx%=0,dy%=300,dm%=Font[0].Modulo*8       // For debugging use
FOR Loop=0 TO Font[0].DataLength-1
BitMask=128
ReadByteData=readAmigabytes(1)
FOR BitLoop=0 TO 7
BitSet=bAND(ReadByteData,BitMask)
IF BitSet<>0
FontData[FdCount]=TRUE
//SETPIXEL dx,dy,RGB(255,255,255)    // For debugging use
ELSE
FontData[FdCount]=FALSE
ENDIF
BitMask=ASR(BitMask,1)
INC FdCount,1
// INC dx,1
// IF dx=dm // For debugging use
// dx=0
// INC dy,1
// ENDIF
NEXT
NEXT

ENDSUB

FUNCTION readAmigabytes: Bytes%
LOCAL ByteArray%[],ByteLoop%,ReturnVal%
REDIM ByteArray[4]

FOR ByteLoop=0 TO Bytes-1
READUBYTE 1,ByteArray[ByteLoop]
//DEBUG "Fileposition="+FILEPOSITION(1)+"\n"
NEXT
// Code below is basically a Amiga to PC endian convertor
SELECT Bytes
CASE 1
// This one not really needed but easier keeping all data reads in one function
ReturnVal=ByteArray[0]     
CASE 2
ReturnVal=(ASL(ByteArray[0],8))+ByteArray[1]
CASE 3
ReturnVal=(ASL(ByteArray[0],16))+(ASL(ByteArray[1],8))+ByteArray[2]
CASE 4
ReturnVal=(ASL(ByteArray[0],24))+(ASL(ByteArray[1],16))+(ASL(ByteArray[2],8))+ByteArray[3]
DEFAULT
ReturnVal=0
ENDSELECT
RETURN ReturnVal
ENDFUNCTION


[attachment deleted by admin]
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

r0ber7

Nice!  :good: I'll give it a go later. I'm thinking of two standard fonts, topaz or that font Amos used. Very basic black and white ones so no problem there. Then I'll probably edit the png in a pixel program, keeping the shape but adding tones and prettiness. :)

fuzzy70

#19
Take a look at the diamond 12 font, its included in the archive I posted & a nice clean looking font, might be to big for your needs though.

I have nearly worked out the header files for colour fonts as in how many bit planes etc, locating the palette structure is proving to be annoying. The Amiga RKM books are a pain to say the least some of the code is in C & some in Assembly, the latter I understand no problem as that's how I used to program the Amiga. Also the examples are missing some details of the flags or are incorrect which results in deciphering the raw include .h headers. If you understand the phrase "Pigeon English" then I have learnt "Pigeon C"  :D .

Also it looks like reading scalable Amiga fonts is a no-no as there is zero info on them, might be due to them being licensed from Agfa/Compugraphic. One way round though is just fire up the emulator & use the Intellifont program to generate a bitmap version at the required size.

Lee


[attachment deleted by admin]
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

r0ber7

Thanks to your magnificent code, I can now use emerald as the menu font for my game. I also like sapphire, but its style would be too distracting I think. Thank you!

A - z have been pixeled for extra smoothness.

[attachment deleted by admin]

fuzzy70

Would hardly class my code as magnificent, but glad it helped you out :)

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)