[comp.sources.amiga] v02i003: WarpText 2.0

billk@pnet01.UUCP (Bill Kelly) (07/18/87)

    [Note that I changed Bill's method of sending the files, so his README
    file is not quite accurate.  I split the sources from the objects and
    posted the objects in comp.binaries.amiga	-Doc]

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	Warp.c
#	WarpC.asm
#	WarpText.asm
#	WarpText.doc
#	WarpText.h
#	WarpText.i
# This archive created: Sat Jul 18 02:45:19 1987
# By:	Craig Norborg (Purdue University Computing Center)
cat << \SHAR_EOF > README
ReadMe for WarpText version 2.0                         Bill Kelly  07Jul87

        Hi.  I've been having a few problems with my assembler.  I wrote
    an example program to open up a window and a screen and then do some
    WarpText into it.  For some reason, the assembler would do strange
    things to the code on the second pass, including not assembling
    the data.  After a while it would give up with some "Error 500" which
    it said was an unknown error and that I should report it.  I didn't
    see anything about this kind of thing in the manual and haven't
    been able to make it work.  It did assemble WarpText, however, and
    I was able to test the routines interactively with Forth.  They all
    work fine.

        Here is a list of the files that should be in WarpText.ARC:

            WarpText.doc        WarpText.asm        WarpText.h
            WarpText.i          Warp.C              WarpC.asm
            Warp                WarpText.obj        README

        WarpText.doc:   A small bit of documentation on the routines,
                        plus a copyright notice, thank-you notes,
                        information on distributing WarpText,
                        my address, etc.   Please read this file.
                        (At least the first part, anyway...)  Thanks.

        WarpText.asm:   The WarpText routines.  There is documentation
                        telling how to call each routine at the beginning
                        of each routine.

        WarpText.h:     The 'C' include for WarpText, written by Anson Mah.

        WarpText.i:     The assembler include for WarpText.

        Warp.C:         A quick test of the original WarpText routines,
                        written by Anson Mah.

        WarpC.asm:      A 'C' interface to the WarpText routines.  Makes
                        them easily callable from 'C' -- written by
                        Anson Mah.

        Warp:           Executable for the file "Warp.C" -- this program
                        only demonstrates the pre-release WarpText routines.
                        The NewWarp (version 2.0) routines did not exixt
                        when Anson wrote Warp.C.  NewWarp is close to
                        twice as fast as the routines demoed by this
                        program.

        WarpText.obj:   Assembley of the file "WarpText.asm" -- assembled
                        with the symbols, and ready to link!  :-)

        README:         Exactly.  That's just what you're doing.


                                                Enjoy the routines --
                                                I hope they will be useful!

                                                Bill Kelly.

