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
 | |
|   
 |