* -------------------------------------------------------------------------- * WarpText.asm -- (PRE-RELEASE!) an ultra-fast, Bill Kelly * super_spiffy text-emitting routine. :-) 06/04/87 * * Copyright 1987 by Bill W. Kelly. * * THANKS: * * Many thanks to Hayes C. Haugen for giving me the idea to write * these routines-- I took one look at Blitz and thought: * "I've *gotta* DO that!" Well, thanks, Hayes -- I've done it. * Now, if I could *only* make a file requestor as nice as yours!!! :-) * * Thanks also to the people who gave me suggestions about ways to improve * the WarpText routines I had originally written! These are much nicer... * * COPYRIGHT NOTICE: * * This code, and the name "WarpText," is Copyright 1987 by Bill W. Kelly. * * DISTRIBUTION INFORMATION: * * You may distribute this code in any way you want to. I would prefer * that you charge less than $10 for distribution, however, and please * leave this whole notice intact. Please also distribute the file * "WarpText.i" together with "WarpText.asm" (this file). Thanks! * * NOTE: IF YOU ARE GOING TO MODIFY THE CODE, please make a little note * containing the date, what the original code was, and anything * else you deem necessary... * * USING WARPTEXT IN A PROGRAM: * * That's what it's here for! * * If you are going to distribute the source code with your program * please follow the restrictions under "DISTRIBUTION INFORMATION." * * It would be neat, especially if you aren't distributing the source * with your program, if you could find a place somewhere in your program * (the "ABOUT" menu, for instance) to say something like, * "Using Bill Kelly's WarpText routines for speed!," however if you * don't seem to be able to do this... don't worry about it. I would * really appreciate it, though! Thanks! * * PLEASE CONTACT ME BEFORE USING THIS CODE IN A COMMERCIAL PROGRAM! * * MY ADDRESS: * * NAME: Bill W. Kelly * UUCP: {akgua, hplabs!hp-sdd, sdcsvax}!crash!pnet01!billk * ARPA: crash!pnet01!billk@nosc * INET: billk@pnet01.CTS.COM | For UUCP, don't do just pnet01!billk; * USPS: 2507 Caminito La Paz | please include the crash!pnet01!billk. * La Jolla, CA 92037 | Thanks! * FONE: (619) 454-1307 * * PRE-RELEASE: * * This is a pre-release version of WarpText. In about half a month or * a month I plan to release a version of WarpText that comes with * an example program and has any reported bugs fixed. I will also * be adding a real clearscreen (clear 'window') on a formfeed and some * other features. If any of the code looks strange, or you notice * that I'm doing something like "moveq #0,dn" where I don't need to... * Well, you might mention it to save me time, although I will be going * back over the code to look for little things like this... * I took as much time as my schedule would permit to write this and get * it debugged and out. There are probably a few strange or unneeded * things I've done -- I haven't *really* LOOKED at the code yet, * though I have tested it... Ah well... * * GEE, THAT'S ALL VERY NICE, BUT HOW DO I CALL THESE ROUTINES??? * * Well, I have given you yet another structure to deal with... * Let me introduce you to WarpInfo... * * STRUCTURE WarpInfo,0 ; ...the denotes internal use. * APTR wi_TextFont ; Pointer to a TextFont structure. * APTR wi_BitMap ; Pointer to a BitMap structure. * WORD wi_WhichPlane ; Which bitplane to render into. * WORD wi_Left ; Left edge of 'window' in char loc's. * WORD wi_Top ; Top edge of 'window' in char loc's. * WORD wi_Width ; Width of 'window' in char loc's. * WORD wi_Height ; Height of 'window' in char loc's. * APTR wi_WindowTop ; Address of top of 'window.' * APTR wi_CurLine ; Address of start of current line. * APTR wi_LastLine ; Address of start of last line. * WORD wi_CurX ; Current X position. * WORD wi_LastX ; Maximum X position on a line. * WORD wi_BPMod ; # total possible chars on a line in bp * WORD wi_Modulo ; Add this to get to next line. * LABEL wi_SIZE * * When you assemble WarpText.asm, it will expect to find this structure * in graphics directory of your include files. It will do: * INCLUDE "graphics/warptext.i" I have already created a file called * "WarpText.i" which should be distributed along with this file. * * Now about the routines: there are only four routines that make up * WarpText. You must call the InitWarpInfo routine before calling any * of the other three routines. * * Please see each routine for information about how to call them. * * OH YEAH, BUG REPORTS: * * What, bugs in *my* code??? (Shut up, Bill...!) * * I would really appreciate hearing about the problems you find in * my code! I welcome your input. 'Ya know, suggestions, questions, * comments, flames?, etc... * * Remember, this is a pre-release version of WarpText. I plan to release * a version that *actually* has an EXAMPLE program with it. (Gee...) * In this version I will fix all the reported bugs and may make some * changes if anyone comes up with any interesting suggestions. * * Anyway, * * HAVE FUN! Bill * -------------------------------------------------------------------------- XDEF InitWarpInfo XDEF GotoXY XDEF GetXY XDEF WarpText NOLIST ; I don't want to see all of this junque... INCLUDE "graphics/text.i" INCLUDE "graphics/gfx.i" INCLUDE "graphics/warptext.i" LIST ; Turn listing back on... * ----------------------------------------- * Seems like a good place to put some code: * ----------------------------------------- CODE ; Ready...FIRE! ...Aim? * -------------------------------------------------------------------------- * INITWARPINFO NEEDS: * * a0 - Pointer to an instance of the WarpInfo structure, with the following * fields initialized: * * wi_TextFont: Pointer to an open font. (I.e. what OpenFont() returns * to you, other than NULL.) * wi_BitMap: Pointer to an initialized, 'working' BitMap structure. * (E.g. Open a window. Get the pointer to the screen * out of wd_WScreen. From there the BitMap structure is * at sc_BitMap, which is an offset, not a pointer, into * the Screen structure.) * wi_WhichPlane: Which bitplane you want the routine to draw into. * Numbering begins at zero. On the Workbench screen * (or any two-bitplane screen) the possible numbers for * wi_WhichPlane are 0 and 1. * wi_Left: Left edge of the 'window' (in character locations) * you want the routine to write into. * wi_Top: Top edge of the 'window' in character locations. * wi_Width: Width of 'window' (also on character locations). * wi_Height: Height of 'window' -- guess what? Character locations. * * REGISTER USAGE FOR INITWARPINFO: * * d0 - Left, Top, Width, Height, etc. * d1 - wi_Modulo * d2 - Scratch * d3 - Y size of font * d4 - Scratch * * a0 - Pointer to WarpInfo structure with above fields initialized. * a1 - Addr of top of bitplane, wi_WindowTop, etc. * a2 - Scratch * -------------------------------------------------------------------------- InitWarpInfo: movem.l d0-d4/a1-a2,-(sp) moveq #0,d4 ; Clear scratch. move.w d4,wi_CurX(a0) ; Store it in WarpInfo. move.w wi_Width(a0),wi_LastX(a0) ; Max X position. move.l wi_BitMap(a0),a1 ; Get some stuff from bmap. moveq #0,d2 move.w bm_BytesPerRow(a1),d2 ; #bytes per row in d2 move.w d2,wi_BPMod(a0) ; #bytes per row->wi_BPMod move.w wi_WhichPlane(a0),d4 ; Get bitplane#. asl.l #2,d4 ; Multiply plane# by four. move.l bm_Planes(a1,d4.l),a1 ; Get address of bitplane. moveq #0,d3 move.l wi_TextFont(a0),a2 move.w tf_YSize(a2),d3 ; Get YSize of font. moveq #0,d1 move.l d2,d1 ; Copy bytesperrow to d1. mulu.w d3,d1 ; YSize*BytesPerRow. move.w d1,wi_Modulo(a0) ; Store it in WarpInfo. moveq #0,d4 move.l d1,d4 ; Copy wi_modulo to scratch. mulu.w wi_Top(a0),d4 ; Mul by Y offset. add.w wi_Left(a0),d4 ; Add X offset. move.l a1,a2 ; BPlane addr to scratch. add.l d4,a2 ; Add offset to btpln addr. move.l a2,wi_WindowTop(a0) ; Stick in WarpInfo. move.l a2,wi_CurLine(a0) ; Stick in WarpInfo. moveq #0,d2 move.w wi_Top(a0),d2 ; Copy Y top to scratch. add.w wi_Height(a0),d2 ; Add Y height to Y top. move.l d1,d4 ; Copy wi_modulo to scratch. mulu.w d2,d4 ; Mul by Y offset. add.w wi_Left(a0),d4 ; Add X offset. move.l a1,a2 ; BPlane addr to scratch. add.l d4,a2 ; Add offset to btpln addr. move.l a2,wi_LastLine(a0) ; Stick in WarpInfo. movem.l (sp)+,d0-d4/a1-a2 rts * -------------------------------------------------------------------------- * GOTOXY NEEDS: * * d0 - New X position. \ All regs. but d1 preserved, * d1 - New Y position. * * a0 - Pointer to initialized WarpInfo structure. * * NOTE: These positions are given in character locations, like everything * else... The positions are relative to the 'window' you have * defined using InitWarpInfo. Position 0,0 is the character in the * top left corner of the window. * This routine does no error checking. (You're supposed to know * how big your window is...) * -------------------------------------------------------------------------- GotoXY: move.w d0,wi_CurX(a0) ; Set new X position. mulu.w wi_Modulo(a0),d1 ; Make Y an offset into window add.l wi_WindowTop(a0),d1 ; Add this offset to the window move.l d1,wi_CurLine(a0) ; to make it the new Y position. rts * -------------------------------------------------------------------------- * GETXY NEEDS: * * a0 - Pointer to an initialized WarpInfo structure. * * It returns the current X position in d0 and the current Y * position in d1. * -------------------------------------------------------------------------- GetXY: move.l wi_CurLine(a0),d1 ; Get current Y addr sub.l wi_WindowTop(a0),d1 ; Sub window to get Y offset. divu.w wi_Modulo(a0),d1 ; Should not be a remainder. moveq #0,d0 move.w wi_CurX(a0),d0 ; Get current X position. rts * -------------------------------------------------------------------------- * WARPTEXT NEEDS: * * d0 - Number of characters to type. (count) * * a0 - Pointer to an initialized WarpInfo structure. (See InitWarpInfo) * a1 - Address of string of characters to type. * * REGISTER USAGE FOR WARPTEXT: (All regs preserved but d0 which will be 0) * * d0 - Number of characters to type (count) * d1 - Character to be emitted * d2 - LoChar * d3 - HiChar * d4 - Current X position * d5 - Scratch * d7 - Bitplane modulo: add to get to next raster line in bitplane. * * a0 - Pointer to WarpInfo structure * a1 - Address of string of characters to type * a2 - Pointer to TextFont structure, address of tf_CharData * a3 - Addr of Current line. * a4 - Scratch * a5 - Scratch * * STACK USAGE FOR WARPTEXT: * * 0(sp) - Last line * 4(sp) - Top line * 8(sp) - tf_YSize * 12(sp) - tf_Modulo: add it to get to next line in font data * 16(sp) - wi_Modulo: add it to get to next line in bitplane 'window' * 20(sp) - Maximum (last) possible X position on a line * -------------------------------------------------------------------------- sp_LastLine: equ 0 ; Offsets into stack to get at this data. sp_TopLine: equ 4 sp_YSize: equ 8 sp_tf_Mod: equ 12 sp_wi_Mod: equ 16 sp_LastX: equ 20 NoChar: equ 256 ; This is where the empty-box char is. ??? WarpText: movem.l d1-d5/d7/a2-a5,-(sp) moveq #0,d4 move.w wi_CurX(a0),d4 ; Get current X position. moveq #0,d5 move.w wi_LastX(a0),d5 ; Get maximum X position. move.l d5,-(sp) ; Stick it on stack. (1st item) move.w wi_Modulo(a0),d5 ; Get wi_Modulo. move.l d5,-(sp) ; Stick it on stack. (2nd item) move.l wi_TextFont(a0),a2 ; Use TextFont to get some stuff: moveq #0,d2 move.b tf_LoChar(a2),d2 ; Get tf_LoChar. moveq #0,d3 move.b tf_HiChar(a2),d3 ; Get tf_HiChar. move.w tf_Modulo(a2),d5 ; Get tf_Modulo. move.l d5,-(sp) ; Stick it on stack. (3rd item) move.w tf_YSize(a2),d5 ; Get tf_YSize move.l d5,-(sp) ; Stick it on stack. (4th item) move.l tf_CharData(a2),a2 ; Replace textfont w/ tf_Chardata. move.l wi_WindowTop(a0),a4 ; Get addr of wi_WindowTop. move.l a4,-(sp) ; Stick it on stack. (5th item) move.l wi_LastLine(a0),a4 ; Get addr of wi_LastLine. move.l a4,-(sp) ; Stick it on stack. (6th item) move.l wi_CurLine(a0),a3 ; Get addr of wi_CurLine. moveq #0,d7 move.w wi_BPMod(a0),d7 ; Get wi_BPMod. subq #1,d0 ; Take one from count. moveq #0,d1 ; Clear d1 because using .b size. subq #1,d4 ; Take one from Current X. DoNextChar: addq #1,d4 ; Add 1 to Current X. DoNextSinAdd: move.b (a1)+,d1 ; Move char to emit to d1. cmpi.b #32,d1 ; Is it a space? beq Blank cmp.b d2,d1 ; Compare with LoChar. blt BoffoChar ; May be a LF, FF, CR, etc. cmp.b d3,d1 ; Compare with HiChar. blt DoNoChar move.l a2,a4 ; Copy tf_CharData to scratch. sub.l d2,d1 ; Sub LoChar from char. adda.l d1,a4 ; Add char to tf_CharData. DoChar: move.l a3,a5 ; Copy current line to scratch. adda.l d4,a5 ; Add XPos to current line. move.l sp_YSize(sp),d5 ; YSize is loop count. subq.l #1,d5 MoveChar: move.b (a4),(a5) ; Move line of char to bitplane. adda.l sp_tf_Mod(sp),a4 ; Add tf_Modulo to tf_Chardata. adda.l d7,a5 ; Add wi_BPMod to bitplane. dbra d5,MoveChar Blank: cmp.l sp_LastX(sp),d4 ; Compare max X and Current X... ble GotoDoNext ; Do next if current <= max. DoLF: moveq #0,d4 ; Xpos is zero now. DoCR: cmpa.l (sp),a3 ; CMP sp_LastLine with current. beq GotoNSA ; Wrap on line if equ. adda.l sp_wi_Mod(sp),a3 ; Point at next line. bra GotoNSA ; Do another character. DoNoChar: move.l a2,a4 ; Copy tf_Chardata to scratch. add.l #NoChar,a4 ; Point at empty-box char. bra DoChar ; Do the empty-box char. BoffoChar: cmpi.l #10,d1 ; Is is a linefeed? beq DoLF cmpi.l #12,d1 ; Is it a formfeed? beq DoFF cmpi.l #13,d1 ; Is it a CR? beq DoCR bra DoNoChar ; Fine. Put up the box. DoFF: moveq #0,d4 ; Make X pos zero. | It doesn't move.l sp_TopLine(sp),a3 ; Point at top | CLS yet. bra GotoNSA GotoDoNext: dbra d0,DoNextChar ; Keep looping? bra WindUp ; Loop is done. Clean up & bail. GotoNSA: dbra d0,DoNextSinAdd ; Do NextChar without adding. WindUp: addq.l #8,sp ; Get rid of stuff kept on stack. addq.l #8,sp addq.l #8,sp move.w d4,wi_CurX(a0) ; Store current X for next time. move.l a3,wi_CurLine(a0) ; Store current Y for next time. movem.l (sp)+,d1-d5/d7/a2-a5 rts END