* Assemble with LWASM

 pragma noforwardrefmax   * Forces LWASM to do multi-pass refrences so it can use reuslts that are smaller then 16 bits

Testing       EQU   0  * 0 = no high speed poke, 1 = faster high speed poke & program autostarts
PIXELS_PER_LEN equ 32

  ORG   $FFB0        * Palette_0

CoCo3_Colours:
  FCB   %00000000    * Colour 0
  FCB   %00100010    * Colour 1
  FCB   %00110101    * Colour 2
  FCB   %00111110    * Colour 3

	ORG     $7BB0      * starts here so we can use $7C as direct page for variables
* Mona Lisa Brush movement table
* BRUSH = [
Brush:
  FDB   $030A,$37BE,$2F9B,$072B,$0E3C,$F59B,$8A91,$1B0B
  FDB   $0EBD,$9378,$B83E,$B05A,$70B5,$0280,$D0B1,$9CD2
  FDB   $2093,$209C,$3D11,$26D6,$DF19,$97F5,$90A3,$A347
  FDB   $8AF7,$0859,$29AD,$A32C,$7DFC,$0D7D,$D57A,$3051
  FDB   $D431,$542B,$B242,$B114,$8A96,$2914,$B0F1,$532C
  FDB   $0413,$0A09,$3EBB,$E916,$1877,$B8E2,$AC72,$80C7
  FDB   $5240,$8D3C,$3EAF,$AD63,$1E14,$B23D,$238F,$C07B
  FDB   $AF9D,$312E,$96CE,$25A7,$9E37,$2C44,$2BB9,$2139
* ];

CoCo_START:
***********************************************************
        ORCC    #$50                    * Disable interrupts
  IF Testing
        STB     $FFD9                  	* High Speed mode enabled
  ENDIF
        LDX     #$0000

* Clear the screen
!
        CLR     ,X+
        CMPX    #Brush
        BNE     <                       * All clear
* X now points to the Brush table
        LDA     #%01111100              * A = $7C
        STA     $FF90                   * CoCo 3 Mode, MMU Enabled, GIME IRQ Enabled, GIME FIRQ Enabled, Vector RAM at FEXX enabled, Standard SCS Normal, ROM Map 16k Int, 16k Ext
        TFR     A,DP                    * DP = $7C
        SETDP   $7C                     * Let the assembler know the DP value

* CoCo Prep
***********************************************************
* Set Hires Screen Resolution and the number of Colours
;        LDA     #%10000000              * = $80, Graphics mode, Colour output, 60 hz, max vertical res
;        LDB     #%00011010            	 * = $1A, 256 x 192 x 16 Colours requires 24,576 bytes = $6000 RAM
        LDD     #$801A                  * Graphics mode, Colour output, 60 hz, max vertical res & 256 x 192 x 16 Colours requires 24,576 bytes = $6000 RAM
        STD     $FF98                   * Graphics mode, Colour output, 60 hz, max vertical res
***********************************************************
      LEAU    cursor_y,PCR  * U = #cursor_y

next_part:
init_part:
      LDB   part		; part 0-63, from the end
      STB   length

; (word) crc_seed = word_seed;
      LDD   ,X++         ; get the next value in A and B
      STD   crc_seed+2   ; STA crc_seed LSB & STB crc_seed LLSB
      STD   ,U           ;	STA cursor_y & STB cursor_x
init_part_end

next_length:
      LDA   #PIXELS_PER_LEN-1
      STA   pixel

next_pixel:
* inlined_rnd           * crc_seed
      ASL   cursor_y-1  * LLSB
      ROL   cursor_y-2  * LSB
      ROL   cursor_y-3  * MSB
      ROL   cursor_y-4  * MMSB
      BCC   nofeedback

      LDB   #4          * Set to 4 above
      LEAY  -4,U        * U=crc_seed   ;  LDU   #crc_seed   * U=crc_seed
xor_seed_loop:
      LDA   ,Y          * Get the crc_seed
      EORA  -4,Y        * XOR the value
      STA   ,Y+         * save the new value + move pointer
      DECB              * decrement the counter
      BNE   xor_seed_loop ;   bpl	xor_seed_loop

      STA   direction	   * a=direction=crc_seed[0]  crc_seed LLSB

nofeedback:
move_cursor:
      LDB   direction  ; B=direction
      ANDB  #$02       ; and #2		; random value 0 or 2 for cursor_y/cursor_x
      LSRB             ; make it 0 or 1
      LDA   B,U        ; B=0 then LDA  cursor_y else B=1 then LDA cursor_x
      TST   direction
      BMI   >
      INCA
      INCA
!
      DECA
      ANDA  #$7F       ; and #$7F	; limit value to 0-127
      STA   B,U        ; sta cursor_y(or cursor_x)

drawpoint:
* drawPixel(bx, by, COLOR[part AND 3])
* bx is a range from (0 to 127)
* by is a range from (0 to 95)
* Coco 3 Screen resolution is 256 x 192 x 16 colours, starting at $0000
* each row is 128 bytes

      LDD   cursor_y          * D = address, A = Y - co-ordinate, B= x - co-ordinate
      CMPA  #96
      BHS   DoneDrawPoint
      ANDB  #$7F
      LSRA
      RORB
      TFR   D,Y
      LDB   part
      ANDB  #$03        * Make colour a range of 0 to 3
      BCC   >           * If carry is clear then it is an even number (left nibble used)
      LDA   #$F0
      BRA   OR_A_B
!
      LDA   #$10
      MUL               * Set high nibble with the colour (left nibble)
      LDA   #$0F
OR_A_B:
      ANDA  ,Y
      STB   SelfModA_OR_B+1  * Self mod to do an add of A & B
SelfModA_OR_B:
      ORA   #$FF
      STA   ,Y

DoneDrawPoint:
;;;;;;;; loop

      DEC   pixel     ;      DEC pixel
      BPL   next_pixel
      DEC   length     ;      DEC length
      BPL   next_length
      DEC   part     ;     DEC part
      BPL   next_part

      BRA  *      * Loop forever

part  FCB   63
xor_const:
;*      LLSB,LSB,MSB,MMSB
; 	FCB   $B7,$1D,$C1,$04  * Little Endian
  FCB   $04,$C1,$1D,$B7  * Big Endian
crc_seed:
;*      LLSB,LSB,MSB,MMSB
;  FCB   $E5,$54,$C8,$7E  * Little Endian
  FCB   $7E,$C8  * Big Endian
; next two bytes will be set when the program starts the crc_seed is 4 bytes so we have to make sure we make space for it
cursor_y  EQU   crc_seed+4
cursor_x  EQU   cursor_y+1
direction EQU   cursor_x+1		; this gets zeroed by setting graphics mode
pixel   EQU   direction+1
length  EQU   pixel+1

  IF Testing
      ORG   $A42E       * Make it autostart
      FDB   CoCo_START
  ENDIF

  END  CoCo_START
