pokeyellow/engine/printer/serial.asm

633 lines
10 KiB
NASM

const_def
const PRINTER_STATUS_BLANK
const PRINTER_STATUS_CHECKING_LINK
const PRINTER_STATUS_TRANSMITTING
const PRINTER_STATUS_PRINTING
const PRINTER_ERROR_1
const PRINTER_ERROR_2
const PRINTER_ERROR_3
const PRINTER_ERROR_4
const PRINTER_ERROR_WRONG_DEVICE
StartTransmission_Send9Rows:
ld a, 9
Printer_StartTransmission:
push af
ld hl, wPrinterData
ld bc, wPrinterDataEnd - wPrinterData
xor a
call Printer_FillMemory
xor a
ldh [rSB], a
ldh [rSC], a
ld [wPrinterOpcode], a
ld hl, wPrinterConnectionOpen
set 0, [hl]
ld a, [wPrinterSettings]
ld [wPrinterSettingsTempCopy], a
pop af
ld [wPrinterQueueLength], a
ret
PrinterTransmissionJumptable:
ld a, [wPrinterSendState]
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 Printer_InitSerial ; 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_Next_ ; 0e
dw Printer_WaitSerial ; 0f
dw Printer_SignalLoopBack ; 10
dw Printer_LoopBack ; 11
dw Printer_WaitLoopBack ; 12
dw Printer_WaitLoopBack_ ; 13
Printer_Next:
ld hl, wPrinterSendState
inc [hl]
ret
Printer_Back:
ld hl, wPrinterSendState
dec [hl]
ret
Printer_Quit:
xor a
ld [wPrinterStatusFlags], a
ld hl, wPrinterSendState
set 7, [hl]
ret
Printer_Next_:
call Printer_Next
ret
Printer_LoopBack:
ld a, $1
ld [wPrinterSendState], a
ret
Printer_InitSerial:
call ResetPrinterData
ld hl, PrinterDataPacket1
call CopyPrinterDataHeader
xor a
ld [wPrinterDataSize], a
ld [wPrinterDataSize + 1], a
ld a, [wPrinterQueueLength]
ld [wPrinterRowIndex], a
call Printer_Next
call Printer_PrepareToSend
ld a, PRINTER_STATUS_CHECKING_LINK
ld [wPrinterStatusIndicator], a
ret
Printer_StartTransmittingTilemap:
call ResetPrinterData
ld hl, wPrinterRowIndex
ld a, [hl]
and a
jr z, Printer_EndTilemapTransmission
ld hl, PrinterDataPacket3
call CopyPrinterDataHeader
call Printer_Convert2RowsTo2bpp
ld a, LOW(wPrinterSendDataSource1End - wPrinterSendDataSource1)
ld [wPrinterDataSize], a
ld a, HIGH(wPrinterSendDataSource1End - wPrinterSendDataSource1)
ld [wPrinterDataSize + 1], a
call ComputePrinterChecksum
call Printer_Next
call Printer_PrepareToSend
ld a, PRINTER_STATUS_TRANSMITTING
ld [wPrinterStatusIndicator], a
ret
Printer_EndTilemapTransmission:
ld a, $6
ld [wPrinterSendState], a
ld hl, PrinterDataPacket4
call CopyPrinterDataHeader
xor a
ld [wPrinterDataSize], a
ld [wPrinterDataSize + 1], a
call Printer_Next
call Printer_PrepareToSend
ret
Printer_SignalSendHeader:
call ResetPrinterData
ld hl, PrinterDataPacket2
call CopyPrinterDataHeader
call Printer_StageHeaderForSend
ld a, $4
ld [wPrinterDataSize], a
ld a, $0
ld [wPrinterDataSize + 1], a
call ComputePrinterChecksum
call Printer_Next
call Printer_PrepareToSend
ld a, PRINTER_STATUS_PRINTING
ld [wPrinterStatusIndicator], a
ret
Printer_SignalLoopBack:
call ResetPrinterData
ld hl, PrinterDataPacket1
call CopyPrinterDataHeader
xor a
ld [wPrinterDataSize], a
ld [wPrinterDataSize + 1], a
ld a, [wPrinterQueueLength]
ld [wPrinterRowIndex], a
call Printer_Next
call Printer_PrepareToSend
ret
Printer_WaitSerial:
ld hl, wPrinterSerialFrameDelay
inc [hl]
ld a, [hl]
cp $6
ret c
xor a
ld [hl], a
call Printer_Next
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_Back
call Printer_Back
ret
Printer_CheckConnectionStatus:
ld a, [wPrinterOpcode]
and a
ret nz
ld a, [wPrinterHandshake]
cp $ff
jr nz, .asm_e88dc
ld a, [wPrinterStatusFlags]
cp $ff
jr z, .asm_e88f8
.asm_e88dc
ld a, [wPrinterHandshake]
cp $81
jr nz, .asm_e88f8
ld a, [wPrinterStatusFlags]
cp $0
jr nz, .asm_e88f8
ld hl, wPrinterConnectionOpen
set 1, [hl]
ld a, $5
ld [wHandshakeFrameDelay], a
call Printer_Next
ret
.asm_e88f8
ld a, $ff
ld [wPrinterHandshake], a
ld [wPrinterStatusFlags], a
ld a, $e
ld [wPrinterSendState], a
ret
Printer_TransmissionLoop:
ld a, [wPrinterOpcode]
and a
ret nz
ld a, [wPrinterStatusFlags]
and $f0
jr nz, .asm_e8921
ld a, [wPrinterStatusFlags]
and $1
jr nz, .asm_e891d
call Printer_Next
ret
.asm_e891d
call Printer_Back
ret
.asm_e8921
ld a, $12
ld [wPrinterSendState], a
ret
Printer_WaitUntilFinished:
ld a, [wPrinterOpcode]
and a
ret nz
ld a, [wPrinterStatusFlags]
and $f3
ret nz
call Printer_Next
ret
Printer_WaitLoopBack:
call Printer_Next
Printer_WaitLoopBack_:
ld a, [wPrinterOpcode]
and a
ret nz
ld a, [wPrinterStatusFlags]
and $f0
ret nz
xor a
ld [wPrinterSendState], a
ret
Printer_PrepareToSend:
.wait_printer_operation
ld a, [wPrinterOpcode]
and a
jr nz, .wait_printer_operation
xor a
ld [wPrinterSendByteOffset], a
ld [wPrinterSendByteOffset + 1], a
ld a, $1
ld [wPrinterOpcode], a
ld a, $88
ldh [rSB], a
ld a, $1
ldh [rSC], a
ld a, $81
ldh [rSC], a
ret
CopyPrinterDataHeader:
ld a, [hli]
ld [wPrinterDataHeader], a
ld a, [hli]
ld [wPrinterDataHeader + 1], a
ld a, [hli]
ld [wPrinterDataHeader + 2], a
ld a, [hli]
ld [wPrinterDataHeader + 3], a
ld a, [hli]
ld [wPrinterChecksum], a
ld a, [hl]
ld [wPrinterChecksum + 1], a
ret
ResetPrinterData:
xor a
ld hl, wPrinterDataHeader
ld [hli], a
ld [hli], a
ld [hli], a
ld [hl], a
ld hl, wPrinterChecksum
ld [hli], a
ld [hl], a
xor a
ld [wPrinterDataSize], a
ld [wPrinterDataSize + 1], a
ld hl, wPrinterSendDataSource1
ld bc, wPrinterSendDataSource1End - wPrinterSendDataSource1
call Printer_FillMemory
ret
ComputePrinterChecksum:
ld hl, $0
ld bc, $4
ld de, wPrinterDataHeader
call .AddToChecksum
ld a, [wPrinterDataSize]
ld c, a
ld a, [wPrinterDataSize + 1]
ld b, a
ld de, wPrinterSendDataSource1
call .AddToChecksum
ld a, l
ld [wPrinterChecksum], a
ld a, h
ld [wPrinterChecksum + 1], a
ret
.AddToChecksum:
.loop
ld a, [de]
inc de
add l
jr nc, .no_carry
inc h
.no_carry
ld l, a
dec bc
ld a, c
or b
jr nz, .loop
ret
Printer_StageHeaderForSend:
ld a, $1
ld [wPrinterSendDataSource1], a
ld a, [wcae2]
ld [wPrinterSendDataSource1 + 1], a
ld a, %11100100
ld [wPrinterSendDataSource1 + 2], a
ld a, [wPrinterSettingsTempCopy]
ld [wPrinterSendDataSource1 + 3], a
ret
Printer_Convert2RowsTo2bpp:
ld a, [wPrinterRowIndex]
ld b, a
ld a, [wPrinterQueueLength]
sub b
ld hl, wPrinterTileBuffer
ld de, 2 * SCREEN_WIDTH
.get_row
and a
jr z, .got_row
add hl, de
dec a
jr .get_row
.got_row
ld e, l
ld d, h
ld hl, wPrinterSendDataSource1
ld c, 2 * SCREEN_WIDTH
.loop
ld a, [de]
inc de
push bc
push de
push hl
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, .vchars1
or $90
jr .got_addr
.vchars1
or $80
.got_addr
ld d, a
lb bc, BANK(Printer_Convert2RowsTo2bpp), 1
call CopyVideoData
pop hl
ld de, $10
add hl, de
pop de
pop bc
dec c
jr nz, .loop
ret
Printer_FillMemory:
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
PrinterSerial_::
ld a, [wPrinterOpcode]
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 .Nop
dw .SignalTransmissionStart
dw .SendHeaderByte1
dw .SendHeaderByte2
dw .SendHeaderByte3
dw .SendHeaderByte4
dw .DataByte
dw .SendChecksumLo
dw .SendChecksumHi
dw .SignalTransmissionEnd
dw .Receive1
dw .Receive2
dw .SignalTransmissionStart
dw .Send_0F
dw .Send_00
dw .Send_00
dw .Send_00
dw .Send_0F
dw .Send_00
dw .SignalTransmissionEnd
dw .Receive1
dw .Receive2_
dw .SignalTransmissionStart
dw .SignalQuit
dw .Send_00
dw .Send_00
dw .Send_00
dw .SignalQuit
dw .Send_00
dw .SignalTransmissionEnd
dw .Receive1
dw .Receive2
.NextInstruction:
ld hl, wPrinterOpcode
inc [hl]
ret
.Nop:
ret
.SignalTransmissionStart:
ld a, $33
call .SendByte
call .NextInstruction
ret
.SendHeaderByte1:
ld a, [wPrinterDataHeader]
call .SendByte
call .NextInstruction
ret
.SendHeaderByte2:
ld a, [wPrinterDataHeader + 1]
call .SendByte
call .NextInstruction
ret
.SendHeaderByte3:
ld a, [wPrinterDataHeader + 2]
call .SendByte
call .NextInstruction
ret
.SendHeaderByte4:
ld a, [wPrinterDataHeader + 3]
call .SendByte
call .NextInstruction
ret
.DataByte:
ld hl, wPrinterDataSize
ld e, [hl]
inc hl
ld d, [hl]
ld a, e
or d
jr z, .sent_last_byte
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, wPrinterSendDataSource1
add hl, de
inc de
ld a, e
ld [wPrinterSendByteOffset], a
ld a, d
ld [wPrinterSendByteOffset + 1], a
ld a, [hl]
call .SendByte
ret
.sent_last_byte
call .NextInstruction
.SendChecksumLo:
ld a, [wPrinterChecksum]
call .SendByte
call .NextInstruction
ret
.SendChecksumHi:
ld a, [wPrinterChecksum + 1]
call .SendByte
call .NextInstruction
ret
.SignalTransmissionEnd:
ld a, $0
call .SendByte
call .NextInstruction
ret
.Receive1:
ldh a, [rSB]
ld [wPrinterHandshake], a
ld a, $0
call .SendByte
call .NextInstruction
ret
.Receive2:
ldh a, [rSB]
ld [wPrinterStatusFlags], a
xor a
ld [wPrinterOpcode], a
ret
.Send_0F:
ld a, $f
call .SendByte
call .NextInstruction
ret
.Send_00:
ld a, $0
call .SendByte
call .NextInstruction
ret
.SignalQuit:
ld a, $8
call .SendByte
call .NextInstruction
ret
.SendByte:
ldh [rSB], a
ld a, $1
ldh [rSC], a
ld a, $81
ldh [rSC], a
ret
.Receive2_:
ldh a, [rSB]
ld [wPrinterStatusFlags], a
xor a
ld [wPrinterOpcode], a
ret