' SPRITER.LST
' Make sure a JOYSTICK is connected !
' I had one connected to PORT 2 so I'm not CERTAIN it will work with any
' other PORT (although it should). SMILEY1.CUR and SMILEY2.CUR were the
' sprites used when putting together this code, so you should load THEM
' (although you really can load ANY two sprite CUR files you like).
'
' Moving the JOYSTICK moves the sprite and prints the sprite direction
' on the top of the screen (as well as the fire button status).
'
' This file was created on an STe and should work on all ST/STe's in
' L/M/H resolution. I don't know if it will work anywhere else.
' ---------------------------------------------------------------------|
@limits                ! DETERMINE SCREEN X,Y,W,H
@lode.sprite
' ---------------------| LOAD SPRITES
> PROCEDURE lode.sprite
  ' ----------------------------|LOAD FIRST CURSOR
  ti$="LOAD FIRST CURSOR"
  PRINT AT(1,1);ti$
  '
  ' #ti$ below is used by TOS 1.4+ to put a "message" in the fileselector.
  ' If you don't have TOS 1.4+ your system will simply ignore #ti$
  ' IOW: You can leave it in, it won't hurt anything.
  '
  FILESELECT #ti$,"\*.CUR","SPRITE_1.CUR",file$
  IF file$=""
    EDIT
  ENDIF
  OPEN "I",#1,file$       ! Open ("I"nput ) the file
  INPUT #1,dummy$         ! Input my personal file identifier
  IF dummy$<>"' UMSP25"   ! If file ID is incorrect
    '
    ALERT 3,"|This is NOT a valid |sprite .CUR file ! ",1," Abort ",lk%
    '
    CLOSE #1              ! Remember to CLOSE the file !
    END
  ENDIF
  l$=INPUT$(1,#1)         ! Input first string (character) in string
  l%=ASC(l$)              ! Return ASCII code of the first string in l$
  m1$=INPUT$(l%,#1)       ! Input string (length of string, #1)
  CLOSE #1                ! Close file
  ' ----------------------------|LOAD SECOND CURSOR
  ti$="LOAD SECOND CURSOR"
  PRINT AT(1,1);ti$
  FILESELECT #ti$,"\*.CUR","SPRITE_2.CUR",file2$
  IF file2$=""
    EDIT
  ENDIF
  OPEN "I",#1,file2$
  INPUT #1,dummy$
  IF dummy$<>"' UMSP25"
    ALERT 3,"|This is NOT a valid |sprite .CUR file ! ",1," Abort ",lk%
    CLOSE #1
    END
  ENDIF
  l1$=INPUT$(1,#1)
  l1%=ASC(l1$)
  m2$=INPUT$(l1%,#1)
  CLOSE #1
  ' ----------------------------| JOYSTICK READER
  @joystick
  EDIT
RETURN
' ---------------------| Set up IKBD to return the JOYSTICK packet
> PROCEDURE joystick
  '
  mc$=MKI$(&H23C8)+MKL$(*a%)+MKI$(&H4E75)   !Convert numbers into char. string
  '
  v%=XBIOS(34)+24       !Address of table w/keyboard processor address.
  o%=LPEEK(v%)          !read 4 bytes starting at address v%
  LPOKE v%,VARPTR(mc$)  !write V:mc$ as a 4 byte value to the address v%
  a%=0
  OUT 4,&H16            !IKBD
  '
  REPEAT                ! Wait for interrupt
  UNTIL a%              ! (the value of the joystick packet is stored in a%)
  '
  LPOKE v%,o%
  joy_0%=a%+1
  joy_1%=a%+2
  OUT 4,&H14
  '
  PRINT AT(1,1);"Press any key to quit."
  '
  a=50                  ! SPRITE coordinates
  b=50
  SPRITE m1$,b,a        ! Place SPRITE on screen at 50,50
  '
  REPEAT
    PRINT AT(1,2);"Joystick: ";(PEEK(a%) AND 1)+1
    @output(PEEK(joy_1%))
  UNTIL INKEY$<>""
  OUT 4,8
RETURN
' ---------------------| SPRITE OUTPUT CONTROL
> PROCEDURE output(x%)
  IF x% AND 128      ! JOYSTICK BUTTON
    PRINT "Button"
  ENDIF
  IF x% AND 1        ! JOYSTICK UP
    IF a>wy          ! If not at top of screen,
      DEC a          ! continue up !
    ENDIF
    VSYNC            ! To reduce screen flicker
    IF b<20          ! If sprite has changed due to screen location,
      SPRITE m2$     ! clean up after 2nd sprite before moving up.
    ENDIF
    SPRITE m1$,b,a   ! Draw first sprite
    PRINT "Up    "
  ENDIF
  IF x% AND 2        ! JOYSTICK DOWN
    IF a<wh          ! If not at bottom of screen,
      INC a          ! continue down !
    ENDIF
    VSYNC
    IF b<20          ! If sprite has changed due to screen location,
      SPRITE m2$     ! clean up after 2nd sprite before moving down.
    ENDIF
    SPRITE m1$,b,a   ! Draw first sprite
    PRINT "Down  "
  ENDIF
  IF x% AND 4        ! JOYSTICK LEFT
    IF b>wx+10       ! If not at left (plus 10 keeps it "on-screen"),
      DEC b          ! continue left !
    ENDIF
    IF b>20          ! If sprite is more than 20 from left,
      VSYNC
      SPRITE m1$,b,a   ! use first sprite
    ELSE
      VSYNC
      SPRITE m1$       ! Clean up after first sprite and
      SPRITE m2$,b,a   ! draw second sprite.
    ENDIF
    PRINT "Left  "
  ENDIF
  IF x% AND 8        ! JOYSTICK RIGHT
    IF b<=ww-10      ! If not at right (minus 10 to keep it "on-screen")
      INC b          ! continue right !
    ENDIF
    VSYNC
    IF b<20          ! If sprite has changed due to screen location,
      SPRITE m2$     ! clean up after second sprite before continuing right.
    ENDIF
    SPRITE m1$,b,a
    PRINT "Right "
  ENDIF
  PRINT CHR$(27);"K"
RETURN
' ---------------------| SCREEN LIMITS
> PROCEDURE limits
  ' You can use your own routines to determine screen x,y,w,h, especially
  ' if your machine doesn't support LINE A variables.
  wx=0                 !Screen x (left)
  wy=10                !Screen y (top)
  ww=INT{L~A-12}       !Screen w (right)
  wh=INT{L~A-4}-10     !Screen h (bottom)
RETURN
' ---------------------|
' ---------------------------------------------------------------------|
' This is my first attempt in "dealing" w/sprites, so obviously the code
' is not very efficient. SPRITER.LST is FREEWARE, so feel free to do
' whatever you deem fit with the code, I hope you find it somewhat useful.
' If nothing else you may have learned something you didn't know before !
' Happy Hacking !  --| Uncle Carl
