pokecrystal/engine/printer/printer_serial.asm

629 lines
12 KiB
NASM

Printer_StartTransmission:
ld hl, wGameboyPrinterRAM
ld bc, wGameboyPrinterRAMEnd - wGameboyPrinterRAM
xor a
call Printer_ByteFill
xor a
ldh [rSB], a
ldh [rSC], a
ld [wPrinterOpcode], a
ld hl, wPrinterConnectionOpen
set 0, [hl]
ld a, [wGBPrinterBrightness]
ld [wPrinterExposureTime], a
xor a
ld [wJumptableIndex], a
ret
PrinterJumptableIteration:
jumptable .Jumptable, wJumptableIndex
.Jumptable:
dw Print_InitPrinterHandshake ; 00
dw Printer_CheckConnectionStatus ; 01
dw Printer_WaitSerial ; 02
dw Printer_StartTransmittingTilemap ; 03
dw Printer_TransmissionLoop ; 04
dw Printer_WaitSerialAndLoopBack2 ; 05
dw Printer_EndTilemapTransmission ; 06
dw Printer_TransmissionLoop ; 07
dw Printer_WaitSerial ; 08
dw Printer_SignalSendHeader ; 09
dw Printer_TransmissionLoop ; 0a
dw Printer_WaitSerial ; 0b
dw Printer_WaitUntilFinished ; 0c
dw Printer_Quit ; 0d
dw Printer_NextSection ; 0e
dw Printer_WaitSerial ; 0f
dw Printer_SignalLoopBack ; 10
dw Printer_SectionOne ; 11
dw Printer_NextSectionWaitLoopBack ; 12
dw Printer_WaitLoopBack ; 13
_Printer_NextSection:
ld hl, wJumptableIndex
inc [hl]
ret
Printer_PrevSection:
ld hl, wJumptableIndex
dec [hl]
ret
Printer_Quit:
xor a
ld [wPrinterStatusFlags], a
ld hl, wJumptableIndex
set 7, [hl]
ret
Printer_NextSection:
call _Printer_NextSection
ret
Printer_SectionOne:
ld a, $1
ld [wJumptableIndex], a
ret
Print_InitPrinterHandshake:
call Printer_ResetData
ld hl, PrinterDataPacket1
call Printer_CopyPacket
xor a
ld [wPrinterSendByteCounter], a
ld [wPrinterSendByteCounter + 1], a
ld a, [wPrinterQueueLength]
ld [wPrinterRowIndex], a
call _Printer_NextSection
call Printer_WaitHandshake
ld a, PRINTER_STATUS_CHECKING
ld [wPrinterStatus], a
ret
Printer_StartTransmittingTilemap:
call Printer_ResetData
; check ???
ld hl, wPrinterRowIndex
ld a, [hl]
and a
jr z, Printer_EndTilemapTransmission
; send packet 3
ld hl, PrinterDataPacket3 ; signal start of transmission
call Printer_CopyPacket
; prepare to send 40 tiles
call Printer_Convert2RowsTo2bpp
ld a, LOW(40 tiles)
ld [wPrinterSendByteCounter], a
ld a, HIGH(40 tiles)
ld [wPrinterSendByteCounter + 1], a
; compute the checksum
call Printer_ComputeChecksum
call _Printer_NextSection
call Printer_WaitHandshake
ld a, PRINTER_STATUS_TRANSMITTING
ld [wPrinterStatus], a
ret
Printer_EndTilemapTransmission:
; ensure that we go from here to routine 7
ld a, $6
ld [wJumptableIndex], a
; send packet 4
ld hl, PrinterDataPacket4 ; signal no transmission
call Printer_CopyPacket
; send no tile data
xor a
ld [wPrinterSendByteCounter], a
ld [wPrinterSendByteCounter + 1], a
call _Printer_NextSection
call Printer_WaitHandshake
ret
Printer_SignalSendHeader:
call Printer_ResetData
ld hl, PrinterDataPacket2 ; signal request print
call Printer_CopyPacket
; prepare to send 1 tile
call Printer_StageHeaderForSend
ld a, LOW(4)
ld [wPrinterSendByteCounter], a
ld a, HIGH(4)
ld [wPrinterSendByteCounter + 1], a
; compute the checksum
call Printer_ComputeChecksum
call _Printer_NextSection
call Printer_WaitHandshake
ld a, PRINTER_STATUS_PRINTING
ld [wPrinterStatus], a
ret
Printer_SignalLoopBack:
call Printer_ResetData
; send packet 1
ld hl, PrinterDataPacket1 ; signal no transmission
call Printer_CopyPacket
; send no tile data
xor a
ld [wPrinterSendByteCounter], a
ld [wPrinterSendByteCounter + 1], a
ld a, [wPrinterQueueLength]
ld [wPrinterRowIndex], a
call _Printer_NextSection
call Printer_WaitHandshake
ret
Printer_WaitSerial:
ld hl, wPrinterSerialFrameDelay
inc [hl]
ld a, [hl]
cp $6
ret c
xor a
ld [hl], a
call _Printer_NextSection
ret
Printer_WaitSerialAndLoopBack2:
ld hl, wPrinterSerialFrameDelay
inc [hl]
ld a, [hl]
cp $6
ret c
xor a
ld [hl], a
ld hl, wPrinterRowIndex
dec [hl]
call Printer_PrevSection
call Printer_PrevSection
ret
Printer_CheckConnectionStatus:
ld a, [wPrinterOpcode]
and a
ret nz
ld a, [wPrinterHandshake]
cp $ff
jr nz, .printer_connected
ld a, [wPrinterStatusFlags]
cp $ff
jr z, .printer_error
.printer_connected
ld a, [wPrinterHandshake]
cp $81
jr nz, .printer_error
ld a, [wPrinterStatusFlags]
cp $0
jr nz, .printer_error
ld hl, wPrinterConnectionOpen
set 1, [hl]
ld a, $5
ld [wHandshakeFrameDelay], a
call _Printer_NextSection
ret
.printer_error
ld a, $ff
ld [wPrinterHandshake], a
ld [wPrinterStatusFlags], a
ld a, $e
ld [wJumptableIndex], a
ret
Printer_TransmissionLoop:
ld a, [wPrinterOpcode]
and a
ret nz
ld a, [wPrinterStatusFlags]
and $f0
jr nz, .enter_wait_loop
ld a, [wPrinterStatusFlags]
and $1
jr nz, .cycle_back
call _Printer_NextSection
ret
.cycle_back
call Printer_PrevSection
ret
.enter_wait_loop
ld a, $12 ; Printer_NextSectionWaitLoopBack
ld [wJumptableIndex], a
ret
Printer_WaitUntilFinished:
ld a, [wPrinterOpcode]
and a
ret nz
ld a, [wPrinterStatusFlags]
and $f3
ret nz
call _Printer_NextSection
ret
Printer_NextSectionWaitLoopBack:
call _Printer_NextSection
Printer_WaitLoopBack:
ld a, [wPrinterOpcode]
and a
ret nz
ld a, [wPrinterStatusFlags]
and $f0
ret nz
xor a
ld [wJumptableIndex], a
ret
Printer_WaitHandshake:
.loop
ld a, [wPrinterOpcode]
and a
jr nz, .loop
xor a
ld [wPrinterSendByteOffset], a
ld [wPrinterSendByteOffset + 1], a
ld a, $1
ld [wPrinterOpcode], a
ld a, $88
ldh [rSB], a
ld a, (0 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
ld a, (1 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
ret
Printer_CopyPacket:
ld a, [hli]
ld [wPrinterData], a
ld a, [hli]
ld [wPrinterData + 1], a
ld a, [hli]
ld [wPrinterData + 2], a
ld a, [hli]
ld [wPrinterData + 3], a
ld a, [hli]
ld [wPrinterChecksum], a
ld a, [hl]
ld [wPrinterChecksum + 1], a
ret
Printer_ResetData:
xor a
ld hl, wPrinterData
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
ld hl, wPrinterChecksum
ld [hli], a
ld [hl], a
xor a
ld [wPrinterSendByteCounter], a
ld [wPrinterSendByteCounter + 1], a
ld hl, wGameboyPrinterRAM
ld bc, wGameboyPrinter2bppSourceEnd - wGameboyPrinter2bppSource
call Printer_ByteFill
ret
Printer_ComputeChecksum:
ld hl, 0
ld bc, 4
ld de, wPrinterData
call .ComputeChecksum
ld a, [wPrinterSendByteCounter]
ld c, a
ld a, [wPrinterSendByteCounter + 1]
ld b, a
ld de, wGameboyPrinterRAM
call .ComputeChecksum
ld a, l
ld [wPrinterChecksum], a
ld a, h
ld [wPrinterChecksum + 1], a
ret
.ComputeChecksum:
.loop
ld a, [de]
inc de
add l
jr nc, .no_overflow
inc h
.no_overflow
ld l, a
dec bc
ld a, c
or b
jr nz, .loop
ret
Printer_StageHeaderForSend:
ld a, $1
ld [wGameboyPrinter2bppSource + 0], a
ld a, [wPrinterMargins]
ld [wGameboyPrinter2bppSource + 1], a
ld a, %11100100 ; 3,2,1,0
ld [wGameboyPrinter2bppSource + 2], a
ld a, [wPrinterExposureTime]
ld [wGameboyPrinter2bppSource + 3], a
ret
Printer_Convert2RowsTo2bpp:
; de = wPrinterTilemapBuffer + 2 * SCREEN_WIDTH * ([wPrinterQueueLength] - [wPrinterRowIndex])
ld a, [wPrinterRowIndex]
xor $ff
ld d, a
ld a, [wPrinterQueueLength]
inc a
add d
ld hl, wPrinterTilemapBuffer
ld de, 2 * SCREEN_WIDTH
.loop1
and a
jr z, .okay1
add hl, de
dec a
jr .loop1
.okay1
ld e, l
ld d, h
ld hl, wGameboyPrinter2bppSource
ld c, 2 * SCREEN_WIDTH
.loop2
ld a, [de]
inc de
push bc
push de
push hl
; convert tile index to vram address
swap a
ld d, a
and $f0
ld e, a
ld a, d
and $f
ld d, a
and $8
ld a, d
jr nz, .vtiles_8xxx
or $90
jr .got_vtile_addr
.vtiles_8xxx
or $80
.got_vtile_addr
ld d, a
; copy 1 vtile to hl
lb bc, BANK(Printer_Convert2RowsTo2bpp), 1
call Request2bpp
pop hl
ld de, 1 tiles
add hl, de
pop de
pop bc
dec c
jr nz, .loop2
ret
Printer_ByteFill:
push de
ld e, a
.loop
ld [hl], e
inc hl
dec bc
ld a, c
or b
jr nz, .loop
ld a, e
pop de
ret
PrinterDataPacket1:
db 1, 0, $00, 0
dw 1
PrinterDataPacket2:
db 2, 0, $04, 0
dw 0
PrinterDataPacket3:
db 4, 0, $80, 2
dw 0
PrinterDataPacket4:
db 4, 0, $00, 0
dw 4
PrinterDataPacket5: ; unused
db 8, 0, $00, 0
dw 8
PrinterDataPacket6: ; unused
db 15, 0, $00, 0
dw 15
_PrinterReceive::
ld a, [wPrinterOpcode]
add a
ld e, a
ld d, 0
ld hl, .Jumptable
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
jp hl
.Jumptable:
dw Printer_DoNothing ; 00
dw Printer_Send0x33 ; 01
dw Printer_SendPrinterData1 ; 02
dw Printer_SendPrinterData2 ; 03
dw Printer_SendPrinterData3 ; 04
dw Printer_SendPrinterData4 ; 05
dw Printer_SendNextByte ; 06
dw Printer_SendwPrinterChecksumLo ; 07
dw Printer_SendwPrinterChecksumHi ; 08
dw Printer_Send0x00_2 ; 09
dw Printer_ReceiveTwoPrinterHandshakeAndSend0x00 ; 0a
dw Printer_ReceiveTwoPrinterStatusFlagsAndExitSendLoop ; 0b
dw Printer_Send0x33 ; 0c triggered by AskSerial
dw Printer_Send0x0f ; 0d
dw Printer_Send0x00 ; 0e
dw Printer_Send0x00 ; 0f
dw Printer_Send0x00 ; 10
dw Printer_Send0x0f ; 11
dw Printer_Send0x00 ; 12
dw Printer_Send0x00_2 ; 13
dw Printer_ReceiveTwoPrinterHandshakeAndSend0x00 ; 14
dw Printer_ReceiveTwoPrinterStatusFlagsAndExitSendLoop_2 ; 15
dw Printer_Send0x33 ; 16 triggered by pressing B
dw Printer_Send0x08 ; 17
dw Printer_Send0x00 ; 18
dw Printer_Send0x00 ; 19
dw Printer_Send0x00 ; 1a
dw Printer_Send0x08 ; 1b
dw Printer_Send0x00 ; 1c
dw Printer_Send0x00_2 ; 1d
dw Printer_ReceiveTwoPrinterHandshakeAndSend0x00 ; 1e
dw Printer_ReceiveTwoPrinterStatusFlagsAndExitSendLoop ; 1f
Printer_NextInstruction:
ld hl, wPrinterOpcode
inc [hl]
ret
Printer_DoNothing:
ret
Printer_Send0x33:
ld a, $33
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_SendPrinterData1:
ld a, [wPrinterData]
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_SendPrinterData2:
ld a, [wPrinterData + 1]
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_SendPrinterData3:
ld a, [wPrinterData + 2]
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_SendPrinterData4:
ld a, [wPrinterData + 3]
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_SendNextByte:
; decrement 16-bit counter
ld hl, wPrinterSendByteCounter
ld a, [hli]
ld d, [hl]
ld e, a
or d
jr z, .done
dec de
ld [hl], d
dec hl
ld [hl], e
ld a, [wPrinterSendByteOffset]
ld e, a
ld a, [wPrinterSendByteOffset + 1]
ld d, a
ld hl, wGameboyPrinterRAM
add hl, de
inc de
ld a, e
ld [wPrinterSendByteOffset], a
ld a, d
ld [wPrinterSendByteOffset + 1], a
ld a, [hl]
call Printer_SerialSend
ret
.done
call Printer_NextInstruction
Printer_SendwPrinterChecksumLo:
ld a, [wPrinterChecksum]
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_SendwPrinterChecksumHi:
ld a, [wPrinterChecksum + 1]
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_Send0x00_2:
; identical to Printer_Send0x00, but referenced less
ld a, $0
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_ReceiveTwoPrinterHandshakeAndSend0x00:
ldh a, [rSB]
ld [wPrinterHandshake], a
ld a, $0
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_ReceiveTwoPrinterStatusFlagsAndExitSendLoop:
ldh a, [rSB]
ld [wPrinterStatusFlags], a
xor a
ld [wPrinterOpcode], a
ret
Printer_Send0x0f:
ld a, $f
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_Send0x00:
ld a, $0
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_Send0x08:
ld a, $8
call Printer_SerialSend
call Printer_NextInstruction
ret
Printer_SerialSend:
ldh [rSB], a
ld a, (0 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
ld a, (1 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
ret
Printer_ReceiveTwoPrinterStatusFlagsAndExitSendLoop_2:
; identical to Printer_ReceiveTwoPrinterStatusFlagsAndExitSendLoop, but referenced less
ldh a, [rSB]
ld [wPrinterStatusFlags], a
xor a
ld [wPrinterOpcode], a
ret