home *** CD-ROM | disk | FTP | other *** search
- *
- * Fast font Assembly sub-routines
- *
- * Copyright 1988 by Darren M. Greenwald
- *
- * Rev. 3.0 9/27/88
- *
- * New blitter based routine to handle any size font
- *
- * This new routine relies on the brute force approach, and the blitter!
- * The font data is unpacked, and the masking, shifting, and target
- * addresses are pre-calculate for speed.
- *
- * This version of the fast text routines can render fonts of any height,
- * and of any size from 4-16 pixels wide. Wider fonts, proportional fonts,
- * and styles are currently not supported.
- *
- * This routine is copyrighted, and freely distributable. It may not be
- * used in any commercial product, shareware product, or commercial
- * publication without permission. It is permissible to release this file
- * as part of a public domain collection, or on a telecommunication service
- * as long as no "special charge" is made for this program;
- * "special charge" does not include standard charges for replication
- * of the media, or use of the system.
- *
- * The intent of the above should be clear - I did the work, and am giving
- * the code away for free. While you may use it, you may not
- * profit from it.
- *
- * The previous fast text routines I released in 1987 were public domain
- * in every sense of the word. In order to use these routines in a
- * commercial, or shareware venture, you must ask permission - at the most
- * I may ask in return that you include credit for the use of these
- * routines within your program's documentation, and/or free registration, or
- * a copy of the software you are developing. In addition, I will provide
- * answers if you have any questions, and just maybe provide assistance
- * with modifying the routines to suit your needs. All I ask is that you
- * ask!
- *
-
- XDEF _InitFastText ;Declare these labels visible to linker
- XDEF _FreeFastText
- XDEF _FastText
-
- XREF _GfxBase
- XREF _LVOAllocMem
- XREF _LVOFreeMem
- XREF _LVOBltTemplate
- XREF _LVOText
- XREF _OwnBlitter
- XREF _DisownBlitter
- XREF _WaitBlit
-
- include "SYS2:asm/exec/types.i"
- include "SYS2:asm/graphics/text.i"
- include "SYS2:asm/hardware/blit.i"
- include "SYS2:asm/hardware/custom.i"
- include "SYS2:asm/graphics/rastport.i"
- CSEG
-
- * ---------------------------------------------------------------------
- * Call this routine to free any memory allocated by InitFastText()
- * below.
- *
- * This is a safe routine - it can be called safely even if InitFastText()
- * fails.
- * ---------------------------------------------------------------------
- _FreeFastText:
-
- MOVE.L FontData,D0 ;safety check for NULL ptr
- BEQ nodata
- MOVEA.L D0,A1 ;address of buffer to free
- MOVE.L FontSize,D0 ;size of buffer to free
- MOVEA.L $4,A6 ;ExecBase
- JSR _LVOFreeMem(A6)
- CLR.L FontData ;set to NULL
-
- nodata:
-
- MOVE.L Imagebuf,D0
- BEQ nobuf ;safety valve
- MOVEA.L D0,A1 ;address of buffer
- MOVE.L Imagesize,D0 ;size of working buffer
- MOVEA.L $4,A6
- JSR _LVOFreeMem(A6)
- CLR.L Imagebuf ;set to NULL
-
- nobuf: RTS
-
- * ---------------------------------------------------------------------
- * This routine does a few things for you.
- *
- * It checks to make sure the font size is within 4 bits wide, and 16
- * bits wide. It also checks for PROP fonts. Wider/thinner fonts, and
- * PROP fonts will cause this routine to fall through, and set up to
- * use Text() instead of the fast text routines. This is transparent, so
- * you do not have to write additional code to handle anything if
- * the FastText() routine cannot be used.
- *
- * It allocates 2 chip ram buffers - one for the unpacked font data,
- * and the other for an image buffer to draw in. The amount of space
- * required is calculated for you based on the font size per the pointer
- * to a TextFont structure which is passed via the stack.
- *
- * The font data is unpacked into words using an edge-to-edge model.
- * Extraneous bits are masked out, and the image data is left justified.
- *
- * The blitter masks, shifts, and destination addresses are pre-calcuated
- * for speed during rendering.
- *
- * An indirect function pointer is set-up based on the font width. 8 bit
- * wide fonts can be rendered faster then other fonts, so a special
- * blitter routine is devoted to handling 8 bit wide fonts. Often this is
- * the most common font, so it makes sense to use this capability.
- *
- * ---------------------------------------------------------------------
-
- font EQU 04 ;stack offset
-
- _InitFastText:
-
- MOVEA.L font(SP),A2 ;address of a text font struct
-
- TST.L tf_CharSpace(A2) ;is this a prop font?
- BNE Initfailed
-
- CLR.L D0
-
- MOVE.W tf_XSize(A2),D0
- MOVE.L D0,XSize ;save
- CMP.W #16,D0 ;check bounds of this
- BHI Initfailed
-
- MOVE.W tf_YSize(A2),D0
- MOVE.L D0,YSize ;save
- CMP.W #4,D0 ;check bounds of this
- BLT Initfailed
-
- MOVE.W tf_Baseline(A2),Baseline
-
- * allocate space for font imagery in unpacked word format - egads, this
- * uses a lot of memory, buts its the price to be paid I guess?
- *
-
- CLR.L FontData ;NULL by default
- CLR.L Imagebuf
-
- MULU #512,D0 ;1 WORD per line * 256 chars
- MOVE.L D0,FontSize ;save size of buffer
- MOVE.L #$10003,D1 ;MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR
- MOVEA.L $4,A6
- JSR _LVOAllocMem(A6) ;allocate space
- TST.L D0
- BEQ Initfailed ;no memory for font data
- MOVE.L D0,FontData ;save pointer
-
- * allocate an image buffer for me to draw text in
-
- MOVE.L YSize,D0
- MULU #128,D0 ;size of buffer calculated
- MOVE.L D0,Imagesize ;save size
- MOVEQ #03,D1 ;MEMF_PUBLIC|MEMF_CHIP
- MOVEA.L $4,A6
- JSR _LVOAllocMem(A6) ;allocate space
- TST.L D0
- BEQ NoImagebuf ;no memory for font data
- MOVE.L D0,Imagebuf ;save pointer
-
- * unpack font data
-
- MOVEA.L tf_CharLoc(A2),A0 ;location of offsets|width
- MOVEA.L tf_CharData(A2),A1
- MOVEA.L FontData,A3 ;where to put unpacked imagery
-
- CLR.L D0
- MOVE.B tf_LoChar(A2),D0
-
- CLR.L D1
- MOVE.B tf_HiChar(A2),D1
-
- SUB.B D0,D1 ;total # of chars to unpack
-
- LSL.L #1,D0 ;BYTE to WORD offset
- ADDA.L D0,A3 ;adjust pntr into image array now
-
- dounpack: MOVE.L (A0)+,D0 ;fetch offset|width of each char
-
- CLR.L D2
- MOVE.W D0,D2 ;width in D2
-
- SWAP D0 ;pix offset in D0
- CLR.L D3
- MOVE.W D0,D3 ;word offset in D3
-
- AND.L #$000F,D0
- LSR.W #4,D3 ;calc word offset
- LSL.W #1,D3
-
- CLR.L D4 ;create mask
- NOT.L D4 ;all ones!
- LSR.L D2,D4 ;mask for this character
- NOT.L D4 ;invert mask
-
- MOVE.L YSize,D5
- SUBQ.W #1,D5 ;-1 for DBF loop
- CLR.L D6
-
- unpkfont: MOVE.L 0(A1,D3.W),D7 ;create in D7
-
- LSL.L D0,D7 ;left justify?
- AND.L D4,D7 ;mask lower bits
- SWAP D7 ;move to lower word
-
- MOVE.W D7,0(A3,D6.L) ;store
-
- ADD.W tf_Modulo(A2),D3 ;adjust word offset
- ADD.L #512,D6
-
- DBF D5,unpkfont
-
- ADDQ.L #2,A3
-
- DBF D1,dounpack
-
- * set up arrays of pre-inited masks, shift values, and target addresses
-
- MOVE.W #DEST+SRCB+SRCA+$FC,D7
-
- MOVE.L XSize,D0
- CMP.W #08,D0 ;if equal to 8, use FASTEST mode!
- BNE docon0
- MOVEQ #00,D7 ;bltcon mask for bltcon1, or 0
-
- docon0:
-
- MOVE.W #255,D1 ;loop 256 times
- MOVEQ #00,D0 ;initial pixel offset
-
- MOVEA.L #masks,A0
- MOVEA.L #shift,A1
- MOVEA.L #local,A2
-
- MOVEQ #12,D5 ;shift value used later
- MOVE.L XSize,D6 ;used later
-
- setup: MOVE.L D0,D2
- MOVE.L D2,D3
-
- LSR.W #4,D2 ;calculate word offset
- LSL.W #1,D2 ; div by 16 * 2 for WORD offset
-
- AND.W #$000F,D3 ;mask out all but pix offset
-
- MOVE.L D2,D4
- ADD.L Imagebuf,D4 ;address to write this too
- MOVE.L D4,(A2)+ ;save address
-
- CLR.W D4 ;create mask
- NOT.W D4 ;all ones!
- LSR.W D3,D4 ;mask for this character
- NOT.W D4 ;invert mask
-
- MOVE.W D4,(A0)+ ;save mask
-
- LSL.W D5,D3 ;shift for bltcon format
- OR.W D7,D3 ;depends of con0, or con1
- MOVE.W D3,(A1)+ ;save shift
-
- ADD.L D6,D0
- DBF D1,setup
-
- * determine maximum # of characters which can be drawn
-
- MOVE.L XSize,D0
- MOVE.L #1008,D1
- DIVU D0,D1
- MOVE.W D1,Maxchars
-
- * set-up blitter control functions based on font width
- * optimize for 8 bit wide fonts!
-
- CMP.W #08,D0 ;if equal to 8, use FASTER mode!
- BEQ faster
-
- slower: MOVE.L #Bltslow,OutPut
- MOVEQ #2,D0 ;width
- BRA setsize
-
- faster: MOVE.L #Bltfast,OutPut
- MOVEQ #1,D0 ;width
-
- setsize: MOVE.L YSize,D1 ;height
- LSL.W #6,D1 ;per blitter's delight
- OR.W D1,D0
- MOVE.L D0,blitsize
-
- RTS ;return TRUE
-
-
- * some error, return false
-
- NoImagebuf: JSR _FreeFastText ;release alloced memory
-
- * indicates regular system Text() may be used via these calls
-
- Initfailed: CLR.L OutPut ;default to calling Text()
- MOVEQ #00,D0 ;return FALSE
- RTS
-
-
- * ---------------------------------------------------------------------
- * Routines to render the line via the blitter!
- *
- * The blitter routines vary somewhat to optimize for speed! 8 bit wide
- * fonts are drawn much faster then other width fonts, but all fonts
- * are drawn much faster then Text()! This makes sense to do this since
- * 8 bit wide fonts are the most common, and because I can make use of
- * some special blitter capabilities to speed the process along!
- * ---------------------------------------------------------------------
-
-
- rp EQU 0004 ;stack offsets
- txbptr EQU rp+4
- count EQU txbptr+4
-
- _FastText: TST.L OutPut
- BEQ CallText ;if InitFastText() failed!
-
- MOVE.L count(SP),D3
- BEQ Noway ;why would you put a 0 for # of chars?
- CMP.W Maxchars,D3
- BLS getblitter
- MOVE.W Maxchars,D3 ;prevent overflow
-
- * ok, I need that blitter for me only!
-
- getblitter: SUBQ.W #1,D3
- JSR _OwnBlitter
- JSR _WaitBlit
-
- * set-up globals first
-
- MOVEA.L txbptr(SP),A0
- MOVEM.L group,D4-D7/A1-A3
-
- * call appropriate routine
-
- MOVEA.L OutPut,A6
- JSR (A6)
-
- * free blitter for someone else
-
- JSR _DisownBlitter
-
- * now blast this into the rastport!
-
- MOVEA.L Imagebuf,A0 ;address of bitplane
- MOVEQ #00,D0 ;no offset
- MOVE.L #128,D1 ;src modulo
- MOVEA.L rp(SP),A1 ;rastport
- CLR.L D2
- MOVE.W rp_cp_x(A1),D2 ;x dest
- ADD.W D4,rp_cp_x(A1) ;modify Move() position
- CLR.L D3
- MOVE.W rp_cp_y(A1),D3 ;dest y
- SUB.W Baseline,D3 ;- baseline of font
- MOVE.L YSize,D5 ;y size
- MOVEA.L _GfxBase,A6
- JSR _LVOBltTemplate(A6)
- Noway: RTS
-
-
- * If InitFastText() failed, Text() may still be called via the
- * FastText() function.
- *
- * This makes use in a system which must use any size font easier to program.
- *
- CallText: MOVEA.L rp(SP),A1
- MOVEA.L txbptr(SP),A0
- MOVE.L count(SP),D0
- MOVEA.L _GfxBase,A6
- JSR _LVOText(A6)
- RTS
-
- * --------------------------------------------------
- * This is the faster logic for an 8 bit wide fonts!
- * --------------------------------------------------
- Bltfast: MOVEA.L #$dff000,A6 ;address of custom chips
-
- * once set, these blitter registers dont change
-
- MOVE.W #DEST+SRCB+SRCA+$FC,bltcon0(A6)
- MOVE.W #$FFFF,bltalwm(A6) ;no last word mask
- MOVE.W #126,bltdmod(A6)
- MOVE.W #126,bltamod(A6)
- MOVE.W #510,bltbmod(A6)
-
- * do as much set-up as possible while last blit is busy
-
- blit8: CLR.L D0
- MOVE.B (A0)+,D0
- BEQ blt8done ;terminate if NULL found
-
- LSL.W #1,D0 ;cast to WORD offset
- ADD.L D5,D0 ;ready with pointer!
-
- ADD.L D6,D4 ;add to width
-
- Wait8: BTST #6,dmaconr(A6) ;wait for last blit to complete
- BNE Wait8
-
- * these blitter register change for each blit
-
- MOVE.L D0,bltbpt(A6) ;b src
- MOVE.L (A3),bltdpt(A6) ;d src pntr
- MOVE.L (A3)+,bltapt(A6) ;a src pntr
- MOVE.W (A1)+,bltafwm(A6) ;first word mask
- MOVE.W (A2)+,bltcon1(A6) ;shift value for b
-
- MOVE.W D7,bltsize(A6) ;trigger blit
- DBF D3,blit8 ;char counter
-
- blt8done: RTS
-
- * --------------------------------------------------
- * This is the slower mode for odd width fonts!
- * --------------------------------------------------
- Bltslow: MOVEA.L #$dff000,A6 ;address of custom chips
- MOVEQ #00,D1 ;address of destination here
-
- * these registers dont change once set
-
- CLR.W bltalwm(A6) ;last word mask
- CLR.W bltcon1(A6) ;no special modes
- MOVE.W #124,bltbmod(A6) ;modulos
- MOVE.W #124,bltdmod(A6)
-
- * this bit clears the image buffer as needed - speed optimized
- * thinner fonts will be drawn faster due to less hits
- * a hit is TRUE whenever the font imagery rolls over into the next word
-
- doblits: MOVE.W (A1)+,D0
- MOVE.L (A3)+,D2
- CMP.L D2,D1
- BEQ dochars ;working on same word
-
- Waitlast: BTST #6,dmaconr(A6) ;wait if needed
- BNE Waitlast
-
- MOVE.L D2,D1 ;save for next time around
-
- MOVE.W #124,bltamod(A6)
- MOVE.W D0,bltafwm(A6)
- MOVE.L D2,bltdpt(A6) ;d src pntr
- MOVE.L D2,bltapt(A6) ;a src pntr
- MOVE.W #DEST+SRCA+$F0,bltcon0(A6) ;d=a
- MOVE.W D7,bltsize(A6) ;trigger blitter clear
-
- * setup while last blit is busy
-
- dochars: CLR.L D0
- MOVE.B (A0)+,D0
- BEQ bltodddone ;terminate if NULL found
-
- LSL.W #1,D0 ;cast to WORD offset
- ADD.L D5,D0 ;ready with pointer!
-
- ADD.L D6,D4 ;add to width
-
- Waitpack: BTST #6,dmaconr(A6) ;wait for image packing
- BNE Waitpack
-
- * set up blitter for character image move
-
- MOVE.W #508,bltamod(A6)
- MOVE.W #$FFFF,bltafwm(A6)
- MOVE.L D0,bltapt(A6) ;a src
- MOVE.L D2,bltbpt(A6) ;b src pntr
- MOVE.L D2,bltdpt(A6) ;d src pntr
- MOVE.W (A2)+,bltcon0(A6) ;shift value for a
- MOVE.W D7,bltsize(A6) ;trigger blit
-
- DBF D3,doblits ;checks count
-
- bltodddone: RTS
-
- RTS
-
-
- DSEG
- * global variables I use - private!
-
- Imagebuf: dc.l 0 ;address of image buffer - part of above struct
- Imagesize: ds.l 1 ;size of working buffer
-
- FontSize: ds.l 1 ;size of font data buffer
-
- YSize: ds.l 1 ;size of font height
-
- Maxchars: ds.w 1 ;Max chars which can be drawn at one time
-
- Baseline: ds.w 1 ;baseline of font
-
- OutPut: dc.l 0 ;address of function to call or NULL for Text()
-
- masks: ds.w 256 ;256 words for masks
- shift: ds.w 256 ;256 shift values
- local: ds.l 256 ;256 pointers to target location
-
- * these are grouped for a good reason - the MOVEM instruction is used
- * by the rendering routines for efficiency - DONT play with the order
- * of these unless you know what you are doing.
-
- group: dc.l 0 ;0 to init width of line register
- FontData: dc.l 0 ;address of font data
- XSize: dc.l 0 ;size of font width
- blitsize: dc.l 0 ;blit size value
- dc.l masks ;address of arrays
- dc.l shift
- dc.l local
-
-
- END
-
-