summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlibjet <libj3t@gmail.com>2020-05-28 01:17:38 +0100
committerlibjet <libj3t@gmail.com>2020-05-28 01:17:38 +0100
commitc4ca2c453d883155e5c44303c02e3012ef5d50af (patch)
tree2a9a5ba73b4296330853c598e2dc1f1ddc600f38
parent34deb66c443af8ef7f36e24350d7f0069517ecd3 (diff)
Add engine/printer/printer_serial.asm
-rwxr-xr-xengine/printer/printer_serial.asm637
-rw-r--r--main.asm9
-rw-r--r--wram.asm6
3 files changed, 648 insertions, 4 deletions
diff --git a/engine/printer/printer_serial.asm b/engine/printer/printer_serial.asm
new file mode 100755
index 00000000..37b06a9f
--- /dev/null
+++ b/engine/printer/printer_serial.asm
@@ -0,0 +1,637 @@
+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:
+ ld a, [wJumptableIndex]
+ ld e, a
+ ld d, 0
+ ld hl, .Jumptable
+ add hl, de
+ add hl, de
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.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
diff --git a/main.asm b/main.asm
index 66eca040..3bd144c3 100644
--- a/main.asm
+++ b/main.asm
@@ -221,10 +221,11 @@ INCBIN "gfx/pokemon/egg/front.2bpp.lz"
SECTION "bank21", ROMX
-Printer_StartTransmission::
- dr $84000, $842db
-_PrinterReceive::
- dr $842db, $8442c
+
+INCLUDE "engine/printer/printer_serial.asm"
+
+SendScreenToPrinter::
+ dr $843f0, $8442c
PrintDexEntry::
dr $8442c, $84560
PrintUnownStamp::
diff --git a/wram.asm b/wram.asm
index 8d64f3c5..88ed2ddb 100644
--- a/wram.asm
+++ b/wram.asm
@@ -415,6 +415,12 @@ wOverworldMapBlocks:: ds 1300 ; c700
wOverworldMapBlocksEnd::
NEXTU ; c700
+; GB Printer screen RAM
+wGameboyPrinterRAM::
+wGameboyPrinterScreen:: ds SCREEN_HEIGHT * SCREEN_WIDTH ; c700
+wGameboyPrinterScreenEnd:: ; c868
+
+NEXTU ; c700
; GB Printer data
wGameboyPrinter2bppSource:: ds 40 tiles
wGameboyPrinter2bppSourceEnd::