442 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			442 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
PUSHS "Printer Variables", WRAM0[PRINTER_VARS_START]
 | 
						|
vTooBusyForPrinter: db ; one if we're too busy to use the async thread for printer stuff
 | 
						|
vPrinterState: db ; options: NONE, READY, ERROR, FULL, PRINTING
 | 
						|
vPreviousPrinterState: db
 | 
						|
def PS_NONE equ 0
 | 
						|
def PS_READY equ 1
 | 
						|
def PS_ERROR equ 2
 | 
						|
def PS_FULL equ 3
 | 
						|
def PS_PRINTING equ 4
 | 
						|
vPrinterReturnValue: dw
 | 
						|
vPrinterReturnValuePrevious: dw
 | 
						|
vPrinterReturnValueChanged: db
 | 
						|
vBuildingByte: dw
 | 
						|
vPrinterIsReady: db
 | 
						|
 | 
						|
vPrinterRow: db
 | 
						|
vPrinterStart: db
 | 
						|
POPS
 | 
						|
 | 
						|
CheckForPrinter:
 | 
						|
  ld a, $F
 | 
						|
  ld hl, ZEROES
 | 
						|
  ld bc, 0
 | 
						|
  call SendPacket
 | 
						|
  ret
 | 
						|
 | 
						|
 | 
						|
SendPacket:
 | 
						|
  ; a should be the command byte
 | 
						|
  ; hl shoulld point at data to send
 | 
						|
  ; bc should be the length of data
 | 
						|
  ; squashes de for the checksum.
 | 
						|
  push af
 | 
						|
  
 | 
						|
  ld a, $88
 | 
						|
  call SendByte
 | 
						|
  ld a, $33
 | 
						|
  call SendByte
 | 
						|
  pop af
 | 
						|
  ld d, 0
 | 
						|
  ld e, a ; the checksum always starts with a vallue of whatever the command is 
 | 
						|
  call SendByte
 | 
						|
  ld a, $00 
 | 
						|
  call SendByte
 | 
						|
  ld a, c 
 | 
						|
  call SendByte
 | 
						|
  ld a, b
 | 
						|
  call SendByte
 | 
						|
  
 | 
						|
  ld a, e
 | 
						|
  add a, b
 | 
						|
  ld e, a 
 | 
						|
  ld a, d
 | 
						|
  adc a, 0
 | 
						|
  ld d, a 
 | 
						|
  
 | 
						|
  ld a, e
 | 
						|
  add a, c 
 | 
						|
  ld e, a 
 | 
						|
  ld a, d 
 | 
						|
  adc a, 0
 | 
						|
  ld d, a
 | 
						|
  
 | 
						|
  ld a, b
 | 
						|
  or a, c 
 | 
						|
  jp z, .doneWithByteLoop
 | 
						|
.byteLoop
 | 
						|
  ld a, [hl]
 | 
						|
  add a, e
 | 
						|
  ld e, a 
 | 
						|
  ld a, d
 | 
						|
  adc a, 0
 | 
						|
  ld d, a 
 | 
						|
  
 | 
						|
  ld a, [hl+]
 | 
						|
  call SendByte
 | 
						|
  dec bc
 | 
						|
  ld a, b
 | 
						|
  or a, c 
 | 
						|
  jp nz, .byteLoop
 | 
						|
.doneWithByteLoop
 | 
						|
  
 | 
						|
  ld a, e
 | 
						|
  call SendByte
 | 
						|
  
 | 
						|
  ld a, d
 | 
						|
  call SendByte
 | 
						|
  
 | 
						|
  ld a, $00
 | 
						|
  call SendByte
 | 
						|
  ld [vPrinterReturnValue], a 
 | 
						|
 | 
						|
  ld a, $00
 | 
						|
  call SendByte
 | 
						|
  ld [vPrinterReturnValue+1], a 
 | 
						|
  
 | 
						|
  call UpdatePrinterStatus
 | 
						|
  ret
 | 
						|
 | 
						|
UpdatePrinterStatus:
 | 
						|
