* GREYSCAL VIEWING UTILITY, RANDY DING, 11/1993
* TAKES A 131x64n GROB WHERE N IS NUMBER OF FRAMES (SHADES OF GREY)
* IF 2 FRAMES, IT IS TAKEN AS A 3 SHADES OF GREY ENCODED GROB
* IF 3 FRAMES, IT IS TAKEN AS A 7 SHADES OF GREY ENCODED GROB
* NOTE 4 FRAME, 11 SHADES OF GREY ENCODED GROB IS NOT IMPLEMENTED (YET)
* ANY NUMBER OF FRAMES OTHER THAN 2 OR 3 WILL BE DISPLAYED IS A
*   RAPID SEQUENCE OF FRAMES, GREY SCALE WORKS WELL UP TO ABOUT 11 FRAMES!
* IMPORTANT, THE BEST WAY TO DESIGN FRAMES SEQUENCES IS FROM LIGHTEST
* TO DARKEST OR THE OTHER WAY AROUND, AS LONG AS THEY ARE IN ORDER,
* AND IT IS BETTER TO USE ODD NUMBER OF FRAMES.
* WHEN NUMBER OF FRAMES IS >= FIVE AND THERE ARE AN ODD NUMBER OF FRAMES
* THE PROGRAM WILL INTERLACE THEM, THAT IS TO DISPLAY EVERY OTHER ONE
* EACH PASS AND THEREBY REDUCE THE FLICKERING.

ASSEMBLE
	   NIBASC  /HPHP48-E/
RPL

