diff options
| author | Jonas Höglund <firefly@firefly.nu> | 2014-07-26 11:48:04 +0200 | 
|---|---|---|
| committer | Jonas Höglund <firefly@firefly.nu> | 2014-07-26 11:48:04 +0200 | 
| commit | 125bc94a0542a6948aef485aa10fd73ff3f95fe6 (patch) | |
| tree | 25a408b8ee7e850322386235cb2024aa36d0b9c7 | |
| parent | 38de443000ff2fb82b53650be7b23f05e017167f (diff) | |
Home: do serial data transfer functions
| -rwxr-xr-x | engine/home.asm | 180 | ||||
| -rwxr-xr-x | wram.asm | 58 | 
2 files changed, 155 insertions, 83 deletions
| diff --git a/engine/home.asm b/engine/home.asm index 4473cd4..4ac478b 100755 --- a/engine/home.asm +++ b/engine/home.asm @@ -1596,37 +1596,40 @@ MemcpyDEHL_hblank: ; 0c32 (0:0c32)  INCBIN "baserom.gbc",$0c4b,$0c91 - $0c4b +; called at roughly 240Hz by TimerHandler  SerialTimerHandler: ; 0c91 (0:0c91) -	ld a, [$cb74] +	ld a, [wSerialOp]  	cp $29 -	jr z, .asm_c9d +	jr z, .begin_transfer  	cp $12 -	jr z, .asm_caa +	jr z, .check_for_timeout  	ret -.asm_c9d -	ld a, [rSC] -	add a -	ret c +.begin_transfer +	ld a, [rSC]          ; +	add a                ; make sure that no serial transfer is active +	ret c                ;  	ld a, $1 -	ld [rSC], a +	ld [rSC], a          ; use internal clock  	ld a, $81 -	ld [rSC], a +	ld [rSC], a          ; use internal clock, set transfer start flag  	ret -.asm_caa -	ld a, [$cb76] -	ld hl, $cb77 +.check_for_timeout +	; sets bit7 of [wSerialFlags] if the serial interrupt hasn't triggered +	; within four timer interrupts (60Hz) +	ld a, [wSerialCounter] +	ld hl, wSerialCounter2  	cp [hl]  	ld [hl], a -	ld hl, $cb78 -	jr nz, .asm_cc2 +	ld hl, wSerialTimeoutCounter +	jr nz, .clear_counter  	inc [hl]  	ld a, [hl]  	cp $4  	ret c -	ld hl, $cb75 +	ld hl, wSerialFlags  	set 7, [hl]  	ret -.asm_cc2 +.clear_counter  	ld [hl], $0  	ret  ; 0xcc5 @@ -1638,44 +1641,46 @@ SerialHandler: ; 0d26 (0:0d26)  	push hl  	push de  	push bc -	ld a, [$ce63] -	or a -	jr z, .asm_d35 -	call Func_3189 -	jr .asm_d6e +	ld a, [$ce63]        ; +	or a                 ; +	jr z, .asm_d35       ; if [$ce63] nonzero: +	call Func_3189       ;   ? +	jr .done             ;   return  .asm_d35 -	ld a, [$cb74] -	or a -	jr z, .asm_d55 +	ld a, [wSerialOp]        ; +	or a                 ; +	jr z, .asm_d55       ; skip ahead if [$cb74] zero +	; send/receive a byte  	ld a, [rSB] -	call Func_0d77 -	call Func_0dc8 +	call SerialHandleRecv +	call SerialHandleSend ; returns byte to actually send  	push af -.asm_d44 +.wait_for_completion  	ld a, [rSC]  	add a -	jr c, .asm_d44 +	jr c, .wait_for_completion  	pop af -	ld [rSB], a -	ld a, [$cb74] +	; end send/receive +	ld [rSB], a          ; prepare sending byte (from Func_0dc8?) +	ld a, [wSerialOp]  	cp $29 -	jr z, .asm_d6e -	jr .asm_d6a +	jr z, .done          ; if [$cb74] != $29, use external clock +	jr .asm_d6a          ; and prepare for next byte.  either way, return  .asm_d55  	ld a, $1 -	ld [$cba2], a +	ld [wSerialRecvCounter], a  	ld a, [rSB] -	ld [$cba5], a +	ld [wSerialRecvBuf], a  	ld a, $ac  	ld [rSB], a -	ld a, [$cba5] -	cp $12 -	jr z, .asm_d6e +	ld a, [wSerialRecvBuf] +	cp $12               ; if [$cba5] != $12, use external clock +	jr z, .done          ; and prepare for next byte.  either way, return  .asm_d6a -	ld a, $80 -	ld [rSC], a -.asm_d6e -	ld hl, $cb76 +	ld a, $80            ; +	ld [rSC], a          ; transfer start, use external clock +.done +	ld hl, wSerialCounter  	inc [hl]  	pop bc  	pop de @@ -1683,101 +1688,116 @@ SerialHandler: ; 0d26 (0:0d26)  	pop af  	reti -Func_0d77: ; 0d77 (0:0d77) -	ld hl, $cba1 +; handles a byte read from serial transfer by decoding it and storing it into +; the receive buffer +SerialHandleRecv: ; 0d77 (0:0d77) +	ld hl, wSerialLastReadCA  	ld e, [hl]  	dec e -	jr z, .asm_d94 +	jr z, .last_was_ca  	cp $ac -	ret z +	ret z                ; return if read_data == $ac  	cp $ca -	jr z, .asm_d92 +	jr z, .read_ca  	or a -	jr z, .asm_d8c +	jr z, .read_00_or_ff  	cp $ff -	jr nz, .asm_d99 -.asm_d8c -	ld hl, $cb75 +	jr nz, .read_data +.read_00_or_ff +	ld hl, wSerialFlags  	set 6, [hl]  	ret -.asm_d92 -	inc [hl] +.read_ca +	inc [hl]             ; inc [wSerialLastReadCA]  	ret -.asm_d94 +.last_was_ca +	; if last byte read was $ca, flip all bits of data received  	ld [hl], $0  	cpl -	jr .asm_d9b -.asm_d99 +	jr .handle_byte +.read_data +	; flip top2 bits of data received  	xor $c0 -.asm_d9b +.handle_byte  	push af -	ld a, [$cba4] +	ld a, [wSerialRecvIndex]  	ld e, a  	ld a, [$cba3]  	dec a  	and $1f  	cp e -	jr z, .asm_dc1 +	jr z, .set_flag_and_return  	ld d, $0 -	ld hl, $cba5 +	; store into receive buffer +	ld hl, wSerialRecvBuf  	add hl, de  	pop af  	ld [hl], a +	; increment buffer index (mod 32)  	ld a, e  	inc a  	and $1f  	ld [$cba4], a -	ld hl, $cba2 +	; increment received bytes counter & clear flags +	ld hl, wSerialRecvCounter  	inc [hl]  	xor a -	ld [$cb75], a +	ld [wSerialFlags], a  	ret -.asm_dc1 +.set_flag_and_return  	pop af -	ld hl, $cb75 +	ld hl, wSerialFlags  	set 0, [hl]  	ret -Func_0dc8: ; 0dc8 (0:0dc8) -	ld hl, $cb7d +; prepares a byte to send over serial transfer, either from the send-save byte +; slot or the send buffer +SerialHandleSend: ; 0dc8 (0:0dc8) +	ld hl, wSerialSendSave  	ld a, [hl]  	or a -	jr nz, .asm_dd9 -	ld hl, $cb7e +	jr nz, .send_saved +	ld hl, wSerialSendBufToggle  	ld a, [hl]  	or a -	jr nz, .asm_ddd +	jr nz, .send_buf +	; no more data--send $ac to indicate this  	ld a, $ac  	ret -.asm_dd9 +.send_saved  	ld a, [hl]  	ld [hl], $0  	ret -.asm_ddd +.send_buf +	; grab byte to send from send buffer, increment buffer index +	; and decrement to-send length  	dec [hl] -	ld a, [$cb7f] +	ld a, [wSerialSendBufIndex]  	ld e, a  	ld d, $0 -	ld hl, $cb81 +	ld hl, wSerialSendBuf  	add hl, de  	inc a  	and $1f -	ld [$cb7f], a +	ld [wSerialSendBufIndex], a  	ld a, [hl] +	; flip top2 bits of sent data  	xor $c0  	cp $ac -	jr z, .asm_e01 +	jr z, .send_escaped  	cp $ca -	jr z, .asm_e01 +	jr z, .send_escaped  	cp $ff -	jr z, .asm_e01 +	jr z, .send_escaped  	or a -	jr z, .asm_e01 +	jr z, .send_escaped  	ret -.asm_e01 +.send_escaped +	; escape tricky data by prefixing it with $ca and flipping all bits +	; instead of just top2  	xor $c0  	cpl -	ld [$cb7d], a +	ld [wSerialSendSave], a  	ld a, $ca  	ret  ; 0xe0a @@ -1791,7 +1811,7 @@ ResetSerial: ; 0ea6 (0:0ea6)  	xor a  	ld [rSB], a  	ld [rSC], a -	ld hl, wBufSerial +	ld hl, wSerialOp  	ld bc, $0051  .asm_eb7  	xor a @@ -1,10 +1,17 @@  ;--- Bank 0: $Cxxx ----------------------------------------  SECTION "WRAM0", WRAM0 -	ds $ab3 +	ds $a00 +wBufOAM: ; ca00 +	ds $a0 +	ds $13 + +; initial value of the A register--used to tell the console when reset  wInitialA: ; cab3  	ds $1 +; what console we are playing on, either 0 (DMG), 1 (SGB) or 2 (CGB) +; use constants CONSOLE_DMG, CONSOLE_SGB and CONSOLE_CGB for checks  wConsole: ; cab4  	ds $1  	ds $1 @@ -49,6 +56,11 @@ wCounterCtr: ; cac3  wCounterEnable: ; cac4  	ds $1 +; byte0: 1/60ths of a second +; byte1: seconds +; byte2: minutes +; byte3: hours (lower byte) +; byte4: hours (upper byte)  wCounter: ; cac5  	ds $5  	ds $6 @@ -56,13 +68,53 @@ wCounter: ; cac5  wVBlankFunctionTrampoline: ; cad0  	ds $20 ; unknown length -wBufPalette: ; caf0 +wBufPalette: ; caf0 - cab7f  	ds $80  	ds $4 -wBufSerial: ; cb74 +;--- Serial transfer bytes (cb74-cbc4) ---------- +wSerialOp: ; cb74 +	ds $1 + +wSerialFlags: ; cb75 +	ds $1 + +wSerialCounter: ; cb76 +	ds $1 + +wSerialCounter2: ; cb77 +	ds $1 + +wSerialTimeoutCounter: ; cb78 +	ds $1 +	ds $4 + +wSerialSendSave: ; cb7d +	ds $1 + +wSerialSendBufToggle: ; cb7e +	ds $1 + +wSerialSendBufIndex: ; cb7f +	ds $1 +	ds $1 + +wSerialSendBuf: ; cb81 +	ds $20 + +wSerialLastReadCA: ; cba1  	ds $1 +wSerialRecvCounter: ; cba2 +	ds $1 +	ds $1 + +wSerialRecvIndex: ; cba4 +	ds $1 + +wSerialRecvBuf: ; $cba5 - $cbc4 +	ds $20 +  ;--- Bank 1: $Dxxx ----------------------------------------  SECTION "WRAM1", WRAMX, BANK[1] | 
