Introduce a 7-byte video header and use it to select between HGR and

DHGR playback modes.  Actually the only difference is whether to
initialize (D)HGR display since everything else is steered by the video
stream.  6 of these bytes are currently unused, but it is convenient
to pad to the same length as the TICK opcode so that it does not
complicate the ACK stream framing.

Move towards the convention of using upper-case labels for system use
(soft switches etc) and lower-case for program use.
This commit is contained in:
kris 2019-04-25 16:25:36 +01:00
parent aaf56e6ec5
commit 6bde085d5e

View File

@ -51,16 +51,36 @@ WDATA = $C097
;;; ;;;
headerlen = $07 ; video header length
; some dummy addresses in order to pad cycle counts ; some dummy addresses in order to pad cycle counts
zpdummy = $08 zpdummy = $08
dummy = $ffff dummy = $ffff
hgr = $f3e2 ptr = $06 ; TODO: we only use this for connection retry count
fullscr = $c052
tick = $c030 ; where the magic happens
prodos = $BF00 ; ProDOS MLI entry point ; soft-switches
reset_vector = $3F2 ; Reset vector KBD = $C000
STORE80ON = $C001
COL80ON = $C00D
KBDSTRB = $C010
TICK = $C030 ; where the magic happens
TEXTOFF = $C050
FULLSCR = $C052
PAGE2OFF = $C054
PAGE2ON = $C055
HIRESON = $C057
DHIRESON = $C05E
; MONITOR SUBROUTINES
HGR = $F3E2
HGR0 = $F3EA ; internal entry point within HGR that doesn't set soft-switches
COUT = $FDED
PRBYTE = $FDDA
PRNTAX = $F941
PRODOS = $BF00 ; ProDOS MLI entry point
RESET_VECTOR = $3F2 ; Reset vector
; W5100 LOCATIONS ; W5100 LOCATIONS
MACADDR = $0009 ; MAC ADDRESS MACADDR = $0009 ; MAC ADDRESS
@ -96,16 +116,6 @@ SCRECV = $40 ; RECV
STINIT = $13 STINIT = $13
STESTABLISHED = $17 STESTABLISHED = $17
; MONITOR SUBROUTINES
KBD = $C000
KBDSTRB = $C010
COUT = $FDED
PRBYTE = $FDDA
PRNTAX = $F941
; ZERO-PAGE STORAGE
PTR = $06 ; TODO: we only use this for connection retry count
; this is the main binary entrypoint (it will be linked at 0x800) ; this is the main binary entrypoint (it will be linked at 0x800)
.segment "LOWCODE" .segment "LOWCODE"
JMP bootstrap JMP bootstrap
@ -118,16 +128,16 @@ PTR = $06 ; TODO: we only use this for connection retry count
bootstrap: bootstrap:
; install reset handler ; install reset handler
LDA #<exit LDA #<exit
STA reset_vector STA RESET_VECTOR
LDA #>exit LDA #>exit
STA reset_vector+1 STA RESET_VECTOR+1
EOR #$A5 EOR #$A5
STA reset_vector+2 ; checksum to ensure warm-start reset STA RESET_VECTOR+2 ; checksum to ensure warm-start reset
LDA #6 ; 5 RETRIES TO GET CONNECTION LDA #6 ; 5 RETRIES TO GET CONNECTION
STA PTR ; NUMBER OF RETRIES STA ptr ; NUMBER OF RETRIES
RESET_W5100: reset_w5100:
LDA #$80 ; reset LDA #$80 ; reset
STA WMODE STA WMODE
LDA #3 ; CONFIGURE WITH AUTO-INCREMENT LDA #3 ; CONFIGURE WITH AUTO-INCREMENT
@ -239,15 +249,15 @@ CHECKTEST:
LDA WDATA ; GET SOCKET STATUS LDA WDATA ; GET SOCKET STATUS
BEQ FAILED ; 0 = SOCKET CLOSED, ERROR BEQ FAILED ; 0 = SOCKET CLOSED, ERROR
CMP #STESTABLISHED CMP #STESTABLISHED
BEQ SETUP ; SUCCESS BEQ wait_read_header ; SUCCESS
BNE CHECKTEST BNE CHECKTEST
FAILED: FAILED:
DEC PTR DEC ptr
BEQ ERRDONE ; TOO MANY FAILURES BEQ ERRDONE ; TOO MANY FAILURES
LDA #$AE ; "." LDA #$AE ; "."
JSR COUT JSR COUT
JMP RESET_W5100 ; TRY AGAIN JMP reset_w5100 ; TRY AGAIN
ERRDONE: ERRDONE:
LDY #0 LDY #0
@ -263,50 +273,76 @@ ERRMSG: .byte $d3,$cf,$c3,$cb,$c5,$d4,$a0,$c3,$cf,$d5,$cc,$c4,$a0,$ce,$cf,$d4,$a
; "SOCKET COULD NOT CONNECT - CHECK REMOTE HOST" ; "SOCKET COULD NOT CONNECT - CHECK REMOTE HOST"
.byte $8D,$00 .byte $8D,$00
SETUP: wait_read_header:
LDA #<S0RXRSR ; Socket 0 Received Size register
STA WADRL ;
LDA WDATA ; High byte of received size
CMP #$01 ; expect at least 256 bytes
BCS op_header ; There is enough data...we don't care exactly how much
; TODO: Read header from video ; TODO: Not sure whether this delay is needed?
NOP ; Little delay ...
NOP
JMP wait_read_header ; Check again
JMP init_mainloop op_header:
; Point to socket 0 buffer
LDA #>RXBASE
STA WADRH
LDA #<RXBASE
STA WADRL
; read video header
; consume 6 padding bytes from HEADER opcode.
; TODO: implement version header so we won't try to play a video for an incompatible
; player version.
LDA WDATA
LDA WDATA
LDA WDATA
LDA WDATA
LDA WDATA
LDA WDATA
JMP _op_header_hgr
.segment "CODE" .segment "CODE"
; Quit to ProDOS ; Initialize (D)HGR in the CODE segment so we don't accidentally toast ourselves when
exit: ; erasing HGR
INC reset_vector+2 ; Invalidate power-up byte _op_header_hgr:
JSR prodos ; Call the MLI ($BF00) LDA WDATA ; Video mode
.BYTE $65 ; CALL TYPE = QUIT BEQ @1 ; 0 = HGR mode
.ADDR exit_parmtable ; Pointer to parameter table
exit_parmtable: ; TODO: clear screen before displaying it to look cleaner
.BYTE 4 ; Number of parameters is 4
.BYTE 0 ; 0 is the only quit type ; DHGR mode
.WORD 0000 ; Pointer reserved for future use
.BYTE 0 ; Byte reserved for future use
.WORD 0000 ; Pointer reserved for future use
init_mainloop: STA TEXTOFF ; XXX move later
JSR hgr ; nukes the startup code we placed in HGR segment STA HIRESON
STA DHIRESON
STA $C050 ; GRAPHICS STA COL80ON
STA $C057 ; HIRES STA STORE80ON
STA $C05E ; DHR
STA $C00D ; 80 COLUMN MODE
STA $C001 ; 80STOREON
; Clear aux screen ; Clear aux screen
STA $C055 ; STA PAGE2ON ; AUX memory active
; Co-opt HGR internals to clear AUX for us.
LDA #$20 LDA #$20
JSR $F3EA JSR HGR0
STA fullscr STA PAGE2OFF ; MAIN memory active
STA $C054 ; MAIN memory active @1:
JSR HGR ; nukes the startup code we placed in HGR segment
STA FULLSCR
; establish invariants expected by decode loop ; establish invariants expected by decode loop
LDY #>RXBASE ; High byte of socket 0 receive buffer LDY #>RXBASE ; High byte of socket 0 receive buffer
LDX #$00 LDX #headerlen ; End of header
LDA #>S0RXRSR
STA WADRH
; fall through
; This is the main audio/video decode loop. ; This is the main audio/video decode loop.
; ;
@ -338,7 +374,7 @@ init_mainloop:
; 14364 Hz "carrier" for the audio DAC, which is slightly audible (at least to my ageing ; 14364 Hz "carrier" for the audio DAC, which is slightly audible (at least to my ageing
; ears) but quite acceptable. ; ears) but quite acceptable.
; ;
; i.e. we get about 14364 player opcodes/second, with the op_ack + CHECKRECV + op_nop ; i.e. we get about 14364 player opcodes/second, with the op_ack + checkrecv + op_nop
; "slow path" costing 2 opcodes. Each of the "fat" audio/video opcodes results in storing ; "slow path" costing 2 opcodes. Each of the "fat" audio/video opcodes results in storing
; 4 video bytes, so we store about 56KB of video data per second. ; 4 video bytes, so we store about 56KB of video data per second.
; ;
@ -354,30 +390,30 @@ init_mainloop:
; X = 0 ; X = 0
; Y register has the high byte of the W5100 address pointer in the RX socket code, so we ; Y register has the high byte of the W5100 address pointer in the RX socket code, so we
; can't trash this until we are ready to point back there. ; can't trash this until we are ready to point back there.
CHECKRECV: checkrecv:
BIT tick ; 4 BIT TICK ; 4
LDA #<S0RXRSR ; 2 Socket 0 Received Size register LDA #<S0RXRSR ; 2 Socket 0 Received Size register
STA WADRL ; 4 STA WADRL ; 4
LDA WDATA ; 4 High byte of received size LDA WDATA ; 4 High byte of received size
CMP #$08 ; 2 expect at least 2k CMP #$08 ; 2 expect at least 2k
; TODO: check this doesn't cross a page bdy or it will add a cycle ; TODO: check this doesn't cross a page bdy or it will add a cycle
BCS RECV ; 3 There is data...we don't care exactly how much because it's at least 2K BCS recv ; 3 There is data...we don't care exactly how much because it's at least 2K
; TODO: Not sure whether this delay is needed? ; TODO: Not sure whether this delay is needed?
NOP ; Little delay ... NOP ; Little delay ...
NOP NOP
JMP CHECKRECV ; Check again JMP checkrecv ; Check again
; There is data to read - restore W5100 address pointer where we last found it ; There is data to read - restore W5100 address pointer where we last found it
; ;
; It turns out that the W5100 automatically wraps the address pointer at the end of the 8K RX/TX buffers ; It turns out that the W5100 automatically wraps the address pointer at the end of the 8K RX/TX buffers
; Since we're using an 8K socket, that means we don't have to do any work to manage the read pointer! ; Since we're using an 8K socket, that means we don't have to do any work to manage the read pointer!
RECV: ; 15 cycles so far recv: ; 15 cycles so far
; point W5100 back into the RX buffer where we left off in op_ack ; point W5100 back into the RX buffer where we left off in op_ack
STY WADRH ; 4 STY WADRH ; 4
STX WADRL ; 4 X=0 here from op_ack STX WADRL ; 4 normally X=0 here from op_ack except during first frame when we have just read the header.
; Check for keypress and pause the video ; Check for keypress and pause the video
@0: BIT KBD ; 4 @0: BIT KBD ; 4
@ -393,10 +429,12 @@ RECV: ; 15 cycles so far
; fall through - tick timings don't matter ; fall through - tick timings don't matter
; pad cycles to keep ticking on 36/37 cycle cadence ; pad cycles to keep ticking on 36/37 cycle cadence
; TODO: what can we do with the luxury of 16 unused cycles?! ; TODO: what can we do with the luxury of 14 unused cycles?!
@2: ; 30 so far @2: ; 30 so far
NOP ; 2 ; X will usually already be 0 from op_ack except during first frame when reading
BIT tick ; 4 ; 36 ; header but reset it unconditionally
LDX #$00 ; 2
BIT TICK ; 4 ; 36
NOP ; 2 NOP ; 2
STA dummy ; 4 STA dummy ; 4
@ -420,7 +458,7 @@ op_nop:
; - read 2 bytes from the stream as address of next opcode ; - read 2 bytes from the stream as address of next opcode
; ;
; Each opcode has 6 cycles of padding, which is necessary to support reordering things to ; Each opcode has 6 cycles of padding, which is necessary to support reordering things to
; get the second "BIT tick" at the right cycle offset. ; get the second "BIT TICK" at the right cycle offset.
; ;
; Where possible we share code by JMPing to a common tail instruction sequence in one of the ; Where possible we share code by JMPing to a common tail instruction sequence in one of the
; earlier opcodes. This is critical for reducing code size enough to fit. ; earlier opcodes. This is critical for reducing code size enough to fit.
@ -436,8 +474,8 @@ op_nop:
.macro op_tick_4 page .macro op_tick_4 page
;4+(4)+2+4+4+4+5+4+5+4+5+4+5+4+4+4+4+3=73 ;4+(4)+2+4+4+4+5+4+5+4+5+4+5+4+4+4+4+3=73
.ident (.concat ("op_tick_4_page_", .string(page))): .ident (.concat ("op_tick_4_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
BIT tick ; 4 BIT TICK ; 4
STA zpdummy ; 3 STA zpdummy ; 3
STA zpdummy ; 3 STA zpdummy ; 3
@ -480,9 +518,9 @@ tickident page, 7
.macro op_tick_6 page .macro op_tick_6 page
;4+(2+4)+3+4+4+5+4+5+4+5+4+5+4+4+4+5+3 ;4+(2+4)+3+4+4+5+4+5+4+5+4+5+4+4+4+5+3
.ident (.concat ("op_tick_6_page_", .string(page))): .ident (.concat ("op_tick_6_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
STA zpdummy ; 3 STA zpdummy ; 3
@ -525,9 +563,9 @@ tickident page, 8
.macro op_tick_8 page .macro op_tick_8 page
;4+(4+4)+3+3+55 ;4+(4+4)+3+3+55
.ident (.concat ("op_tick_8_page_", .string(page))): .ident (.concat ("op_tick_8_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
BIT tick ; 4 BIT TICK ; 4
STA zpdummy ; 3 STA zpdummy ; 3
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_55")) ; 3 + 55 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_55")) ; 3 + 55
@ -536,10 +574,10 @@ tickident page, 8
.macro op_tick_10 page .macro op_tick_10 page
;4+(4+2+4)+3+56 ;4+(4+2+4)+3+56
.ident (.concat ("op_tick_10_page_", .string(page))): .ident (.concat ("op_tick_10_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_56")) ; 3 + 56 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_56")) ; 3 + 56
.endmacro .endmacro
@ -547,10 +585,10 @@ tickident page, 8
.macro op_tick_12 page .macro op_tick_12 page
;4+(4+4+4)+3+3+51 ;4+(4+4+4)+3+3+51
.ident (.concat ("op_tick_12_page_", .string(page))): .ident (.concat ("op_tick_12_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
BIT tick ; 4 BIT TICK ; 4
STA zpdummy ; 3 STA zpdummy ; 3
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_51")) ; 3 + 51 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_51")) ; 3 + 51
@ -559,11 +597,11 @@ tickident page, 8
.macro op_tick_14 page .macro op_tick_14 page
;4+(4+4+2+4)+3+52 ;4+(4+4+2+4)+3+52
.ident (.concat ("op_tick_14_page_", .string(page))): .ident (.concat ("op_tick_14_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_52")) ; 3+52 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_52")) ; 3+52
.endmacro .endmacro
@ -571,14 +609,14 @@ tickident page, 8
.macro op_tick_16 page .macro op_tick_16 page
; 4+(4+4+4+4)+5+2+3+43 ; 4+(4+4+4+4)+5+2+3+43
.ident (.concat ("op_tick_16_page_", .string(page))): .ident (.concat ("op_tick_16_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
; This temporarily violates X=0 invariant required by tick_6, but lets us share a ; This temporarily violates X=0 invariant required by tick_6, but lets us share a
; common opcode tail; otherwise we need a dummy 4-cycle opcode between the ticks, which ; common opcode tail; otherwise we need a dummy 4-cycle opcode between the ticks, which
; doesn't leave enough to JMP with. ; doesn't leave enough to JMP with.
LDX WDATA ; 4 LDX WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
BIT tick ; 4 BIT TICK ; 4
STA page << 8,x ; 5 STA page << 8,x ; 5
LDX #$00 ; 2 restore X=0 invariant LDX #$00 ; 2 restore X=0 invariant
@ -589,14 +627,14 @@ tickident page, 8
.macro op_tick_18 page .macro op_tick_18 page
; 4 + (4+4+4+2+4)+5+5+2+2+4+5+4+5+4+4+4+4+3 ; 4 + (4+4+4+2+4)+5+5+2+2+4+5+4+5+4+4+4+4+3
.ident (.concat ("op_tick_18_page_", .string(page))): .ident (.concat ("op_tick_18_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
; lets us reorder the 5-cycle STA page << 8,y outside of tick loop. ; lets us reorder the 5-cycle STA page << 8,y outside of tick loop.
; This temporarily violates X=0 invariant required by tick_6 ; This temporarily violates X=0 invariant required by tick_6
LDX WDATA ; 4 LDX WDATA ; 4
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
STA page << 8,X ; 5 STA page << 8,X ; 5
@ -623,12 +661,12 @@ tickident page, 8
.macro op_tick_20 page .macro op_tick_20 page
;4+(4+4+5+3+4)+3+46=73 ;4+(4+4+5+3+4)+3+46=73
.ident (.concat ("op_tick_20_page_", .string(page))): .ident (.concat ("op_tick_20_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
STA zpdummy ; 3 STA zpdummy ; 3
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_46")) JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_46"))
.endmacro .endmacro
@ -637,12 +675,12 @@ tickident page, 8
.macro op_tick_22 page .macro op_tick_22 page
; 4+(4+4+5+4+4)+3+3+42 ; 4+(4+4+5+4+4)+3+3+42
.ident (.concat ("op_tick_22_page_", .string(page))): .ident (.concat ("op_tick_22_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
BIT tick ; 4 BIT TICK ; 4
STA zpdummy ; 3 STA zpdummy ; 3
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_42")) ; 3 + 42 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_42")) ; 3 + 42
@ -651,13 +689,13 @@ tickident page, 8
.macro op_tick_24 page .macro op_tick_24 page
;4+(4+4+5+4+3+4)+3+42 ;4+(4+4+5+4+3+4)+3+42
.ident (.concat ("op_tick_24_page_", .string(page))): .ident (.concat ("op_tick_24_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
STA zpdummy ; 3 STA zpdummy ; 3
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_42")) JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_42"))
.endmacro .endmacro
@ -665,13 +703,13 @@ tickident page, 8
.macro op_tick_26 page ; pattern repeats from op_tick_8 .macro op_tick_26 page ; pattern repeats from op_tick_8
; 4+(4+4+5+4+5+4)+3+37 ; 4+(4+4+5+4+5+4)+3+37
.ident (.concat ("op_tick_26_page_", .string(page))): .ident (.concat ("op_tick_26_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
BIT tick; 4 BIT TICK; 4
STA zpdummy ; 3 STA zpdummy ; 3
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_37")) ; 3 + 37 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_37")) ; 3 + 37
@ -680,14 +718,14 @@ tickident page, 8
.macro op_tick_28 page ; pattern repeats from op_tick_10 .macro op_tick_28 page ; pattern repeats from op_tick_10
; 4+(4+2+4+5+4+5+4)+3+38 ; 4+(4+2+4+5+4+5+4)+3+38
.ident (.concat ("op_tick_28_page_", .string(page))): .ident (.concat ("op_tick_28_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_38")) JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_38"))
.endmacro .endmacro
@ -695,14 +733,14 @@ tickident page, 8
.macro op_tick_30 page ; pattern repeats from op_tick_12 .macro op_tick_30 page ; pattern repeats from op_tick_12
;4+(4+4+5+4+5+4+4)+3+3+33 ;4+(4+4+5+4+5+4+4)+3+3+33
.ident (.concat ("op_tick_30_page_", .string(page))): .ident (.concat ("op_tick_30_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
BIT tick ; 4 BIT TICK ; 4
STA zpdummy ; 3 STA zpdummy ; 3
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_33")) ; 3 + 33 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_33")) ; 3 + 33
@ -711,7 +749,7 @@ tickident page, 8
.macro op_tick_32 page ; pattern repeats from op_tick_14 .macro op_tick_32 page ; pattern repeats from op_tick_14
;4+(4+4+5+4+5+4+2+4)+3+34 ;4+(4+4+5+4+5+4+2+4)+3+34
.ident (.concat ("op_tick_32_page_", .string(page))): .ident (.concat ("op_tick_32_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -719,7 +757,7 @@ tickident page, 8
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_34")) JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_34"))
.endmacro .endmacro
@ -727,7 +765,7 @@ tickident page, 8
.macro op_tick_34 page ; pattern repeats from op_tick_16 .macro op_tick_34 page ; pattern repeats from op_tick_16
; 4+(4+4+5+4+5+4+4+4)+2+5+5+3+20 ; 4+(4+4+5+4+5+4+4+4)+2+5+5+3+20
.ident (.concat ("op_tick_34_page_", .string(page))): .ident (.concat ("op_tick_34_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -735,7 +773,7 @@ tickident page, 8
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
LDX WDATA ; 4 ; allows reordering STA ...,X outside ticks LDX WDATA ; 4 ; allows reordering STA ...,X outside ticks
BIT tick ; 4 BIT TICK ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
STA page << 8,X ; 5 STA page << 8,X ; 5
@ -748,7 +786,7 @@ tickident page, 8
.macro op_tick_36 page ; pattern repeats from op_tick_18 .macro op_tick_36 page ; pattern repeats from op_tick_18
;4+(4+4+5+4+5+4+4+2+4)+5+5+2+2+4+4+4+4+3 ;4+(4+4+5+4+5+4+4+2+4)+5+5+2+2+4+4+4+4+3
.ident (.concat ("op_tick_36_page_", .string(page))): .ident (.concat ("op_tick_36_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -757,7 +795,7 @@ tickident page, 8
LDY WDATA ; 4 LDY WDATA ; 4
LDX WDATA ; 4 LDX WDATA ; 4
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
STA page << 8,X ; 5 STA page << 8,X ; 5
@ -776,7 +814,7 @@ tickident page, 8
.macro op_tick_38 page ; pattern repeats from op_tick_20 .macro op_tick_38 page ; pattern repeats from op_tick_20
; 4 + (4+4+5+4+5+4+5+3+4)+3+28 ; 4 + (4+4+5+4+5+4+5+3+4)+3+28
.ident (.concat ("op_tick_38_page_", .string(page))): .ident (.concat ("op_tick_38_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -785,7 +823,7 @@ tickident page, 8
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
STA zpdummy ; 3 STA zpdummy ; 3
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_28")) ; 3 + 28 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_28")) ; 3 + 28
.endmacro .endmacro
@ -794,7 +832,7 @@ tickident page, 8
.macro op_tick_40 page ; pattern repeats from op_tick_22 .macro op_tick_40 page ; pattern repeats from op_tick_22
;4+(4+4+5+4+5+4+5+4+4)+3+3+24 ;4+(4+4+5+4+5+4+5+4+4)+3+3+24
.ident (.concat ("op_tick_40_page_", .string(page))): .ident (.concat ("op_tick_40_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -803,7 +841,7 @@ tickident page, 8
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
BIT tick ; 4 BIT TICK ; 4
STA zpdummy STA zpdummy
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_24")) JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_24"))
@ -812,7 +850,7 @@ tickident page, 8
.macro op_tick_42 page ; pattern repeats from op_tick_24 .macro op_tick_42 page ; pattern repeats from op_tick_24
;4+(4+4+5+4+5+4+5+4+3+4)+3+24 ;4+(4+4+5+4+5+4+5+4+3+4)+3+24
.ident (.concat ("op_tick_42_page_", .string(page))): .ident (.concat ("op_tick_42_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -822,7 +860,7 @@ tickident page, 8
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
STA zpdummy ; 3 STA zpdummy ; 3
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_24")) ; 3 + 24 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_24")) ; 3 + 24
.endmacro .endmacro
@ -830,7 +868,7 @@ tickident page, 8
.macro op_tick_44 page ; pattern repeats from op_tick_26 .macro op_tick_44 page ; pattern repeats from op_tick_26
; 4 + (4+4+5+4+5+4+5+4+5+4)+3+3+19 ; 4 + (4+4+5+4+5+4+5+4+5+4)+3+3+19
.ident (.concat ("op_tick_44_page_", .string(page))): .ident (.concat ("op_tick_44_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -840,7 +878,7 @@ tickident page, 8
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
BIT tick; 4 BIT TICK; 4
STA zpdummy ; 3 STA zpdummy ; 3
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_19")) ; 3 + 19 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_19")) ; 3 + 19
@ -849,7 +887,7 @@ tickident page, 8
.macro op_tick_46 page ; pattern repeats from op_tick_28 .macro op_tick_46 page ; pattern repeats from op_tick_28
;4+(4+2+4+5+4+5+4+5+4+5+4)+3+20 ;4+(4+2+4+5+4+5+4+5+4+5+4)+3+20
.ident (.concat ("op_tick_46_page_", .string(page))): .ident (.concat ("op_tick_46_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -860,7 +898,7 @@ tickident page, 8
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_20")) JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_20"))
.endmacro .endmacro
@ -868,7 +906,7 @@ tickident page, 8
.macro op_tick_48 page ; pattern repeats from op_tick_30 .macro op_tick_48 page ; pattern repeats from op_tick_30
;4+(4+4+5+4+5+4+5+4+5+4+4)+3+3+15 ;4+(4+4+5+4+5+4+5+4+5+4+4)+3+3+15
.ident (.concat ("op_tick_48_page_", .string(page))): .ident (.concat ("op_tick_48_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -880,7 +918,7 @@ tickident page, 8
STA page << 8,Y ; 5 STA page << 8,Y ; 5
LDA WDATA ; 4 LDA WDATA ; 4
BIT tick ; 4 BIT TICK ; 4
STA zpdummy ; 3 STA zpdummy ; 3
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_15")) ; 3 + 15 JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_15")) ; 3 + 15
@ -889,7 +927,7 @@ tickident page, 8
.macro op_tick_50 page ; pattern repeats from op_tick_32 .macro op_tick_50 page ; pattern repeats from op_tick_32
;4+(4+4+5+4+5+4+5+4+5+4+2+4)+3+16 ;4+(4+4+5+4+5+4+5+4+5+4+2+4)+3+16
.ident (.concat ("op_tick_50_page_", .string(page))): .ident (.concat ("op_tick_50_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -902,7 +940,7 @@ tickident page, 8
LDA WDATA ; 4 LDA WDATA ; 4
NOP ; 2 NOP ; 2
BIT tick ; 4 BIT TICK ; 4
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_16")) JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_16"))
.endmacro .endmacro
@ -910,7 +948,7 @@ tickident page, 8
.macro op_tick_52 page ; pattern repeats from op_tick_34 .macro op_tick_52 page ; pattern repeats from op_tick_34
;4+(4+4+5+4+5+4+5+4+5+4+4+4)+2+3+12 ;4+(4+4+5+4+5+4+5+4+5+4+4+4)+2+3+12
.ident (.concat ("op_tick_52_page_", .string(page))): .ident (.concat ("op_tick_52_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -923,7 +961,7 @@ tickident page, 8
LDA WDATA ; 4 LDA WDATA ; 4
STA .ident (.concat ("_op_tick_6_page_", .string(page), "_jmp"))+2 ; 4 STA .ident (.concat ("_op_tick_6_page_", .string(page), "_jmp"))+2 ; 4
BIT tick ; 4 BIT TICK ; 4
NOP ; 2 NOP ; 2
JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_12")) JMP .ident(.concat("_op_tick_page_", .string(page), "_tail_12"))
@ -932,7 +970,7 @@ tickident page, 8
.macro op_tick_54 page ; pattern repeats from op_tick_36 .macro op_tick_54 page ; pattern repeats from op_tick_36
; 4 + (4+4+5+4+5+4+5+3+3+4+5+4+4)+4+4+4+3 ; 4 + (4+4+5+4+5+4+5+3+3+4+5+4+4)+4+4+4+3
.ident (.concat ("op_tick_54_page_", .string(page))): .ident (.concat ("op_tick_54_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -948,7 +986,7 @@ tickident page, 8
STA zpdummy ; 3 STA zpdummy ; 3
STA zpdummy ; 3 STA zpdummy ; 3
BIT tick ; 4 BIT TICK ; 4
; used >3 pad cycles between tick pair; can't branch to tail ; used >3 pad cycles between tick pair; can't branch to tail
STA @D+2 ; 4 STA @D+2 ; 4
@ -961,7 +999,7 @@ tickident page, 8
.macro op_tick_56 page .macro op_tick_56 page
; 4+(4+4+5+4+5+4+5+4+5+4+4+4+4)+2+4+4+3 ; 4+(4+4+5+4+5+4+5+4+5+4+4+4+4)+2+4+4+3
.ident (.concat ("op_tick_56_page_", .string(page))): .ident (.concat ("op_tick_56_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -976,7 +1014,7 @@ tickident page, 8
STA @D+2 ; 4 STA @D+2 ; 4
STA dummy ; 4 STA dummy ; 4
BIT tick ; 4 BIT TICK ; 4
; used >3 pad cycles between tick pair; can't branch to tail ; used >3 pad cycles between tick pair; can't branch to tail
NOP ; 2 NOP ; 2
@ -990,7 +1028,7 @@ tickident page, 8
.macro op_tick_58 page ; pattern repeats from op_tick_40 .macro op_tick_58 page ; pattern repeats from op_tick_40
;4+(4+4+5+4+5+4+5+4+5+4+4+3+3+4)+4+4+3 ;4+(4+4+5+4+5+4+5+4+5+4+4+3+3+4)+4+4+3
.ident (.concat ("op_tick_58_page_", .string(page))): .ident (.concat ("op_tick_58_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -1006,7 +1044,7 @@ tickident page, 8
STA zpdummy ; 3 STA zpdummy ; 3
STA zpdummy ; 3 STA zpdummy ; 3
BIT tick ; 4 BIT TICK ; 4
; used >3 pad cycles between tick pair; can't branch to tail ; used >3 pad cycles between tick pair; can't branch to tail
LDA WDATA ; 4 LDA WDATA ; 4
@ -1018,7 +1056,7 @@ tickident page, 8
.macro op_tick_60 page .macro op_tick_60 page
; 4+(4+4+5+4+5+4+5+4+5+4+4+4+4+4)+2+4+3 ; 4+(4+4+5+4+5+4+5+4+5+4+4+4+4+4)+2+4+3
.ident (.concat ("op_tick_60_page_", .string(page))): .ident (.concat ("op_tick_60_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -1035,7 +1073,7 @@ tickident page, 8
LDA WDATA ; 4 LDA WDATA ; 4
STA dummy ; 4 STA dummy ; 4
BIT tick ; 4 BIT TICK ; 4
; used >3 pad cycles between tick pair; can't branch to tail ; used >3 pad cycles between tick pair; can't branch to tail
NOP ; 2 NOP ; 2
@ -1047,7 +1085,7 @@ tickident page, 8
.macro op_tick_62 page .macro op_tick_62 page
;4+(4+4+5+4+5+4+5+4+5+4+4+4+3+3+4)+4+3 ;4+(4+4+5+4+5+4+5+4+5+4+4+4+3+3+4)+4+3
.ident (.concat ("op_tick_62_page_", .string(page))): .ident (.concat ("op_tick_62_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -1064,7 +1102,7 @@ tickident page, 8
STA zpdummy ; 3 STA zpdummy ; 3
STA zpdummy ; 3 STA zpdummy ; 3
BIT tick ; 4 BIT TICK ; 4
; used >3 pad cycles between tick pair; can't branch to tail ; used >3 pad cycles between tick pair; can't branch to tail
STA @D+1 ; 4 STA @D+1 ; 4
@ -1075,7 +1113,7 @@ tickident page, 8
.macro op_tick_64 page .macro op_tick_64 page
;4+(4+4+5+4+5+4+5+4+5+4+4+4+4+4+4)+2+3 ;4+(4+4+5+4+5+4+5+4+5+4+4+4+4+4+4)+2+3
.ident (.concat ("op_tick_64_page_", .string(page))): .ident (.concat ("op_tick_64_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -1093,7 +1131,7 @@ tickident page, 8
STA @D+1 ; 4 STA @D+1 ; 4
STA dummy ; 4 STA dummy ; 4
BIT tick ; 4 BIT TICK ; 4
NOP ; 2 NOP ; 2
@D: @D:
@ -1103,7 +1141,7 @@ tickident page, 8
.macro op_tick_66 page ; pattern repeats from op_tick_8 .macro op_tick_66 page ; pattern repeats from op_tick_8
; 4+(4+4+5+4+5+4+5+4+5+4+4+4+3+4+3+4)+3 ; 4+(4+4+5+4+5+4+5+4+5+4+4+4+3+4+3+4)+3
.ident (.concat ("op_tick_66_page_", .string(page))): .ident (.concat ("op_tick_66_page_", .string(page))):
BIT tick ; 4 BIT TICK ; 4
LDA WDATA ; 4 LDA WDATA ; 4
LDY WDATA ; 4 LDY WDATA ; 4
STA page << 8,Y ; 5 STA page << 8,Y ; 5
@ -1122,7 +1160,7 @@ tickident page, 8
STA zpdummy ; 3 STA zpdummy ; 3
STA zpdummy ; 3 STA zpdummy ; 3
BIT tick ; 4 BIT TICK ; 4
@D: @D:
JMP op_nop ; 3 JMP op_nop ; 3
@ -1248,7 +1286,7 @@ op_terminate:
; the last 4 bytes in a 2K "TCP frame". i.e. we can assume that we need to consume ; the last 4 bytes in a 2K "TCP frame". i.e. we can assume that we need to consume
; exactly 2K from the W5100 socket buffer. ; exactly 2K from the W5100 socket buffer.
op_ack: op_ack:
BIT tick ; 4 BIT TICK ; 4
; allow flip-flopping the PAGE1/PAGE2 soft switches to steer writes to MAIN/AUX screens ; allow flip-flopping the PAGE1/PAGE2 soft switches to steer writes to MAIN/AUX screens
; actually this allows touching any $C0XX soft-switch, in case that is useful somehow ; actually this allows touching any $C0XX soft-switch, in case that is useful somehow
@ -1269,7 +1307,7 @@ op_ack:
LDX #<S0RXRD ; 2 LDX #<S0RXRD ; 2
STX WADRL ; 4 STX WADRL ; 4
BIT tick ; 4 (36) BIT TICK ; 4 (36)
LDA WDATA ; 4 Read high byte LDA WDATA ; 4 Read high byte
; No need to read low byte since it's guaranteed to be 0 since we're at the end of a 2K frame. ; No need to read low byte since it's guaranteed to be 0 since we're at the end of a 2K frame.
@ -1294,7 +1332,21 @@ op_ack:
; - used as the low byte for resetting the W5100 address pointer when we're ready to start processing more data ; - used as the low byte for resetting the W5100 address pointer when we're ready to start processing more data
LDX #$00 ; 2 restore invariant for dispatch loop LDX #$00 ; 2 restore invariant for dispatch loop
JMP CHECKRECV ; 3 (37 with following BIT tick) JMP checkrecv ; 3 (37 with following BIT TICK)
; Quit to ProDOS
exit:
INC RESET_VECTOR+2 ; Invalidate power-up byte
JSR PRODOS ; Call the MLI ($BF00)
.BYTE $65 ; CALL TYPE = QUIT
.ADDR exit_parmtable ; Pointer to parameter table
exit_parmtable:
.BYTE 4 ; Number of parameters is 4
.BYTE 0 ; 0 is the only quit type
.WORD 0000 ; Pointer reserved for future use
.BYTE 0 ; Byte reserved for future use
.WORD 0000 ; Pointer reserved for future use
; CLOSE TCP CONNECTION ; CLOSE TCP CONNECTION