SHAR_EOF
cat << \SHAR_EOF > Warp.c
/* WarpText Quickie Test    Anson Mah  06/08/87
 * For Lattice C
 *
 * NOTE: This test does not use any of the WarpText 2.0 routines as
 *       they did not exist when Anson wrote this.
 *       I made an example program for all of the routines but I
 *       couldn't get the $#%! assembler to assembler it!  It kept
 *       giving me all sorts of strange errors on the second pass.
 *       I was able to test all the routines interactively in Forth
 *       so, while I know the new (and old) routines work, I have no
 *       program to give out that demonstrates them...  Sorry,
 *                                                      Bill.
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include "graphics/WarpText.h"

extern void InitWarpInfo(), GotoXY(), GetXY(), WarpText();

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase = NULL;
struct Window *w = NULL;
struct WarpInfo *winfo = NULL;

struct TextAttr taTopaz80 = { "topaz.font", 8, FS_NORMAL, FPF_ROMFONT };

struct NewWindow wdef = {
        0,0,640,200,
        0,1,
        CLOSEWINDOW,
        WINDOWDRAG | WINDOWCLOSE | WINDOWDEPTH | SMART_REFRESH | ACTIVATE,
        NULL, NULL,
        "WarpText Test",
        NULL, NULL,
        0,0,640,200,
        WBENCHSCREEN
};

void closestuff()
{
        if (winfo)              FreeMem(winfo, sizeof(struct WarpInfo));
        if (w)                  CloseWindow(w);
        if (GfxBase)            CloseLibrary(GfxBase);
        if (IntuitionBase)      CloseLibrary(IntuitionBase);
        XCEXIT(0);
}

void openstuff()
{
        if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary(
                "intuition.library", 33)))
                closestuff();
        if (!(GfxBase = (struct GfxBase *)OpenLibrary(
                "graphics.library", 33)))
                closestuff();
        if (!(winfo = (struct WarpInfo *)AllocMem(sizeof(struct WarpInfo),
                MEMF_PUBLIC)))
                closestuff();
        if (!(w = (struct Window *)OpenWindow(&wdef)))
                closestuff();
}

ULONG strlen(s)
char *s;
{
        ULONG i = 0;

        while (*s++)
                i++;
        return(i);
}

void _main()
{
        static char *text[17];
        struct IntuiMessage *msg;
        ULONG class;
        UWORD i;

        openstuff();

        text[0] = "Hi, Bill!\n";
        text[1] = "   Thanx for your WarpText routines.  As you can see, this\n";
        text[2] = "is a quick test of 'em.  The only routine I don't use is\n";
        text[3] = "GetXY.  Also note that I have created a WarpText.h file for\n";
        text[4] = "C programmers like yours truly and also a C interface\n";
        text[5] = "module for the same people!  Please do what you will with\n";
        text[6] = "them.\n";
        text[7] = "   Right.  I've looked over your code and can't see any\n";
        text[8] = "immediate improvements, but I may if I study them longer.\n";
        text[9] = "Actually, I believe you might gain some more speed if you\n";
        text[10] = "start using the Blitter instead.  It was made to handle\n";
        text[11] = "stuff like this.  You should be able to get upward of\n";
        text[12] = "30,000 chars/sec if you use it.  This number was measured\n";
        text[13] = "with the set of routines my friends came up with a while\n";
        text[14] = "back.  It's fairly accurate.\n";
        text[15] = "   Anyway, more when I have more time to hack!\n";
        text[16] = "                                          Anson";

        /* set up WarpInfo */
        winfo->wi_TextFont = (APTR)OpenFont(&taTopaz80);
        winfo->wi_BitMap = (APTR)&w->WScreen->BitMap;
        winfo->wi_WhichPlane = 0;
        winfo->wi_Left = 10;
        winfo->wi_Top = 3;
        winfo->wi_Width = 60;
        winfo->wi_Height = 21;
        InitWarpInfo(winfo);

        /* warp out text */
        for (i = 0; i < 17; i++)
                WarpText(winfo, text[i], strlen(text[i]));
        GotoXY(winfo, 25, 19);
        WarpText(winfo, "Hey, I'm here!", 14);
        GotoXY(winfo, 10, 20);
        WarpText(winfo, "And here!!", 10);

        CloseFont(winfo->wi_TextFont);

        for (;;) {
                WaitPort(w->UserPort);
                msg = (struct IntuiMessage *)GetMsg(w->UserPort);
                ReplyMsg(msg);
                class = msg->Class;
                switch (class) {
                        case CLOSEWINDOW:
                                closestuff();
                                break;
                }
        }
}

void MemCleanup() {}  /* Lattice stub */
SHAR_EOF
cat << \SHAR_EOF > WarpC.asm
* -------------------------------------------------------
* WarpC.asm -- C Interface For WarpText Routines
* Written by Anson Mah 06/08/87
*
* Interface to WarpText 2.0 added 06Jul87 by billk.
* Actually, I don't think the 2.0 interface I just wrote
* will be very useful.  Ah well.  It's there, do what you
* will with it...  Bill.
* -------------------------------------------------------

        XDEF    _InitWarpInfo
        XDEF    _GotoXY
        XDEF    _GetXY
        XDEF    _WarpText
        XDEF    _SetupFont      ;WarpText 2.0
        XDEF    _NewWarp        ;WarpText 2.0
        XDEF    _XORCursor      ;WarpText 2.0

        XREF    InitWarpInfo
        XREF    GotoXY
        XREF    GetXY
        XREF    WarpText
        XREF    SetupFont       ;WarpText 2.0
        XREF    NewWarp         ;WarpText 2.0
        XREF    XORCursor       ;WarpText 2.0

* ----------------------------------------------------
* Call: InitWarpInfo(winfo);
*       struct WarpInfo *winfo;
* ----------------------------------------------------
_InitWarpInfo:
        move.l  4(a7),a0                ; get pointer to WarpInfo
        jsr     InitWarpInfo
        rts