;vPrinterState: db ; options: NONE, READY, ERROR, FULL, PRINTING
 | 
						|
  ld a, PS_NONE
 | 
						|
  ld [vPrinterState], a 
 | 
						|
  ld a, [vPrinterReturnValue]
 | 
						|
  cp a, $81
 | 
						|
  ret nz ; if the alive byte isn't $81, return with PS_NONE
 | 
						|
  
 | 
						|
  ld a, PS_ERROR
 | 
						|
  ld [vPrinterState], a 
 | 
						|
  ld a, [vPrinterReturnValue+1]
 | 
						|
  and a, $F0
 | 
						|
  ret nz ; if the top nibble is non-zero, there's some error
 | 
						|
  
 | 
						|
  ld a, PS_FULL
 | 
						|
  ld [vPrinterState], a 
 | 
						|
  ld a, [vPrinterReturnValue+1]
 | 
						|
  bit 2, a 
 | 
						|
  ret nz ; if the FULL bit iis set then it's full\
 | 
						|
  
 | 
						|
  ld a, PS_PRINTING
 | 
						|
  ld [vPrinterState], a 
 | 
						|
  ld a, [vPrinterReturnValue+1]
 | 
						|
  bit 1, a 
 | 
						|
  ret nz ; if the printing bit is set then it's printing
 | 
						|
  
 | 
						|
  ld a, PS_READY
 | 
						|
  ld [vPrinterState], a 
 | 
						|
  ret ; if we didn't find any of the bits we check for, it's good to go
 | 
						|
 | 
						|
 | 
						|
PrepNetwork:
 | 
						|
  ld a, 0 
 | 
						|
  ld [vPrinterStart], a 
 | 
						|
  
 | 
						|
  ld a, PS_NONE
 | 
						|
  ld [vPreviousPrinterState], a 
 | 
						|
  
 | 
						|
  ld hl, rSC
 | 
						|
  set 0, [hl] 
 | 
						|
  ret 
 | 
						|
 | 
						|
SendByte:
 | 
						|
; waits until the thing is free, then sends the byte in a. puts the receiived
 | 
						|
; byte in a anad returns.
 | 
						|
  push hl
 | 
						|
  
 | 
						|
  ld hl, rSC
 | 
						|
  
 | 
						|
  .waitForFree
 | 
						|
    bit 7, [hl]
 | 
						|
    jp nz, .waitForFree
 | 
						|
  
 | 
						|
  ld [rSB], a
 | 
						|
  
 | 
						|
  set 7, [hl] ; request transfer 
 | 
						|
  
 | 
						|
  .waitForResponse
 | 
						|
    bit 7, [hl]
 | 
						|
    jp nz, .waitForResponse
 | 
						|
  
 | 
						|
  ld a, [rSB]
 | 
						|
  
 | 
						|
  pop hl
 | 
						|
  ret 
 | 
						|
  
 | 
						|
KickOffPrintJob:
 | 
						|
  ld a, 1 
 | 
						|
  ld [vBlocked], a 
 | 
						|
  
 | 
						|
  ld a, 1
 | 
						|
  ld [vPrinterStart],a
 | 
						|
  ld a, 0 
 | 
						|
  ld [vPrinterRow], a
 | 
						|
 | 
						|
  call CardPrintPrep  
 | 
						|
  call CardUpdate
 | 
						|
 | 
						|
  ret
 | 
						|
  
 | 
						|
RunPrintJob:
 | 
						|
  ld a, [vPrinterStart]
 | 
						|
  cp a, 0
 | 
						|
  ret z
 | 
						|
  
 | 
						|
  ld a, [vPrinterRow] ; printer row holds the row of printing we're on; this
 | 
						|
  ; combines the tile row of the card + borders and also when to wait for printing
 | 
						|
  ; to finish. also later we use the register for 'whetther it's a row of the card'
 | 
						|
  bit 0, a ; on even numbered printer rows just jump to the "wait for printable"
 | 
						|
  ; routine. this should increase the printer row only if the printer is ready
 | 
						|
  ; and return.
 | 
						|
  jp z, WaitForPrintable
 | 
						|
  
 | 
						|
  cp a, 1 ; if the print row is 1, then we want the top border
 | 
						|
  jp nz, :+
 | 
						|
    call PlanTopRow
 | 
						|
    call BuildRow
 | 
						|
    set 7, a ; set bit 7 as a flaag thatt we've already taken one of these branches.
 | 
						|
  :
 | 
						|
  cp a, 35 ; if the print row is 35, we want the bottom border
 | 
						|
  jp nz, :+
 | 
						|
    call PlanBottomRow
 | 
						|
    call BuildRow
 | 
						|
    set 7, a 
 | 
						|
  :
 | 
						|
  cp a, 37 ; if the row is 37, we want to clear the buffer and reset
 | 
						|
  jp nz, :+
 | 
						|
    call ClearBuffer
 | 
						|
    
 | 
						|
    ld a, 0 
 | 
						|
    ld [vBlocked], a 
 | 
						|
    ld [vPrinterStart],a
 | 
						|
    ld [vPrinterRow], a
 | 
						|
    ld a, 1 
 | 
						|
    ld [vPrinterIsReady], a
 | 
						|
    
 | 
						|
    ret ; don't finish sending the print if we're cleaning up.
 | 
						|
  :
 | 
						|
  bit 7, a ; if this bit was set by one of the previous branches, then
 | 
						|
  ; we aren't drawing a row; otherwise the rest of a holds the printer row for
 | 
						|
  ; a card row to draw
 | 
						|
  jp nz, :+
 | 
						|
    res 7, a ; get rid of that "drawing a row" bit
 | 
						|
    srl a ; divide by two to get rid of the "drawing or waiting" bit
 | 
						|
    dec a ; subtract one to get the row index into card space
 | 
						|
    
 | 
						|
    call PlanRowA
 | 
						|
    call BuildRow
 | 
						|
    
 | 
						|
    ld b, 8 ; pre-increment so that when we pre-decrement in the loop later it works
 | 
						|
    sla a 
 | 
						|
    sla a 
 | 
						|
    sla a
 | 
						|
    add a, 24 ; multiply by 8 and add 24 to get from card tile space to sprite space
 | 
						|
    add a, b ; start from the bottom row of these tiles, a*8 + 7
 | 
						|
    ld c, a ; c holds the current scanline we're looking at for this inner loop
 | 
						|
    .addSpriteLinesLoop
 | 
						|
      dec c 
 | 
						|
      
 | 
						|
      ld a, c
 | 
						|
      ld [vCurrentScanline], a
 | 
						|
      call AddSpritesToLine
 | 
						|
  
 | 
						|
      dec b
 | 
						|
      jp nz, .addSpriteLinesLoop
 | 
						|
    .doneAddSpriteLinesLoop
 | 
						|
  :
 | 
						|
  
 | 
						|
  call DoubleTheBuffer
 | 
						|
  call PrintTheBuffer
 | 
						|
  ld a, [vPrinterRow]
 | 
						|
  inc a 
 | 
						|
  ld [vPrinterRow], a
 | 
						|
  ret
 | 
						|
  
 | 
						|
