* -------------------------------------------------------------------------- * WarpText.asm Version 2.0 Bill Kelly * 07/07/87 * * Copyright 1987 by Bill W. Kelly. * XDEF InitWarpInfo XDEF GotoXY XDEF GetXY XDEF WarpText XDEF SetupFont XDEF NewWarp XDEF XORCursor 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... CODE ; WarpText begins... * ========================================================================== * * | __ ___ __ __ | * | / \ / / \ / / /| / \ / \ | * \|/ / / / / / / / / /_| /\__/ /\__/ \|/ * V \__/ /___ /___/ \/\/ / | / \ / V * * -------------------------------------------------------------------------- * InitWarpInfo: * ------------- * * 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. sub.w #1,wi_LastX(a0) ; make it 0-relative. 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: * ------- * * 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: * ------ * * 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: * --------- * * 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 ; I thought this was where the "empty-box" ; character was. It isn't. Anyone know where ; it is? Or am I supposed to generate it ; myself???? 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... blt 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 * * ========================================================================== * ========================================================================== * * | ___ __ __ | * | /| / / / / / / /| / \ / \ | * \|/ / | / /--- / / / / / / /_| /\__/ /\__/ \|/ * V / |/ /___ \/\/ \/\/ / | / \ / V * * -------------------------------------------------------------------------- * SetupFont: * ---------- * Call with NewWarpInfo and TextFont on the stack. * (TextFont should be on top) * * You must allocate a 2048 byte buffer (does not have to reside in CHIP RAM) * and store its address into the nwi_FontData field of the NewWarpInfo * structure prior to calling SetupFont. * SetupFont will take the font data from the pointer to the FontData * structure you supply on the stack and rearrange it into the 2048 byte * array. It is not a smart routine -- it is set up to unpack only the * Topaz 8 font, or any 8x8 font with the same number of characters as topaz * and the same modulo. If you want to use an 8x8 font that has different * number of characters defined and a different modulo, you will have to * modify the SetupFont code. * SetupFont: movem.l d0/a0-a3,-(sp) ;Save used regs move.l 24(sp),a2 ;FontData kept in a2 move.l 28(sp),a1 ;NewWarpInfo kept in a1 move.l nwi_FontData(a1),a0 ;array to rearrange font into move.l #31,d0 ;number of blank chars. TheUnCola: move.b #$FE,(a0)+ ;$FE = %11111110 move.b #$C6,(a0)+ ;$C6 = %11000110 move.b #$C6,(a0)+ ;$C6 = %11000110 move.b #$C6,(a0)+ ;$C6 = %11000110 move.b #$C6,(a0)+ ;$C6 = %11000110 move.b #$C6,(a0)+ ;$C6 = %11000110 move.b #$FE,(a0)+ ;$FE = %11111110 move.b #$00,(a0)+ ;$00 = %00000000 dbf d0,TheUnCola ;Get the picture? :-) move.l tf_CharData(a2),a2 ;get addr of the font data move.l a2,a3 ;save for later loops moveq #0,d0 ;zero is 1st char in chardata DoAnother: add.w d0,a2 ;add char offset to chardata move.b (a2),(a0)+ ;begin copying char into array add.w #192,a2 ;add tf_modulo for next byte move.b (a2),(a0)+ add.w #192,a2 move.b (a2),(a0)+ add.w #192,a2 move.b (a2),(a0)+ add.w #192,a2 move.b (a2),(a0)+ add.w #192,a2 move.b (a2),(a0)+ add.w #192,a2 move.b (a2),(a0)+ add.w #192,a2 move.b (a2),(a0)+ ;finished copying this character move.l a3,a2 ;point to chardata again addq.b #1,d0 ;add one for next character cmp.w #223,d0 ;need to stop after 223rd char ble.s DoAnother movem.l (sp)+,d0/a0-a3 ;restore used regs rts * * -------------------------------------------------------------------------- * -------------------------------------------------------------------------- * NewWarp: * -------- * Call with NewWarpInfo, String-address, and String-count on the stack. * (String-count should be on top) * * You must have called SetupFont AND have filled in the nwi_BitPlane * field in the NewWarpInfo structure before you call NewWarp. * It would be a good idea, also, to make sure you've set up nwi_XLoc * and nwi_YLoc to the correct places before you go writing text. * They are character-position relative, rather than pixel relative. * Setting nwi_XLoc and nwi_XLoc to 8,8 for example, would be like telling * the Graphics library Text() routine to write text at 80,80. * Another note: Unlike Text(), NewWarp writes directly into a bitplane * and does not do clipping at the edges of rastports. This makes * NewWarp very fast, but less flexible. I have found it easiest to * use the WarpText routines in SUPER_BITMAP windows. * NewWarp: movem.l d0-d3/a0-a4,-(sp) ;save used registers move.l 40(sp),d3 ;String-count kept in d3 move.l 44(sp),a2 ;String-addr kept in a2 move.l 48(sp),a4 ;NewWarpInfo kept in a4 move.w nwi_XLoc(a4),d0 ;move to d0 before incrementing add.w d3,nwi_XLoc(a4) ;increment XLoc like Text() subq.w #1,d3 ;adjust count for dbf move.w nwi_YLoc(a4),d1 move.l nwi_BitPlane(a4),a0 move.l nwi_FontData(a4),a1 move.l a1,a3 ;safe keeping of FontData asl.w #7,d1 ;This multiplies YLoc move.w d1,d2 ;times 640 in 26 cycles asl.w #2,d1 ;instead of the 74 cycles add.w d2,d1 ;a MULU would take. add.w d0,d1 ;Add XLOC to expanded YLOC. add.w d1,a0 ;Add LOC offset to bitplane. OnceAgain: moveq #0,d0 move.b (a2)+,d0 ;Put character in d0. asl.w #3,d0 ;Make offset into FontData add.w d0,a1 ;Add offset to fontData address. move.b (a1)+,(a0) ;Start moving the font data add.w #80,a0 ;into the bitmap... move.b (a1)+,(a0) add.w #80,a0 move.b (a1)+,(a0) add.w #80,a0 move.b (a1)+,(a0) add.w #80,a0 move.b (a1)+,(a0) add.w #80,a0 move.b (a1)+,(a0) add.w #80,a0 move.b (a1)+,(a0) add.w #80,a0 move.b (a1)+,(a0) ;Finished moving data. sub.w #559,a0 ;restore a0 to next char loc move.l a3,a1 ;restore a1 to FontData dbf d3,OnceAgain movem.l (sp)+,d0-d3/a0-a4 ;restore used registers rts * * -------------------------------------------------------------------------- * -------------------------------------------------------------------------- * XORCursor: * ---------- * Call with NewWarpInfo on the stack. * * You must have called SetupFont AND have filled in the nwi_BitPlane * field in the NewWarpInfo structure before you call XORCursor. * XORCursor XOR's a console-device-like cursor to the current xy location. * To get the cursor to be a different color than the Text you've been * emitting with NewWarp you have to change the bitplane being pointed to * by nwi_BitPlane. I thought of adding another APTR to the end of * the NewWarpInfo structure called nwi_CursorPlane that you could set * to point to a different bitplane which would only be used only * by XORCursor. I haven't yet, as I want to get this stuff out. * If you would like to, feel free to do so. * XORCursor: movem.l d0-d1/a0-a1,-(sp) ;Save used registers move.l 20(sp),a1 ;NewWarpInfo kept in a1 move.w nwi_YLoc(a1),d0 move.l nwi_BitPlane(a1),a0 asl.w #7,d0 ;This multiplies YLoc move.w d0,d1 ;times 640 in 26 cycles asl.w #2,d0 ;instead of the 74 cycles add.w d1,d0 ;a MULU would take. add.w nwi_XLoc(a1),d0 ;Add XLOC to expanded YLOC. add.w d0,a0 ;Add LOC offset to bitplane. eor.b #$FF,(a0) ;XOR the cursor... add.w #80,a0 eor.b #$FF,(a0) add.w #80,a0 eor.b #$FF,(a0) add.w #80,a0 eor.b #$FF,(a0) add.w #80,a0 eor.b #$FF,(a0) add.w #80,a0 eor.b #$FF,(a0) add.w #80,a0 eor.b #$FF,(a0) add.w #80,a0 eor.b #$FF,(a0) movem.l (sp)+,d0-d1/a0-a1 ;restore used registers rts * * ========================================================================== END ; WarpText ends. * --------------------- * * End of "WarpText.asm" * * --------------------- *