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 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 UpdatePrintUI: ld a, [vPrinterState] cp a, PS_NONE ld hl, BanishPrinterUI jp z, Async_Spawn_HL cp a, PS_READY ld hl, SummonPrinterUI jp z, Async_Spawn_HL cp a, PS_ERROR ld hl, ShowErrorUI jp z, Async_Spawn_HL cp a, PS_PRINTING ld hl, ShowPrinting jp z, Async_Spawn_HL cp a, PS_FULL ld hl, ShowFull jp z, Async_Spawn_HL ld hl, BanishPrinterUI jp Async_Spawn_HL UpdatePrintUIImmediate: ld a, [vPrinterReturnValue] cp a, $81 call z, SummonPrinterUI ld a, [vPrinterReturnValue] cp a, $81 call nz, BanishPrinterUI ret BanishPrinterUI: ld hl, PrinterNotDetected ld de, _SCRN0 + 32*1 + 17 ld b, 2 ld c, 2 call CopyTilesToMap ret ShowErrorUI: ld hl, PrinterError ld de, _SCRN0 + 32*1 + 17 ld b, 2 ld c, 2 call CopyTilesToMap ret ShowPrinting: ld hl, PrinterPrinting ld de, _SCRN0 + 32*1 + 17 ld b, 2 ld c, 2 call CopyTilesToMap ret ShowFull: ld hl, PrinterFull ld de, _SCRN0 + 32*1 + 17 ld b, 2 ld c, 2 call CopyTilesToMap ret SummonPrinterUI: ld hl, PrinterAvailable ld de, _SCRN0 + 32*1 + 17 ld b, 2 ld c, 2 call CopyTilesToMap 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 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 ld b, b 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 ld b, b 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 ld b, b 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 ld b, b 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 PrinterTiles: db $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 db $00,$1c,$00,$0e,$38,$3f,$64,$7f,$7f,$7f,$7f,$40,$7f,$40,$3f,$3f db $00,$00,$00,$00,$00,$00,$06,$b6,$ff,$ff,$ff,$11,$ff,$11,$fe,$fe db $00,$00,$00,$80,$0e,$8e,$12,$9e,$24,$bc,$38,$b8,$00,$80,$00,$00 db $00,$00,$00,$00,$5a,$5a,$92,$92,$5a,$5a,$52,$52,$9b,$9b,$00,$00 db $00,$00,$18,$98,$18,$98,$18,$98,$18,$98,$00,$80,$18,$98,$00,$00 db $00,$00,$00,$00,$d8,$d8,$94,$94,$d8,$d8,$94,$94,$d2,$d2,$00,$00 db $00,$00,$00,$80,$19,$99,$15,$95,$19,$99,$11,$91,$11,$91,$00,$00 db $00,$00,$00,$00,$92,$92,$5a,$5a,$96,$96,$52,$52,$52,$52,$00,$00 db $00,$00,$00,$80,$1d,$9d,$11,$91,$19,$99,$11,$91,$11,$91,$00,$00 db $00,$00,$00,$00,$52,$52,$52,$52,$52,$52,$52,$52,$db,$db,$00,$00 PrinterTiles.End: ; $22 PrinterNotDetected: db $00, $00 db $13, $00 PrinterAvailable: db $f1, $f2 db $f3, $f4 PrinterPrinting: db $f1, $f2 db $f7, $f8 PrinterError: db $f1, $f2 db $f5, $f6 PrinterFull: db $f1, $f2 db $f9, $fa