PlanTopRow:
 | 
						|
  ; draw the top of a card as tile ids in buffer one
 | 
						|
  ld hl, CardBrowse.UITilemap
 | 
						|
  ld bc, 10
 | 
						|
  ld de, BUFFER_ONE
 | 
						|
  call CopyRange ; copy tiles for the top row to the first buffer
 | 
						|
  ret
 | 
						|
PlanRowA: ; a should be which row of a tile map we should draw
 | 
						|
  push af
 | 
						|
  
 | 
						|
  ld de, BUFFER_ONE
 | 
						|
  
 | 
						|
  ld a, $0b
 | 
						|
  ld [de], a
 | 
						|
  inc de
 | 
						|
 | 
						|
  call FindCardTileMap ; now hl points at the beginning of the tile map
 | 
						|
  
 | 
						|
  pop af
 | 
						|
  push af
 | 
						|
  
 | 
						|
  sla a
 | 
						|
  sla a
 | 
						|
  sla a ; multiply row number by 8 for the stride of the tile map
 | 
						|
  ld b, 0
 | 
						|
  ld c, a ; advance to the row we're looking for.
 | 
						|
  add hl, bc
 | 
						|
  ld b, 8
 | 
						|
  :
 | 
						|
    ld a, [hl+] 
 | 
						|
    ld [de], a 
 | 
						|
    inc de
 | 
						|
    dec b
 | 
						|
    jp nz, :-
 | 
						|
  
 | 
						|
  ld a, $0c
 | 
						|
  ld [de], a 
 | 
						|
  
 | 
						|
  pop af
 | 
						|
  
 | 
						|
  ret
 | 
						|
PlanBottomRow:
 | 
						|
  ; draw the bottom of a card as tile ids in buffer one
 | 
						|
  ld hl, CardBrowse.UITilemap + 20*17 ;
 | 
						|
  ld bc, 10
 | 
						|
  ld de, BUFFER_ONE
 | 
						|
  call CopyRange ; copy tiles for the top row to the first buffer
 | 
						|
  ret
 | 
						|
  
 | 
						|
BuildRow:
 | 
						|
  ; assuming buffer one contains a sequence of ten tile IDs
 | 
						|
  ; this writes the tile data for each of those tiles sequentially into BUFFER_TWO
 | 
						|
  push af
 | 
						|
  ld hl, BUFFER_ONE
 | 
						|
  ld de, BUFFER_TWO
 | 
						|
  ld c, 10
 | 
						|
  .loop
 | 
						|
    push bc
 | 
						|
    ld a, [hl+] ; fetch a tile ID
 | 
						|
    push hl
 | 
						|
    ld hl, UITiles
 | 
						|
    cp a, 26
 | 
						|
    jp c, :+
 | 
						|
      ; if the tile id is greater than 26, then we need to fetch from the card data
 | 
						|
      sub a, 26 ; and undo the offset encoded into the tile map
 | 
						|
      call FindCardKeyTiles
 | 
						|
    :
 | 
						|
    call FindTileData
 | 
						|
    ; now hl points to tile data, de points to a spot in buffer 2
 | 
						|
    ld bc, 16
 | 
						|
    call CopyRange
 | 
						|
    pop hl
 | 
						|
    pop bc
 | 
						|
    dec c
 | 
						|
    jp nz, .loop
 | 
						|
  pop af
 | 
						|
  ret
 | 
						|
