*  Program to draw a single pixel interposed on Single Playfield Code.
*  Submitted by Thomas J. Eshelman, Reading, Pa.  11/25/88
*
*  Purpose:  Create a library routine to produces a single-playfield display
*            using system graphics primitives.
*
*  Draw a pixel at predetermined location and color.
*  This particular example is written for an early DevPak assembler.
*  Please refer to accompanying Manx version for full comments.

   incdir   "fh0:Asm_Include/"

   include  exec/types.i
   include  exec/exec_lib.i
   include  graphics/gfx.i
   include  graphics/gfxbase.i
   include  graphics/rastport.i
   include  graphics/view.i
   include  graphics/graphics_lib.i
   include  libraries/dosextens.i
   include  libraries/dos_lib.i
   include  workbench/workbench.i
   include  workbench/startup.i
   include  hardware/custom.i
   include  tomesh.i


NUMCOLS     EQU   8
PLANEPTR    EQUR  d0

DEPTH       EQU   3                    Two sets of dimensions to remind that
WIDTH       EQU   401                  the display is not the same as the
HEIGHT      EQU   201                  bitmap.

VPWIDTH     EQU   321                  The odd value chosen to remind never
VPHEIGHT    EQU   201                  to draw >= size of the bitmap.



start:


   suba.l      a1,a1                   Asm. doesn't provide the automatic
   CALLEXEC    FindTask                startup code of 'C'.  Hence, we steal
   move.l      d0,mytask               this classic scheme from David Ashley.

   lea         gfxname(pc),a1
   moveq       #0,d0
   jsr         _LVOOpenLibrary(a6)
   move.l      d0,GfxBase

   movea.l     d0,a1
   move.l      gb_ActiView(a1),oldview

   lea         dosname(pc),a1
   moveq       #0,d0
   jsr         _LVOOpenLibrary(a6)
   move.l      d0,DosBase

   clr.l       returnmsg

   movea.l     mytask(pc),a4
   tst.l       pr_CLI(a4)
   bne         nowb

   lea         pr_MsgPort(a4),a0
   jsr         _LVOWaitPort(a6)        Must wait for WB to give a go-ahead.

   lea         pr_MsgPort(a4),a0
   jsr         _LVOGetMsg(a6)          Received.  Get it off process port.

   move.l      d0,returnmsg            Save to reply with when closing.

   movea.l     d0,a4
   move.l      sm_ArgList(a4),d0       (This won't happen.  Is used as for
   beq         nowb                           convenience only.)

   move.l      d0,a4
   move.l      wa_Lock(a4),d1

   movea.l     DosBase(pc),a6
   CALLDOS     CurrentDir

nowb:

   bsr         playfields              NOW YOU MAY CALL THE PROGRAM PROPER

   move.w      #160,d0
   move.w      #100,d1
   move.w      #3,d2

   bsr         paint_pixel             Draw un pixel.

   move.l      #500,d1
   CALLDOS     Delay

closeall:

   move.l      returnmsg(pc),d4        To quit, we must retrieve the message.
   beq         nowb2                   If none, we  came from the CLI.

   CALLEXEC    Forbid                  May not multitask during the reply.

   move.l      d4,a1
   jsr         _LVOReplyMsg(a6)        Reply to the WorkBench!

nowb2:

   lea         bitmap+bm_Planes(pc),a2 Deallocate raster memory.
   moveq       #DEPTH-1,d2

deallocate_1:
  
   move.l      #WIDTH,d0
   move.l      #HEIGHT,d1
   movea.l     (a2),a0                 Remember to dereference.
   move.l      a0,d2
   beq         quit_0

   CALLGRAF    FreeRaster

   adda.l      #4,a2
   dbra        d2,deallocate_1

quit_0:

   movea.l     cm(pc),a0
   move.l      a0,d0
   beq         quit_1
   CALLGRAF    FreeColorMap

quit_1:

   lea         vport(pc),a0
   move.l      a0,d2
   beq         quit_2
   CALLGRAF    FreeVPortCopLists

quit_2:

   lea         view(pc),a0
   movea.l     v_LOFCprList(a0),a0
   move.l      a0,d2
   beq         quit_3
   CALLGRAF    FreeCprList

quit_3:

   movea.l     oldview(pc),a1
   move.l      a1,d2
   beq         quit_4
   CALLGRAF    LoadView

quit_4:

   movea.l     DosBase(pc),a1
   move.l      a1,d2
   beq         quit_5
   CALLEXEC    CloseLibrary

quit_5:

   movea.l     GfxBase(pc),a1
   move.l      a1,d2
   beq         quit_6
   CALLEXEC    CloseLibrary

quit_6:

   rts                                 Return to system.