* ----------------------------------------------------
* Call: GotoXY(winfo, x, y);
*       struct WarpInfo *winfo;
*       UWORD x, y;
* ----------------------------------------------------
_GotoXY:
        move.l  04(a7),a0               ; get pointer to WarpInfo
        move.l  08(a7),d0               ; get new X position
        move.l  12(a7),d1               ; get new Y position
        jsr GotoXY
        rts

* ----------------------------------------------------
* Call: GetXY(winfo, &x, &y);
*       struct WarpInfo *winfo;
*       UWORD x, y;
* ----------------------------------------------------
_GetXY:
        move.l  04(a7),a0               ; get pointer to WarpInfo
        jsr     GetXY
        move.l  08(a7),a0               ; get address of x variable
        move.w  d0,(a0)                 ; store x coordinate
        move.l  12(a7),a0               ; get address of y variable
        move.w  d1,(a0)                 ; store y coordinate
        rts

* ----------------------------------------------------
* Call: WarpText(winfo, text, len);
*       struct WarpInfo *winfo;
*       char *text;     /* pointer to string */
*       ULONG len;      /* length of string */
* ----------------------------------------------------
_WarpText:
        move.l  04(a7),a0
        move.l  08(a7),a1
        move.l  12(a7),d0
        jsr     WarpText
        rts

* ------------------------------------------------------
* Call: SetupFont(nwinfo, tf);                    WT 2.0
*       struct NewWarpInfo *nwinfo;               billk
*       struct TextFont *tf;  /* pointer to open font */
* ------------------------------------------------------
_SetupFont:
        jmp     SetupFont
        rts

* ------------------------------------------------------
* Call: NewWarp(nwinfo, text, len);               WT 2.0
*       struct NewWarpInfo *nwinfo;               billk
*       char *text;     /* pointer to string */
*       ULONG len;      /* length of string */
* ------------------------------------------------------
_NewWarp:
        jmp     NewWarp
        rts

* ------------------------------------------------------
* Call: XORCursor(nwinfo, text, len);             WT 2.0
*       struct NewWarpInfo *nwinfo;               billk
* ------------------------------------------------------
_XORCursor:
        jmp     XORCursor
        rts

        END

* ------------------ *
* End of "WarpC.asm" *
* ------------------ *
SHAR_EOF
cat << \SHAR_EOF > WarpText.asm
* --------------------------------------------------------------------------
* 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" *
* --------------------- *
SHAR_EOF
cat << \SHAR_EOF > WarpText.doc
WarpText.doc                      WT 2.0                        Bill Kelly
                                                                07/06/87

       //     // ////// //////  //////    //////// ////// ||//  ////////
      //     // //  // //  //  //  //       //    //      |//     //
     //  /  // ////// //////  //////       //    /////    //     //
    // /// // //  // //  //  //           //    //       //|    //
   ///   /// //  // //   // //           //    //////   //||   //

THANK YOU'S: (in alphabetical order)

  Thanks to Anson Mah for writing the WarpText 'C' interface.
  Without him, there wouldn't be one -- I don't speak C!

  Thanks to Aaron Avery for taking my original unreleased WarpText routine,
  which was fast but not fancy, and speeding it up immensely.  This routine,
  (after I sped it up even more by rearranging the font data), and Aaron's
  cursor routine, are WarpText 2.0.

  Thanks to Hayes C. Haugen who, by writing Blitz, reminded me of what
  text on a computer like this *ought* to be like and so got me started
  on WarpText.

  Thanks to Leon Frankel (sorry if I got the name wrong -- that's what it
  sounded like over the phone) for reporting a bug in the wi_Width handling
  in the WarpText prerelease routines.
  (Please see "BUGS:" for more information.)

  If I forgot anyone -- sorry.  Thanks to you, too!

COPYRIGHT NOTICE:

                The WarpText code, and the name "WarpText,"
                    is Copyright 1987 by Bill W. Kelly.

DISTRIBUTION INFORMATION:

  Feel free to distribute this code, complying with the following
  restriction:

       Since there are many files in this release of WarpText,
       please distribute them in ARCed form so that no files get lost.
       (If you need to UUEncode, please UUEncode the ARC file.)
       Thanks!

  NOTE: IF YOU ARE GOING TO MODIFY THE CODE, please make a little note
        containing the date, your comments, and what the original code was.
        Thanks.

USING WARPTEXT IN A PROGRAM:

  That's why I wrote it!

  If you are going to distribute the WarpText source code with your program
  please also follow the directions 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 can be found at the end of this file.)