DoubleTheBuffer:
 | 
						|
  ld hl, BUFFER_TWO
 | 
						|
  ld de, BUFFER_ONE
 | 
						|
  
 | 
						|
  ld a, 10
 | 
						|
  .topHalfLoop
 | 
						|
    push hl
 | 
						|
    push af
 | 
						|
    call WriteTopHalfDoubledTile
 | 
						|
    pop af
 | 
						|
    pop hl
 | 
						|
    ld bc, 16
 | 
						|
    add hl, bc
 | 
						|
    dec a 
 | 
						|
    jp nz, .topHalfLoop
 | 
						|
    
 | 
						|
  ld hl, BUFFER_TWO
 | 
						|
  ld a, 10
 | 
						|
  .bottomHalfLoop
 | 
						|
    push hl
 | 
						|
    push af
 | 
						|
    ld bc, 8
 | 
						|
    add hl, bc
 | 
						|
    call WriteTopHalfDoubledTile
 | 
						|
    pop af
 | 
						|
    pop hl
 | 
						|
    ld bc, 16
 | 
						|
    add hl, bc
 | 
						|
    dec a 
 | 
						|
    jp nz, .bottomHalfLoop
 | 
						|
  
 | 
						|
  ret
 | 
						|
PrintTheBuffer:
 | 
						|
  call ClearBuffer
 | 
						|
  
 | 
						|
  ld a, 4 ; fill buffer
 | 
						|
  ld hl, BUFFER_ONE
 | 
						|
  ld bc, $280
 | 
						|
  call SendPacket
 | 
						|
  
 | 
						|
  call SendEmpty
 | 
						|
  
 | 
						|
  call SendPrint
 | 
						|
  ret
 | 
						|
 | 
						|
 | 
						|
WaitForPrintable:
 | 
						|
  ld a, $F
 | 
						|
  ld hl, ZEROES
 | 
						|
  ld bc, 0
 | 
						|
  call SendPacket
 | 
						|
  
 | 
						|
   ; NONE, READY, ERROR, FULL, PRINTING
 | 
						|
   
 | 
						|
  ld a, [vPrinterState]
 | 
						|
  cp a, PS_PRINTING
 | 
						|
  ret z
 | 
						|
  cp a, PS_ERROR
 | 
						|
  ret z
 | 
						|
  cp a, PS_NONE
 | 
						|
  ret z
 | 
						|
  
 | 
						|
  call ClearBuffer
 | 
						|
  
 | 
						|
  ld a, [vPrinterState]
 | 
						|
  cp a, PS_FULL
 | 
						|
  ret z
 | 
						|
  
 | 
						|
  ld a, [vPrinterRow]
 | 
						|
  inc a 
 | 
						|
  ld [vPrinterRow], a 
 | 
						|
  
 | 
						|
  ret
 | 
						|
 | 
						|
 | 
						|
SendEmpty:
 | 
						|
  ld a, 4
 | 
						|
  ld hl, ZEROES
 | 
						|
  ld bc, 0
 | 
						|
  call SendPacket
 | 
						|
  ret
 | 
						|
  
 | 
						|
 | 
						|
SendPrint:
 | 
						|
  call SendEmpty
 | 
						|
 | 
						|
  ld hl, BUFFER_ONE
 | 
						|
  ld a, 1 ; number of sheets
 | 
						|
  ld [hl+], a
 | 
						|
  ld a, $00 ; margins
 | 
						|
  ld [hl+], a 
 | 
						|
  ld a, $e4 ; palette
 | 
						|
  ld [hl+], a 
 | 
						|
  ld a, $7f ; exposure
 | 
						|
  ld [hl+], a 
 | 
						|
  
 | 
						|
  ld a, 2 ; print
 | 
						|
  ld hl, BUFFER_ONE
 | 
						|
  ld bc, 4
 | 
						|
  call SendPacket
 | 
						|
  ret
 | 
						|
  
 | 
						|
  
 | 
						|
ClearBuffer:
 | 
						|
  ld a, $1
 | 
						|
  ld hl, ZEROES
 | 
						|
  ld bc, 0
 | 
						|
  call SendPacket
 | 
						|
  
 | 
						|
  ret
 | 
						|
  
 |