playfields:

   lea         view(pc),a1
   CALLGRAF    InitView

   lea         view(pc),a1
   move.l      #vport,v_ViewPort(a1)

   lea         vport(pc),a0
   jsr         _LVOInitVPort(a6)

   moveq       #NUMCOLS,d0
   jsr         _LVOGetColorMap(a6)     Declares/allocates a struct ColorMap
   move.l      d0,cm                   invisibly, and returns pointer to it.

   lea         vport(pc),a0
   move.l      d0,vp_ColorMap(a0)
   move.w      #VPWIDTH,vp_DWidth(a0)
   move.w      #VPHEIGHT,vp_DHeight(a0)

   move.l      #rasinfo,vp_RasInfo(a0)
   move.w      #0,vp_Modes(a0)

   lea         vport(pc),a0
   lea         colortable(pc),a1
   moveq       #NUMCOLS,d0
   jsr         _LVOLoadRGB4(a6)        Loads the struct ColorMap, supra.

   lea         bitmap(pc),a0
   move.l      #DEPTH,d0
   move.l      #WIDTH,d1
   move.l      #HEIGHT,d2
   jsr         _LVOInitBitMap(a6)
 
allocate:

   lea         bitmap+bm_Planes(pc),a2
   moveq       #DEPTH-1,d2

plane:

   move.l      #WIDTH,d0
   move.l      #HEIGHT,d1
   jsr         _LVOAllocRaster(a6)
   move.l      PLANEPTR,(a2)
   beq         closeall

   movea.l     PLANEPTR,a1
   RASSIZE     #WIDTH,#HEIGHT          Macro returns in d0.
   moveq       #0,d1
   jsr         _LVOBltClear(a6)

   adda.l      #4,a2
   dbra        d2,plane

   lea         rasinfo(pc),a0
   move.l      #bitmap,ri_BitMap(a0)
   move.w      #0,ri_RxOffset(a0)
   move.w      #0,ri_RyOffset(a0)
   move.l      #0,ri_Next(a0)

   lea         view(pc),a0
   lea         vport(pc),a1
   jsr         _LVOMakeVPort(a6)

   lea         view(pc),a1
   jsr         _LVOMrgCop(a6)

   lea         rastport(pc),a1
   jsr         _LVOInitRastPort(a6)

   lea         rastport(pc),a1
   move.l      #bitmap,rp_BitMap(a1)

   lea         rastport(pc),a1
   moveq       #0,d0
   jsr         _LVOSetRast(a6)

   lea         view(pc),a1
   jsr         _LVOLoadView(a6)

   rts


paint_pixel:

*  For my purposes, I will place x in d0, y in d1 and color in d2 prior to
*  calling the routine.  See the Manx code accompanying this file for full
*  commentary.

   lea      $dff000,a0
   lea      bitmap,a2

   move.w   d2,d3                      Copy color.
   move.w   d1,d7                      Copy Y coordinate.
   mulu     bm_BytesPerRow(a2),d7      Byte offset of line containing Y.

   move.w   d0,d4                      Copy X coordinate.
   lsr.w    #4,d4
   lsl.w    #1,d4                      Divide by 8 while clearing bit 0.
   add.w    d4,d7                      Add X byte offset to Y offset.
   ext.l    d7

   move.w   d0,d4                      Copy X coordinate.
   andi.w   #$f,d4                     Retrieve bit additional.

   move.w   #$8000,d5                  Set bit representing byte's 'base'.
   lsr.w    d4,d5                      Move right to precise draw position.
   move.w   d5,d6                      Mask to OR a one for color draw.
   not.w    d6                         Mask to AND a zero for Bg color erase.

   move.b   bm_Depth(a2),d0            Number of planes to draw into.
   ext.w    d0
   subq.w   #1,d0                      Subtract one for dbra.

   clr.w    d1                         Begin counter at 0.  Increment below.

pixl61:

   move.w   d1,d2                      Place the 0 to whatever.
   lsl.w    #2,d2                      Multiply * 4 to increment plane ptr.
   movea.l  bm_Planes(a2,d2.w),a3      Retrieve this plane pointer.

   add.l    d7,a3                      Come to our pixel.
   btst     d1,d3                      Test the color bit in our plane.
   beq      pixl62                     Branch if unset.

   or.w     d5,(a3)                    Make sure the bit in the 'as shifted'
*                                      position is set to cause the draw.
   bra      pixl63                     Test next plane.

pixl62:

   and.w    d6,(a3)                    Make sure the bit in the 'as shifted'
*                                      position is NOT set to cause an erase.

pixl63:

   addq.w   #1,d1                      Advance to next plane, and to the
   dbra     d0,pixl61                  corresponding bit in the binary color
*                                      number.
   rts




gfxname:       GRAFNAME
dosname:       DOSNAME
colortable:    dc.w  $000,$fff,$f00,$0f0,$00f,$ff0,$0ff,$f0f

GfxBase:       ds.l   1
DosBase:       ds.l   1
mytask:        ds.l   1
returnmsg:     ds.l   1
cm:            ds.l   1
oldview:       ds.l   1
view:          ds.b   v_SIZEOF
vport:         ds.b   vp_SIZEOF
bitmap:        ds.b   bm_SIZEOF
rastport:      ds.b   rp_SIZEOF
rasinfo:       ds.b   ri_SIZEOF
fillcolor:     ds.w   1

                           end