GENERAL INFORMATION:

  The "Old Warp" routines use the WarpInfo structure to keep track
  of which bitplane they're writing into, the current X and Y locations,
  the TextFont data, etc.

  STRUCTURE   WarpInfo,0      ; ...the <I> 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    ; <I> Address of top of 'window.'
      APTR    wi_CurLine      ; <I> Address of start of current line.
      APTR    wi_LastLine     ; <I> Address of start of last line.
      WORD    wi_CurX         ; <I> Current X position.
      WORD    wi_LastX        ; <I> Maximum X position on a line.
      WORD    wi_BPMod        ; <I> # total possible chars on a line in bp
      WORD    wi_Modulo       ; <I> Add this to get to next line.
      LABEL   wi_SIZE

  Call the InitWarpInfo routine before calling any of the other "Old Warp"
  routines.  The WarpInfo structure you pass InitWarpInfo must be partially
  initialized before calling InitWarpInfo.  InitWarpInfo prepares
  the parts WarpInfo structure marked with "<I>" so that the WarpInfo
  structure can be used with GetXY, GotoXY, and WarpText.

  The "New Warp" routines use NewWarpInfo structure.  It's a lot smaller
  than WarpInfo because the new routines have sacrificed features for speed.

    STRUCTURE   NewWarpInfo,0
        WORD    nwi_XLoc        ; Current X position in char. loc's.
        WORD    nwi_YLoc        ; Current Y position in char. loc's.
        APTR    nwi_BitPlane    ; Address of bitplane to render text into.
        APTR    nwi_FontData    ; Address of 2048 byte array for font data.
        LABEL   nwi_SIZE

  Call the SetupFont routine before calling any of the other "New Warp"
  routines.  SetupFont unpacks the font passed to it into the 2048 byte
  array, the address of which is kept in nwi_FontData.  You must allocate
  this 2048 byte array and store its address into nwi_FontData before
  calling SetupFont.  Pass the pointer to an open font to SetupFont on
  the stack.  The 2048 byte array does not have to be in CHIP ram because
  the routines do not use the blitter.  After calling SetupFont, the
  NewWarpInfo structure can be used with NewWarp and XORCursor.

  Please see the file "WarpText.asm" for more information about each
  routine.

BUGS:

    Known Bugs:                                         Fixed:
    -----------                                         ------

      WarpText writes to two more columns per line         /
      than it should.  If you specify 10 for wi_Width    \/        Yes.
      you will get 12 characters per line.
                                                               _
      If WarpText encounters a character that has not    |\ | / \
      been defined in the font it's using it will not    | \| \_/  Not yet.
      output the empty-box character.  A garbage
      character-pattern will appear.

BUG REPORTS:

  I would really appreciate hearing about any problems you find in
  my code!  Please don't hesitate to drop me a line or send me mail
  if you have any suggestions, questions, or comments.  I welcome
  your input.
                                                    Enjoy,
                                                    Bill Kelly.

MY ADDRESS:

  NAME: Bill W. Kelly
  UUCP: {hplabs!hp-sdd, sdcsvax, ihnp4}!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

* --------------------- *
* End of "WarpText.doc" *
* --------------------- *
SHAR_EOF
cat << \SHAR_EOF > WarpText.h
/* ------------------------------------------------------------------------
 * graphics/WarpText.h -- 'C' include for WarpText           Bill Kelly
 * text routines.               WT 2.0                       07/06/87
 *
 * Copyright 1987 by Bill W. Kelly.  All Rights Reserved.
 *
 * This is meant to go in the Graphics directory of the C includes.
 * Made for C by Anson Mah 06/08/87  |  06Jun87 added NewWarpInfo (billk)
 * ------------------------------------------------------------------------
 */

/* -------------------------------------------------------------------------
 * The following structure, WarpInfo, is used by these four routines:
 *   InitWarpInfo    (Initializes the WarpInfo structure for use)
 *   GetXY           (Returns current cursor position)
 *   GotoXY          (Sets cursor to given position)
 *   WarpText        (Emits text at ~13,500 characters per second)
 */