::
 CK1NOLASTWD
 CK&DISPATCH1
 TWELVE 		       ( *grob object* )
 ::
  SKIP
  $ "v1.1 11/93 R Ding"
  DUPGROBDIM		       ( *must be 131 x 64*n grob* )
  BINT_131d #<> SWAP
  SIXTYFOUR		       ( *calculate number of frames* )
  #/			       ( *grobYsize / 64 -> remain, quotient* )
  SWAP
  #0<>			       ( *if remainder <> 0 then bad* )
  ROT OR ITE
  DROP			       ( *drop #frames and skip code if bad* )
  CODE

* only 1 of the following flag bits will be set at a time
:ILACE	   EQU	   0	       interlace flag bit in ST reg
:WT21	   EQU	   1	       2-1 frame weighting flag bit in ST reg
:WT421	   EQU	   2	       4-2-1 frame weighting flag bit in ST reg

DOGREY	   GOSBVL  =POP#       pop number of frames from RPL stack
	   R1=A.F  A	       save number of frames
	   GOSBVL  =SAVPTR     save registers
	   INTOFF	       totally disable keyboard interrupts
	   ST=0    15	       ''
	   A=DAT1  A	       D1 -> grob object now on top of stack
	   C=0	   A
	   LC(2)   20	       skip 20 nib prolog
	   A=A+C   A
	   R0=A.F  A	       save pointer to data grob first line
	   ?ABIT=0 0	       even address?
	   GOYES   :EVEN       skip if grob data is allready byte alligned

	   LC(1)   #C	       1100b, [disp on: b3] & [offset: b2 b1 b0]
	   D0=(5)  #00100      display bit offset address
	   DAT0=C  1	       shift display left 4 pixels
	   D0=(2)  #25	       line byte offset addr, nibs skipped per line
	   LC(3)   #FFE        signed number with bit 0 ignored
	   DAT0=C  X	       make byte offset = -2 nibs (1 byte)

:EVEN	   D0=(5)  #128        display line counter addr
	   D1=(5)  #120        display start addr
	   LC(2)   63
	   DAT0=C  B	       make line counter 63

	   ST=0    :ILACE      make flag bit = 1 if interlacing required
	   ST=0    :WT21       = 1 if only 2 frames, 2-1 weighting
	   ST=0    :WT421      = 1 if 3 frames, 4-2-1 weighting
	   A=R1.F  B	       recall number of frames
	   LC(2)   2
	   ?A#C    B
	   GOYES   :NOWT21
	   ST=1    :WT21       2-1 weighted frames if 2
	   GOTO    :STOFRAM
:NOWT21    LC(2)   3
	   ?A#C    B
	   GOYES   :NOWT421
	   ST=1    :WT421      4-2-1 weighted frames if 3
	   LA(2)   #32	       special bit sequence for interlacing 4-2-1
	   GOTO    :STOFRAM
:NOWT421   ?ABIT=0 0	       don't interlace if even # of frames
	   GOYES   :NOLACE
	   LC(2)   5
	   ?A<C    B	       don't interlace if less than 5 frames
	   GOYES   :NOLACE
	   ST=1    :ILACE
:NOLACE    A=A-1   B	       decr # frames, counts thru 0
:STOFRAM   R1=A.F  B

:MAIN	   C=R1.F  B	       #frames-1 or 4-2-1 interlacing bit sequence
	   D=C	   B
:MAIN1	   A=R0.F  A	       recall pointer to data, first frame
	   B=A	   A

:WAIT	   ?ST=0   :ILACE      test interlace flag
	   GOYES   :WAIT0
	   D=D+1   XS	       comp bit 8, the skip flag for interlacing
	   C=D	   XS
	   ?CBIT=0 8	       when interlacing, display every other frame
	   GOYES   :NEXT
:WAIT0	   A=DAT0  B	       wait for display refresh to be completed
	   ?ABIT=1 5	       line counter decriments from 3F to 0
	   GOYES   :WAIT0
:WAIT1	   A=DAT0  B	       waiting for bit 5 transition from 0 to 1
	   ?ABIT=0 5
	   GOYES   :WAIT1

	   A=B	   A
	   DAT1=A  A	       change screen start address

	   C=0	   A	       read keyboard
	   LC(3)   #1FF
	   OUT=C
	   GOSBVL  =CINRTN
	   ?C#0    A
	   GOYES   :EXIT       exit if key down
	   OUT=C	       stop reading keyboard

:NEXT	   ?ST=1   :WT421
	   GOYES   :DO421
	   D=D-1   B
	   GOC	   :GOMAIN     repeat frame sequence from top
	   ?ST=1   :ILACE
	   GOYES   :NEXT1      ignore weighting flag if interlacing
	   ?ST=0   :WT21
	   GOYES   :NEXT1      no 2-1 weighting
	   ?D#0    B	       repeat first frame again, 2 weighted
	   GOYES   :GOWAIT
:NEXT1	   LC(5)   64*34       nibs in one 131x64 grob, 34 nibs per line
	   B=B+C   A	       adjust pointer to next frame
:GOWAIT    GOTO    :WAIT
:DO421	   SB=0
	   DSRB.F  B
	   ?SB=0
	   GOYES   :NOSB421
	   GOTO    :NEXT1
:NOSB421   ?D=0    B
	   GOYES   :GOMAIN     restart sequence from top
	   GOTO    :MAIN1      don't reset interlace sequence counter
:GOMAIN    GOTO    :MAIN

:EXIT	   C=0	   X	       stop reading keyboard
	   OUT=C
	   LA(2)   63-8        here assuming menu row was originally on
	   DAT0=A  B	       reset line counter
	   GOSBVL  =D0->Row1   get original display address
	   AD0EX
	   DAT1=A  A	       reset display address
	   ?ABIT=0 0	       check for even address
	   GOYES   :EXITEVEN
	   LA(1)   #C	       1100b, [disp on: b3] & [offset: b2 b1 b0]
	   LC(3)   #FFE        signed number with bit 0 ignored
	   GOTO    :EXIT01
:EXITEVEN  LA(1)   #8
	   LC(3)   #0
:EXIT01    D1=(2)  #0	       reset bit offset
	   DAT1=A  1
	   D1=(2)  #25	       reset line byte offset
	   DAT1=C  X
	   INTON	       enable keyboard interrupts
	   ST=1    15	       ''
	   GOVLNG  =GETPTRLOOP recall registers then LOOP
  ENDCODE
  DROP			       ( *grob* )
 ;			       ( *end first dispatch* )

* begin second dispatch, RFU packed grob character string

 THREE			       ( *string object* )
 ::
  CODE			       ( *RFU code, taken apart by rpl48* )
       GOSBVL  =SAVPTR	       ( *and modified to work on the GX* )
       GOSBVL  =GARBAGECOL
       GOSBVL  =GETPTR
       C=DAT1  A
       D1=C
       A=DAT1  A
       LCHEX   02A2C
       ?C#A    A
       GOYES   LBC362 +00026
       D1=D1+  5
       A=DAT1  A
       LCHEX   0000F
       ?C>A    A
       GOYES   LBC362 +00014
       D1=D1+  5
       A=DAT1  A
       LCHEX   24652
       ?C=A    A
       GOYES   LBC366 +00006
LBC362 GOTO    LBC55F +001FC
LBC366 D1=D1+  5
       GOSBVL  =ROOM
       A=DAT1  A
       D1=D1+  5
       C=C-A   A
       GONC    LBC37F +00006
LBC37B GOTO    LBC554 +001D8
LBC37F C=C-CON A,10
       GOC     LBC37B -0000B
       CD1EX
       RSTK=C
       C=A     A
       RSTK=C
       GOSBVL  =CREATETEMP
       GOSBVL  =D1=DSKTOP  *	    changed by Randy D. 9/2/93
*	D1=(5)	#70579
*	C=DAT1	A
*	D1=C
       CD0EX
       DAT1=C  A
       D1=C
       C=RSTK
       R2=C.F  A
       C=RSTK
       R3=C.F  A
       GOSUB   LBC3D6 +00014
       ST=0    10
       GOSBVL  =GETPTR
       A=DAT0  A
       D0=D0+  5
       PC=(A)
LBC3D6 C=R3.F  A
       D0=C
       D=0     X
LBC3E2 D=D-1   XS
       GONC    LBC3F9 +00013
       LCHEX   700
       D=C     XS
       C=DAT0  B
       D=C     B
       D0=D0+  2
LBC3F9 D=D+D   B
       GOC     LBC403 +00006
       GOTO    LBC493 +00093
LBC403 LCHEX   04
       GOSUB   LBC524 +00119
       ?A#0    B
       GOYES   LBC464 +00056
       LCHEX   05
       GOSUB   LBC524 +0010C
       ?A=0    B
       GOYES   LBC428 +0000D
       LCHEX   1F
       A=A+C   B
       GOTO    LBC464 +0003F
LBC428 LCHEX   5E
LBC42C A=DAT0  B
       DAT1=A  1
       D0=D0+  1
       D1=D1+  1
       C=C-1   B
       GONC    LBC42C -00011
       A=R2.F  A
       LCHEX   0005F
       A=A-C   A
       GOC     LBC460 +00011
       ?A=0    A
       RTNYES
       R2=A.F  A
       GOTO    LBC3E2 -0007B
LBC460 GOTO    LBC55F +000FE
LBC464 B=A     B
       B=B-1   B
LBC46A C=DAT0  B
       DAT1=C  1
       D0=D0+  1
       D1=D1+  1
       B=B-1   B
       GONC    LBC46A -00011
       C=R2.F  A
       C=C-A   A
       GOC     LBC460 -00026
       ?C=0    A
       RTNYES
       R2=C.F  A
LBC493 LCHEX   02
       GOSUB   LBC524 +00089
       ?A#0    B
       GOYES   LBC4AE +00010
       LCHEX   04
       GOSUB   LBC524 +0007C
       A=A+CON B,8
LBC4AE A=A+CON B,4
       R0=A.F  A
       LCHEX   07
       GOSUB   LBC524 +00062
       CD0EX
       R3=C.F  A
       C=R0.F  B
       B=C     B
       A=A+1   A
       CD1EX
       D1=C
       C=C-A   A
       D0=C
       B=B-1   B
LBC4E4 C=DAT0  B
       DAT1=C  1
       D0=D0+  1
       D1=D1+  1
       B=B-1   B
       GONC    LBC4E4 -00011
       C=R2.F  A
       A=R0.F  A
       C=C-A   A
       GOC     LBC520 +0001A
       ?C=0    A
       RTNYES
       R2=C.F  A
       C=R3.F  A
       D0=C
       GOTO    LBC3E2 -0013B
LBC520 GOTO    LBC55F +0003E
LBC524 B=C     B
       A=0     A
LBC529 A=A+A   B
       D=D-1   XS
       GONC    LBC543 +00013
       LCHEX   700
       D=C     XS
       C=DAT0  B
       D=C     B
       D0=D0+  2
LBC543 D=D+D   B
       GONC    LBC54C +00005
       A=A+1   B
LBC54C B=B-1   B
       GONC    LBC529 -00027
       RTN
LBC554 LCHEX   04FBB
       GOTO    LBC566 +0000A
LBC55F LCHEX   18CA7
LBC566 RSTK=C
       ST=0    10
       GOSBVL  =GETPTR
       RTN
  ENDCODE
  DUPTYPEGROB?
  NOTcase DROP
  DUPGROBDIM		       ( *must be 131 x 64*n grob* )
  BINT_131d #<> SWAP
  SIXTYFOUR		       ( *calculate number of frames* )
  #/			       ( *grobYsize / 64 -> remain, quotient* )
  SWAP
  #0<>			       ( *if remainder <> 0 then bad* )
  ROT OR ITE
  DROP			       ( *drop #frames and skip code if bad* )
  CODE
	   GOTO    DOGREY
  ENDCODE
  DROP			       ( *grob* )
 ;			       ( *end second dispatch* )
;
