home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff281.lzh / FarPrint / FastText.asm < prev    next >
Assembly Source File  |  1989-11-20  |  18KB  |  525 lines

  1. *
  2. * Fast font Assembly sub-routines
  3. * Copyright 1988 by Darren M. Greenwald
  4. *
  5. * Rev. 3.0 9/27/88
  6. *
  7. * New blitter based routine to handle any size font
  8. *
  9. * This new routine relies on the brute force approach, and the blitter!
  10. * The font data is unpacked, and the masking, shifting, and target
  11. * addresses are pre-calculated for speed.
  12. *
  13. * This version of the fast text routines can render fonts of any height,
  14. * and of any size from 4-16 pixels wide.  Wider fonts, proportional fonts,
  15. * and styles are currently not supported.
  16. *
  17. * This routine is copyrighted, and freely distributable.  It may not be
  18. * used in any commercial product, shareware product, or commercial
  19. * publication  without permission.  It is permissible to release this file
  20. * as part of a public domain collection, or on a telecommunication service
  21. * as long as no "special charge" is made for this program;
  22. * "special charge" does not include standard charges for replication
  23. * of the media, or use of the system.
  24. *
  25. * The intent of the above should be clear - I did the work, and am giving
  26. * the code away for free.  While you may use it, you may not
  27. * profit from it.
  28. *
  29. * The previous fast text routines I released in 1987 were public domain
  30. * in every sense of the word.  In order to use these routines in a
  31. * commercial, or shareware venture, you must ask permission - at the most
  32. * I may ask in return that you include credit for the use of these
  33. * routines within your program's documentation, and/or free registration, or
  34. * a copy of the software you are developing.  In addition, I will provide
  35. * answers if you have any questions, and just maybe provide assistance
  36. * with modifying the routines to suit your needs.  All I ask is that you
  37. * ask!
  38. *
  39.  
  40.             XDEF     _InitFastText   ;Declare these labels visible to linker
  41.             XDEF     _FreeFastText
  42.             XDEF     _FastText
  43.  
  44.             XREF     _GfxBase
  45.             XREF     _LVOAllocMem
  46.             XREF     _LVOFreeMem
  47.             XREF     _LVOBltTemplate
  48.             XREF     _LVOText
  49.             XREF     _OwnBlitter
  50.             XREF     _DisownBlitter
  51.             XREF     _WaitBlit
  52.  
  53.             include  "exec/types.i"
  54.             include  "graphics/text.i"
  55.             include  "hardware/blit.i"
  56.             include  "hardware/custom.i"
  57.             include  "graphics/rastport.i"
  58.             CSEG
  59.  
  60. * ---------------------------------------------------------------------
  61. * Call this routine to free any memory allocated by InitFastText() 
  62. * below.
  63. * This is a safe routine - it can be called safely even if InitFastText()
  64. * fails.
  65. * ---------------------------------------------------------------------
  66. _FreeFastText:
  67.  
  68.             MOVE.L   FontData,D0       ;safety check for NULL ptr
  69.             BEQ      nodata
  70.             MOVEA.L  D0,A1             ;address of buffer to free
  71.             MOVE.L   FontSize,D0       ;size of buffer to free
  72.             MOVEA.L  $4,A6             ;ExecBase
  73.             JSR      _LVOFreeMem(A6)
  74.             CLR.L    FontData          ;set to NULL
  75.  
  76. nodata:
  77.  
  78.             MOVE.L   Imagebuf,D0
  79.             BEQ      nobuf             ;safety valve
  80.             MOVEA.L  D0,A1             ;address of buffer
  81.             MOVE.L   Imagesize,D0      ;size of working buffer
  82.             MOVEA.L  $4,A6
  83.             JSR      _LVOFreeMem(A6)
  84.             CLR.L    Imagebuf          ;set to NULL
  85.  
  86. nobuf:      RTS
  87.  
  88. * ---------------------------------------------------------------------
  89. * This routine does a few things for you.
  90. *
  91. * It checks to make sure the font size is within 4 bits wide, and 16
  92. * bits wide.  It also checks for PROP fonts.  Wider/thinner fonts, and
  93. * PROP fonts will cause this routine to fall through, and set up to
  94. * use Text() instead of the fast text routines.  This is transparent, so
  95. * you do not have to write additional code to handle anything if
  96. * the FastText() routine cannot be used.
  97. *
  98. * It allocates 2 chip ram buffers - one for the unpacked font data,
  99. * and the other for an image buffer to draw in.  The amount of space
  100. * required is calculated for you based on the font size per the pointer
  101. * to a TextFont structure which is passed via the stack.
  102. *
  103. * The font data is unpacked into words using an edge-to-edge model.
  104. * Extraneous bits are masked out, and the image data is left justified.
  105. *
  106. * The blitter masks, shifts, and destination addresses are pre-calcuated
  107. * for speed during rendering.
  108. *
  109. * An indirect function pointer is set-up based on the font width.  8 bit
  110. * wide fonts can be rendered faster then other fonts, so a special
  111. * blitter routine is devoted to handling 8 bit wide fonts.  Often this is
  112. * the most common font, so it makes sense to use this capability.
  113. *
  114. * ---------------------------------------------------------------------
  115.  
  116. font        EQU      04       ;stack offset
  117.  
  118. _InitFastText:
  119.  
  120.             MOVEA.L  font(SP),A2       ;address of a text font struct
  121.  
  122.             TST.L    tf_CharSpace(A2)  ;is this a prop font?
  123.             BNE      Initfailed
  124.  
  125.             CLR.L    D0
  126.  
  127.             MOVE.W   tf_XSize(A2),D0
  128.             MOVE.L   D0,XSize          ;save
  129.             CMP.W    #16,D0            ;check bounds of this
  130.             BHI      Initfailed
  131.  
  132.             MOVE.W   tf_YSize(A2),D0
  133.             MOVE.L   D0,YSize          ;save
  134.             CMP.W    #4,D0             ;check bounds of this
  135.             BLT      Initfailed
  136.  
  137.             MOVE.W   tf_Baseline(A2),Baseline
  138.  
  139. * allocate space for font imagery in unpacked word format - egads, this
  140. * uses a lot of memory, buts its the price to be paid I guess?
  141. *
  142.  
  143.             CLR.L    FontData          ;NULL by default
  144.             CLR.L    Imagebuf
  145.  
  146.             MULU     #512,D0           ;1 WORD per line * 256 chars
  147.             MOVE.L   D0,FontSize       ;save size of buffer
  148.             MOVE.L   #$10003,D1        ;MEMF_PUBLIC|MEMF_CHIP|MEMF_CLEAR
  149.             MOVEA.L  $4,A6
  150.             JSR      _LVOAllocMem(A6)  ;allocate space
  151.             TST.L    D0
  152.             BEQ      Initfailed        ;no memory for font data
  153.             MOVE.L   D0,FontData       ;save pointer
  154.  
  155. * allocate an image buffer for me to draw text in
  156.  
  157.             MOVE.L   YSize,D0
  158.             MULU     #128,D0           ;size of buffer calculated
  159.             MOVE.L   D0,Imagesize      ;save size
  160.             MOVEQ    #03,D1            ;MEMF_PUBLIC|MEMF_CHIP
  161.             MOVEA.L  $4,A6
  162.             JSR      _LVOAllocMem(A6)  ;allocate space
  163.             TST.L    D0
  164.             BEQ      NoImagebuf        ;no memory for font data
  165.             MOVE.L   D0,Imagebuf       ;save pointer
  166.  
  167. * unpack font data
  168.  
  169.             MOVEA.L  tf_CharLoc(A2),A0 ;location of offsets|width
  170.             MOVEA.L  tf_CharData(A2),A1
  171.             MOVEA.L  FontData,A3       ;where to put unpacked imagery
  172.  
  173.             CLR.L    D0
  174.             MOVE.B   tf_LoChar(A2),D0
  175.  
  176.             CLR.L    D1
  177.             MOVE.B   tf_HiChar(A2),D1
  178.  
  179.             SUB.B    D0,D1             ;total # of chars to unpack
  180.  
  181.             LSL.L    #1,D0             ;BYTE to WORD offset
  182.             ADDA.L   D0,A3             ;adjust pntr into image array now
  183.  
  184. dounpack:   MOVE.L   (A0)+,D0          ;fetch offset|width of each char
  185.  
  186.             CLR.L    D2
  187.             MOVE.W   D0,D2             ;width in D2
  188.  
  189.             SWAP     D0                ;pix offset in D0
  190.             CLR.L    D3
  191.             MOVE.W   D0,D3             ;word offset in D3
  192.  
  193.             AND.L    #$000F,D0
  194.             LSR.W    #4,D3             ;calc word offset
  195.             LSL.W    #1,D3
  196.  
  197.             CLR.L    D4                ;create mask
  198.             NOT.L    D4                ;all ones!
  199.             LSR.L    D2,D4             ;mask for this character
  200.             NOT.L    D4                ;invert mask
  201.  
  202.             MOVE.L   YSize,D5
  203.             SUBQ.W   #1,D5             ;-1 for DBF loop
  204.             CLR.L    D6
  205.  
  206. unpkfont:   MOVE.L   0(A1,D3.W),D7     ;create in D7
  207.  
  208.             LSL.L    D0,D7             ;left justify?
  209.             AND.L    D4,D7             ;mask lower bits
  210.             SWAP     D7                ;move to lower word
  211.             
  212.             MOVE.W   D7,0(A3,D6.L)     ;store
  213.  
  214.             ADD.W    tf_Modulo(A2),D3  ;adjust word offset
  215.             ADD.L    #512,D6
  216.  
  217.             DBF      D5,unpkfont
  218.  
  219.             ADDQ.L   #2,A3
  220.  
  221.             DBF      D1,dounpack
  222.  
  223. * set up arrays of pre-inited masks, shift values, and target addresses
  224.  
  225.             MOVE.W   #DEST+SRCB+SRCA+$FC,D7
  226.  
  227.             MOVE.L   XSize,D0
  228.             CMP.W    #08,D0            ;if equal to 8, use FASTEST mode!
  229.             BNE      docon0
  230.             MOVEQ    #00,D7            ;bltcon mask for bltcon1, or 0
  231.  
  232. docon0:
  233.  
  234.             MOVE.W   #255,D1           ;loop 256 times
  235.             MOVEQ    #00,D0            ;initial pixel offset
  236.  
  237.             MOVEA.L  #masks,A0
  238.             MOVEA.L  #shift,A1
  239.             MOVEA.L  #local,A2
  240.  
  241.             MOVEQ    #12,D5            ;shift value used later
  242.             MOVE.L   XSize,D6          ;used later
  243.  
  244. setup:      MOVE.L   D0,D2
  245.             MOVE.L   D2,D3
  246.  
  247.             LSR.W    #4,D2             ;calculate word offset
  248.             LSL.W    #1,D2             ; div by 16 * 2 for WORD offset
  249.  
  250.             AND.W    #$000F,D3         ;mask out all but pix offset
  251.  
  252.             MOVE.L   D2,D4
  253.             ADD.L    Imagebuf,D4       ;address to write this too
  254.             MOVE.L   D4,(A2)+          ;save address
  255.  
  256.             CLR.W    D4                ;create mask
  257.             NOT.W    D4                ;all ones!
  258.             LSR.W    D3,D4             ;mask for this character
  259.             NOT.W    D4                ;invert mask
  260.  
  261.             MOVE.W   D4,(A0)+          ;save mask
  262.  
  263.             LSL.W    D5,D3             ;shift for bltcon format
  264.             OR.W     D7,D3             ;depends of con0, or con1
  265.             MOVE.W   D3,(A1)+          ;save shift
  266.  
  267.             ADD.L    D6,D0
  268.             DBF      D1,setup
  269.  
  270. * determine maximum # of characters which can be drawn
  271.  
  272.             MOVE.L   XSize,D0
  273.             MOVE.L   #1008,D1
  274.             DIVU     D0,D1
  275.             MOVE.W   D1,Maxchars
  276.  
  277. * set-up blitter control functions based on font width
  278. * optimize for 8 bit wide fonts!
  279.  
  280.             CMP.W    #08,D0            ;if equal to 8, use FASTER mode!
  281.             BEQ      faster
  282.  
  283. slower:     MOVE.L   #Bltslow,OutPut
  284.             MOVEQ    #2,D0             ;width
  285.             BRA      setsize
  286.  
  287. faster:     MOVE.L   #Bltfast,OutPut
  288.             MOVEQ    #1,D0             ;width
  289.  
  290. setsize:    MOVE.L   YSize,D1          ;height
  291.             LSL.W    #6,D1             ;per blitter's delight
  292.             OR.W     D1,D0
  293.             MOVE.L   D0,blitsize
  294.  
  295.             RTS                        ;return TRUE
  296.  
  297.  
  298. * some error, return false
  299.  
  300. NoImagebuf: JSR      _FreeFastText     ;release alloced memory
  301.  
  302. * indicates regular system Text() may be used via these calls
  303.  
  304. Initfailed: CLR.L    OutPut            ;default to calling Text()
  305.             MOVEQ    #00,D0            ;return FALSE
  306.             RTS
  307.  
  308.  
  309. * ---------------------------------------------------------------------
  310. * Routines to render the line via the blitter!
  311. *
  312. * The blitter routines vary somewhat to optimize for speed!  8 bit wide
  313. * fonts are drawn much faster then other width fonts, but all fonts
  314. * are drawn much faster then Text()!  This makes sense to do this since
  315. * 8 bit wide fonts are the most common, and because I can make use of
  316. * some special blitter capabilities to speed the process along!
  317. * ---------------------------------------------------------------------
  318.  
  319.  
  320. rp          EQU      0004        ;stack offsets
  321. txbptr      EQU      rp+4
  322. count       EQU      txbptr+4
  323.  
  324. _FastText:  TST.L    OutPut
  325.             BEQ      CallText    ;if InitFastText() failed!
  326.  
  327.             MOVE.L   count(SP),D3
  328.             BEQ      Noway       ;why would you put a 0 for # of chars?
  329.             CMP.W    Maxchars,D3
  330.             BLS      getblitter
  331.             MOVE.W   Maxchars,D3 ;prevent overflow
  332.  
  333. * ok, I need that blitter for me only!
  334.  
  335. getblitter: SUBQ.W   #1,D3
  336.             JSR      _OwnBlitter
  337.             JSR      _WaitBlit
  338.  
  339. * set-up globals first
  340.  
  341.             MOVEA.L  txbptr(SP),A0
  342.             MOVEM.L  group,D4-D7/A1-A3
  343.  
  344. * call appropriate routine
  345.  
  346.             MOVEA.L  OutPut,A6
  347.             JSR      (A6)
  348.  
  349. * free blitter for someone else
  350.  
  351.             JSR      _DisownBlitter
  352.  
  353. * now blast this into the rastport!
  354.  
  355.             MOVEA.L  Imagebuf,A0       ;address of bitplane
  356.             MOVEQ    #00,D0            ;no offset
  357.             MOVE.L   #128,D1           ;src modulo
  358.             MOVEA.L  rp(SP),A1         ;rastport
  359.             CLR.L    D2
  360.             MOVE.W   rp_cp_x(A1),D2    ;x dest
  361.             ADD.W    D4,rp_cp_x(A1)    ;modify Move() position
  362.             CLR.L    D3
  363.             MOVE.W   rp_cp_y(A1),D3    ;dest y
  364.             SUB.W    Baseline,D3       ;- baseline of font
  365.             MOVE.L   YSize,D5          ;y size
  366.             MOVEA.L  _GfxBase,A6
  367.             JSR      _LVOBltTemplate(A6)
  368. Noway:      RTS
  369.  
  370.  
  371. * If InitFastText() failed, Text() may still be called via the
  372. * FastText() function.
  373. *
  374. * This makes use in a system which must use any size font easier to program.
  375. *
  376. CallText:   MOVEA.L  rp(SP),A1
  377.             MOVEA.L  txbptr(SP),A0
  378.             MOVE.L   count(SP),D0
  379.             MOVEA.L  _GfxBase,A6
  380.             JSR      _LVOText(A6)
  381.             RTS
  382.  
  383. * --------------------------------------------------
  384. * This is the faster logic for an 8 bit wide fonts!
  385. * --------------------------------------------------
  386. Bltfast:    MOVEA.L  #$dff000,A6       ;address of custom chips
  387.  
  388. * once set, these blitter registers dont change
  389.  
  390.             MOVE.W   #DEST+SRCB+SRCA+$FC,bltcon0(A6)
  391.             MOVE.W   #$FFFF,bltalwm(A6)   ;no last word mask
  392.             MOVE.W   #126,bltdmod(A6)
  393.             MOVE.W   #126,bltamod(A6)
  394.             MOVE.W   #510,bltbmod(A6)
  395.  
  396. * do as much set-up as possible while last blit is busy
  397.  
  398. blit8:      CLR.L    D0
  399.             MOVE.B   (A0)+,D0
  400.             BEQ      blt8done          ;terminate if NULL found
  401.  
  402.             LSL.W    #1,D0             ;cast to WORD offset
  403.             ADD.L    D5,D0             ;ready with pointer!
  404.  
  405.             ADD.L    D6,D4             ;add to width
  406.  
  407. Wait8:      BTST     #6,dmaconr(A6)    ;wait for last blit to complete
  408.             BNE      Wait8
  409.  
  410. * these blitter register change for each blit
  411.  
  412.             MOVE.L   D0,bltbpt(A6)     ;b src
  413.             MOVE.L   (A3),bltdpt(A6)   ;d src pntr
  414.             MOVE.L   (A3)+,bltapt(A6)  ;a src pntr
  415.             MOVE.W   (A1)+,bltafwm(A6) ;first word mask           
  416.             MOVE.W   (A2)+,bltcon1(A6) ;shift value for b
  417.  
  418.             MOVE.W   D7,bltsize(A6)    ;trigger blit
  419.             DBF      D3,blit8          ;char counter
  420.  
  421. blt8done:   RTS
  422.  
  423. * --------------------------------------------------
  424. * This is the slower mode for odd width fonts!
  425. * --------------------------------------------------
  426. Bltslow:    MOVEA.L  #$dff000,A6       ;address of custom chips
  427.             MOVEQ    #00,D1            ;address of destination here
  428.  
  429. * these registers dont change once set
  430.  
  431.             CLR.W    bltalwm(A6)       ;last word mask
  432.             CLR.W    bltcon1(A6)       ;no special modes
  433.             MOVE.W   #124,bltbmod(A6)  ;modulos
  434.             MOVE.W   #124,bltdmod(A6)
  435.  
  436. * this bit clears the image buffer as needed - speed optimized
  437. * thinner fonts will be drawn faster due to less hits
  438. * a hit is TRUE whenever the font imagery rolls over into the next word
  439.  
  440. doblits:    MOVE.W   (A1)+,D0
  441.             MOVE.L   (A3)+,D2
  442.             CMP.L    D2,D1
  443.             BEQ      dochars           ;working on same word
  444.  
  445. Waitlast:   BTST     #6,dmaconr(A6)    ;wait if needed
  446.             BNE      Waitlast
  447.  
  448.             MOVE.L   D2,D1             ;save for next time around
  449.  
  450.             MOVE.W   #124,bltamod(A6)
  451.             MOVE.W   D0,bltafwm(A6)
  452.             MOVE.L   D2,bltdpt(A6)     ;d src pntr
  453.             MOVE.L   D2,bltapt(A6)     ;a src pntr
  454.             MOVE.W   #DEST+SRCA+$F0,bltcon0(A6) ;d=a
  455.             MOVE.W   D7,bltsize(A6)    ;trigger blitter clear
  456.  
  457. * setup while last blit is busy
  458.  
  459. dochars:    CLR.L    D0
  460.             MOVE.B   (A0)+,D0
  461.             BEQ      bltodddone        ;terminate if NULL found
  462.  
  463.             LSL.W    #1,D0             ;cast to WORD offset
  464.             ADD.L    D5,D0             ;ready with pointer!
  465.  
  466.             ADD.L    D6,D4             ;add to width
  467.  
  468. Waitpack:   BTST     #6,dmaconr(A6)    ;wait for image packing
  469.             BNE      Waitpack
  470.  
  471. * set up blitter for character image move
  472.  
  473.             MOVE.W   #508,bltamod(A6)
  474.             MOVE.W   #$FFFF,bltafwm(A6)
  475.             MOVE.L   D0,bltapt(A6)     ;a src
  476.             MOVE.L   D2,bltbpt(A6)     ;b src pntr
  477.             MOVE.L   D2,bltdpt(A6)     ;d src pntr
  478.             MOVE.W   (A2)+,bltcon0(A6) ;shift value for a
  479.             MOVE.W   D7,bltsize(A6)    ;trigger blit
  480.  
  481.             DBF      D3,doblits        ;checks count
  482.  
  483. bltodddone: RTS
  484.  
  485.             RTS
  486.  
  487.  
  488.             DSEG
  489. * global variables I use - private!
  490.  
  491. Imagebuf:   dc.l     0     ;address of image buffer - part of above struct
  492. Imagesize:  ds.l     1     ;size of working buffer
  493.  
  494. FontSize:   ds.l     1     ;size of font data buffer
  495.  
  496. YSize:      ds.l     1     ;size of font height
  497.  
  498. Maxchars:   ds.w     1     ;Max chars which can be drawn at one time
  499.  
  500. Baseline:   ds.w     1     ;baseline of font
  501.  
  502. OutPut:     dc.l     0     ;address of function to call or NULL for Text()
  503.  
  504. masks:      ds.w     256   ;256 words for masks
  505. shift:      ds.w     256   ;256 shift values
  506. local:      ds.l     256   ;256 pointers to target location
  507.  
  508. * these are grouped for a good reason - the MOVEM instruction is used
  509. * by the rendering routines for efficiency - DONT play with the order
  510. * of these unless you know what you are doing.
  511.  
  512. group:      dc.l     0     ;0 to init width of line register
  513. FontData:   dc.l     0     ;address of font data
  514. XSize:      dc.l     0     ;size of font width
  515. blitsize:   dc.l     0     ;blit size value
  516.             dc.l     masks ;address of arrays
  517.             dc.l     shift
  518.             dc.l     local
  519.  
  520.  
  521.             END
  522.  
  523.