struct WarpInfo {               /* ...the <I> denotes internal use */
        APTR    wi_TextFont;    /*     Pointer to a TextFont structure */
        APTR    wi_BitMap;      /*     Pointer to a BitMap structure */
        UWORD   wi_WhichPlane;  /*     Which bitplane to render into */
        UWORD   wi_Left;        /*     Left edge of 'window' in char loc's */
        UWORD   wi_Top;         /*     Top edge of 'window' in char loc's */
        UWORD   wi_Width;       /*     Width of 'window' in char loc's */
        UWORD   wi_Height;      /*     Height of 'window' in char loc's */
        APTR    wi_WindowTop;   /* <I> Address of top of 'window' */
        APTR    wi_CurLine;     /* <I> Address of start of current line */
        APTR    wi_LastLine;    /* <I> Address of start of last line */
        UWORD   wi_CurX;        /* <I> Current X position */
        UWORD   wi_LastX;       /* <I> Maximum X position on a line */
        UWORD   wi_BPMod;       /* <I> # total possible chars on a line in bp */
        UWORD   wi_Modulo;      /* <I> Add this to get to next line */
};

/* -------------------------------------------------------------------------
 * The following structure, NewWarpInfo, is used by these three routines:
 *   SetupFont       (Copies font to given 2048 byte array for faster access)
 *   NewWarp         (Emits text at ~30,000 characters per second)
 *   XORCursor       (XOR's a visible cursor to the current xy location)
 */

struct NewWarpInfo {
        UWORD   nwi_XLoc;       /* Current X position in char. loc's. */
        UWORD   nwi_YLoc;       /* Current Y position in char. loc's. */
        APTR    nwi_BitPlane;   /* Address of bitplane to render text into. */
        APTR    nwi_FontData;   /* Address of 2048 byte array for font data. */
};

* ---------------------------- *
* End of "graphics/WarpText.h" *
* ---------------------------- *
SHAR_EOF
cat << \SHAR_EOF > WarpText.i
* ------------------------------------------------------------------------
* graphics/WarpText.i -- Assembler include file for         Bill Kelly
* WarpText text routines.                                   07/07/87
*
* Copyright 1987 by Bill W. Kelly.  All Rights Reserved.
*
* This is meant to go in the Graphics directory of the assembler includes.
* When you assemble WarpText.asm, it will include: "graphics/WarpText.i"
* ------------------------------------------------------------------------

* --------------------------------------------------------------------------
* The following structure, WarpInfo, is used by these four routines:
*   InitWarpInfo    (Initializes the WarpInfo structure for use)
*   GetXY           (Returns current cursor position)
*   GotoXY          (Sets cursor to given position)
*   WarpText        (Emits text at ~13,500 characters per second)


    STRUCTURE  WarpInfo,0       ;...the <I> denotes internal use.
        APTR    wi_TextFont     ;Pointer to a TextFont structure.
        APTR    wi_BitMap       ;Pointer to a BitMap structure.
        UWORD   wi_WhichPlane   ;Which bitplane to render into.
        UWORD   wi_Left         ;Left edge of 'window' in char loc's.
        UWORD   wi_Top          ;Top edge of 'window' in char loc's.
        UWORD   wi_Width        ;Width of 'window' in char loc's.
        UWORD   wi_Height       ;Height of 'window' in char loc's.
        APTR    wi_WindowTop    ;<I> Address of top of 'window.'
        APTR    wi_CurLine      ;<I> Address of start of current line.
        APTR    wi_LastLine     ;<I> Address of start of last line.
        UWORD   wi_CurX         ;<I> Current X position.
        UWORD   wi_LastX        ;<I> Maximum X position on a line.
        UWORD   wi_BPMod        ;<I> # total possible chars on a line in bp
        UWORD   wi_Modulo       ;<I> Add this to get to next line.
        LABEL   wi_SIZE


* --------------------------------------------------------------------------
* The following structure, NewWarpInfo, is used by these three routines:
*   SetupFont       (Copies font to given 2048 byte array for faster access)
*   NewWarp         (Emits text at ~30,000 characters per second)
*   XORCursor       (XOR's a visible cursor to the current xy location)


    STRUCTURE  NewWarpInfo,0
        UWORD   nwi_XLoc        ;Current X position in char. loc's.
        UWORD   nwi_YLoc        ;Current Y position in char. loc's.
        APTR    nwi_BitPlane    ;Address of bitplane to render text into.
        APTR    nwi_FontData    ;Address of 2048 byte array for font data.
        LABEL   nwi_SIZE


* ---------------------------- *
* End of "graphics/WarpText.i" *
* ---------------------------- *
SHAR_EOF
#	End of shell archive
exit 0