mirror of https://github.com/pret/pokecrystal.git
629 lines
12 KiB
NASM
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
|