cruisin-usa/COMM.ASM

1185 lines
19 KiB
NASM
Executable File

.FILE "COMM.ASM"
*----------------------------------------------------------------------------
*
*
*COPYRIGHT (C) 1994 BY TV GAMES, INC.
*ALL RIGHTS RESERVED
*
.include C30.EQU
.include OBJ.EQU
.include MACS.EQU
.include MPROC.EQU
.include VUNIT.EQU
.include CMOS.EQU
.include SYSID.EQU
.include SYS.EQU
.include GLOBALS.EQU
.include SNDTAB.EQU
.include PALL.EQU
.include OBJECTS.EQU
.include TEXT.EQU
.include COMM.EQU
TIME_DELAY .set 18
.globl COMM_MASTER_ERROR_CNT
.globl COMM_MASTER_TRANSES
.globl COMM_SLAVE_ERROR_CNT
.globl COMM_SLAVE_TRANSES
.globl COMM_SLAVE_NREADY
fbss COMM_MASTER_ERROR_CNT,1
fbss COMM_MASTER_TRANSES,1
fbss COMM_SLAVE_ERROR_CNT,1
fbss COMM_SLAVE_TRANSES,1
fbss COMM_SLAVE_NREADY,1
.bss COMMFLAG,1 ;COMMUNICATIONS IS OVER
pbss ONEFLAG,1
pbss TRANSMISSION_ACTIVE,1 ;1=TRUE
pbss TRANSMISSION_DEAD,1 ;1=DEAD LINK
*----------------------------------------------------------------------------
COMM_INIT:
PUSH DP
LDP @DIPRAM
LDI @DIPRAM,R1
LDI 0,R0
STI R0,@ONEFLAG ;CLEAR OUT ONE PLAYER FLAG
LDI C_SLA,R0
TSTB CMDP_MASTER,R1
LDIZ C_MAS,R0
LS 16,R0
LDP @COMMDP
STI R0,@COMM_IO
LDI C_CE,R0
LS 16,R0
STI R0,@COMM_CTL
POP DP
RETS
*----------------------------------------------------------------------------
RECEIVE_BUFFERI .word RECEIVE_BUFFER
COMM_IOI .word COMM_IO
CTL EQU COMM_CTL-COMM_IO
*----------------------------------------------------------------------------
COMM_ENABLE_INT2:
;
;if slave then enable the interrupt 2
;(comm int 2)
;
LDP @DIPRAM
LDI @DIPRAM,R1
TSTB DIP_COMMP,R1
BNZ BABA
TSTB CMDP_MASTER,R1
BZ BABA
LDI INT2_M,R1
LDP @COMMINTM
STI R1,@COMMINTM
BABA LDP @COMMINTM
OR @COMMINTM,IE
SETDP
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
COMM_MASTER_SEND_SYNC:
LDI @COMMFLAG,R0 ;DONT INTERRUPT COMMUNICATIONS
RETSNZ
LDI @DIPRAM,R0
TSTB CMDP_MASTER,R0
RETSNZ
DINT
ANDN INT2_M,IE ;DISABLE LINK INT2
LDI @COMM_IOI,AR5 ;SETUP I/O REGISTER
*TRIGGER INTERRUPT IN SLAVE
LDI *AR5,R0
RS 16,R0
AND C_C2,R0
LDI R0,R1
OR C_MAS|C_IRQ,R0
LS 16,R0
STI R0,*AR5 ;INT2 HI COMM_IO
NOP
NOP
NOP
LDI C_MAS,R0
OR R1,R0
LS 16,R0
STI R0,*AR5 ;INT2 LO COMM_IO
ANDN INT2_M,IF ;REMOVE ANY LATCHED INT
RETS
*----------------------------------------------------------------------------
*
*SET ONE PLAYER GAME (NO LINK)
*
SETONE:
PUSH R0
PUSH AR0
CLRI R0
STI R0,@TRANSMISSION_ACTIVE
LDI 1,R0
STI R0,@ONEFLAG
LDI @DIPRAM,R0
TSTB CMDP_MASTER,R0
LDIZ C_C2|C_MAS,R0 ;MASTER CASE SEND C2=1
LDINZ C_C1|C_SLA,R0 ;SLAVE CASE SEND C1=1
B ONEX
*
*CLR ONE PLAYER GAME (NO LINK)
*
CLRONE:
PUSH R0
PUSH AR0
LDI 1,R0
STI R0,@TRANSMISSION_ACTIVE
LDI 0,R0
STI R0,@ONEFLAG
LDI @DIPRAM,R0
TSTB CMDP_MASTER,R0
LDIZ C_MAS,R0 ;MASTER CASE
LDINZ C_SLA,R0 ;SLAVE CASE
ONEX
LDI @COMM_IOI,AR0 ;SETUP I/O REGISTER
LS 16,R0
STI R0,*AR0
POP AR0
POP R0
RETS
*----------------------------------------------------------------------------
*COMMUNICATIONS LINK
*
COMMPAL .set 0990000h ;COMMUNICATIONS PAL
COMM_ROUTINE:
CLRI AR7
LDP @COMMPAL
LDI @COMMPAL,R0
LDI *AR7,R1
SETDP
AND 0FH,R0
CMPI 4,R0 ;BAD PAL ?
RETSNZ ;YES....QUIT
LDI @DIPRAM,R0 ;CHECK FOR COMMUNICATIONS
TSTB DIP_COMMP,R0
RETSNZ ;NO
COMM_HOLDFORA2D
LDI @RDPOT,R1
CMPI 3,R1
BNZ COMM_HOLDFORA2D
LDI 1,R1
STI R1,@COMMFLAG ;DONT INTERRUPT COMMUNICATIONS
TSTB CMDP_MASTER,R0 ;CHECK MASTER/SLAVE
BNZ COMM_SLAVE
*
*MASTER MUST ALWAYS 0 <- C_IRQE
*
COMM_MASTER:
SETDP
LDI @COMM_IOI,AR5 ;SETUP I/O REGISTER
*CHECK ONE PLAYER MODE
LDI @ONEFLAG,R0
BZ CM1
RETS ;WE'RE IN ONE PLAYER, EXIT
CM1
LDI @SEND_BUFFER_A_LEN,R6 ;16 bits
LDI @SEND_BUFFER_AI,AR2
CMPI 0,R6
BLE CMERRORL ;ZERO LENGTH, NO MESSAGE
CMPI 240H,R6
BGE CMERRORL ;LENGTH ERROR
ADDI R6,AR2,AR0 ;ADD 2 NULLS TO THE END DUDES
LDI CB_NULL,R2
STI R2,*AR0
STI R2,*+AR0(1)
*BEGIN SYNC ROUTINE
LDI C_MAS,R0 ;send C2=0
LS 16,R0
STI R0,*AR5
LDI 120,R3
LDI @TRANSMISSION_DEAD,R0 ;GET TIMEOUT VALUES
BZ WTLPMI
LDI 1,R3 ;WAIT A FRAME IF DEAD
ADDI @INFRAMES,R3
CMPI 4,R3
LDIGT 4,R3
WTLPMI LDI *AR5,R0 ;GET C0,C1
RS 16,R0
TSTB C_C1,R0 ;SLAVE C1=1 (ONE PLAYER MODE)
BZ CM2 ;NO
LDI 0,R0 ;SLAVE IN ONE PLAYER MODE, EXIT
STI R0,@TRANSMISSION_ACTIVE
STI R0,@TRANSMISSION_DEAD
RETS
CM2
TSTB C_C0,R0 ;WAIT FOR SLAVE READY SIGNAL
BNZ CM3 ;GOT IT...
CMPI @INFRAMES,R3 ;WAITING TOO LONG?
BGT WTLPMI ;NO, KEEP LOOPING
B CMERRORDEAD ;YES, ITS DEAD...
CM3
LDI 0,R0
STI R0,@TRANSMISSION_DEAD
LDI 1,R0
STI R0,@TRANSMISSION_ACTIVE
LDI C_C2|C_MAS,R0 ;SEND C2=1
LS 16,R0
STI R0,*AR5
ADDI 1,R3 ;A LITTLE MORE TIME
WTLPMI2
CMPI @INFRAMES,R3 ;WAITING TOO LONG?
BLE CMERRORDEAD ;YES, ITS DEAD...
LDI *AR5,R0 ;WAIT C0=0
RS 16,R0
TSTB C_C0,R0
BNZ WTLPMI2
LDI C_MAS,R0 ;send C2=0
LS 16,R0
STI R0,*AR5
;
;END SYNC ROUTINE
DINT
WTLPMI3 LDI *AR5,R0 ;WAIT C1=1
RS 16,R0
TSTB C_C1,R0
BZ WTLPMI3
LDI C_MAS,R0
LS 16,R0
STI R0,*AR5
LDI C_SND,R0 ;SET DATA CONTROL FOR SEND
LS 16,R0
STI R0,*+AR5(CTL) ;COMM_CTL
*
*SEND MESSAGE LENGTH TO SLAVE
*16 BITS LENGTH
*MESSAGE LENGTH IS MULT OF 2
*
ADDI 1,R6
RS 1,R6
LDI R6,AR6
NOT R6,R7
LDI R7,R5
LSH -8,R7
LDI R6,R4
LSH -8,R6
AND 0FFH,R7
AND 0FFH,R6
AND 0FFH,R5
AND 0FFH,R4
*SEND LENGTH (BYTE 1 MSB)
OR C_MAS|C_C2,R6 ; (C2=1)
LS 16,R6
STI R6,*AR5 ;SEND C2 HIGH WITH DATA
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
*SEND LENGTH (BYTE 2 LSB)
OR C_MAS,R4 ; (C2=1)
LS 16,R4
STI R4,*AR5 ;SEND C2 HIGH WITH DATA
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
*SEND LENGTH (BYTE 3 MSB COMPLEMENTED)
OR C_MAS|C_C2,R7 ; (C2=1)
LS 16,R7
STI R7,*AR5 ;SEND C2 HIGH WITH DATA
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
*SEND LENGTH (BYTE 4 LSB COMPLEMENTED)
OR C_MAS,R5
LS 16,R5
STI R5,*AR5 ;SEND C2 LOW WITH DATA
RPTS 65
NOP
DEC AR6
LDI 0FFh,R4
*
* SEND MASTERS BUFFER
*
LDI 0,R3 ;CHECKSUM
*byte1
AND *AR2++,R4,R6
ADDI R6,R3 ;FORM CHECKSUM
OR C_MAS|C_C2,R6 ;(C2=1)
MSDLP
LS 16,R6
STI R6,*AR5
RPTS TIME_DELAY
NOP
*byte2
AND *AR2++,R4,R6
ADDI R6,R3
OR C_MAS,R6 ;(C2=0)
LS 16,R6
STI R6,*AR5
RPTS TIME_DELAY
NOP
DBUD AR6,MSDLP
AND *AR2++,R4,R6
ADDI R6,R3 ;FORM CHECKSUM
OR C_MAS|C_C2,R6 ; (C2=1)
;---->DBUD AR6,MSDLP
ANDN C_MAS|C_C2,R6 ;ONE TOO MANY...
SUBI R6,R3
*SEND THE CHECKSUM
AND 0FFFFH,R3 ;MASK CKSUM TO 16 BITS
LDI R3,R6 ;SEND MSB
RS 8,R6
OR C_MAS|C_C2,R6 ;(C2=1)
LS 16,R6
STI R6,*AR5 ;SEND 2 HIGH
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
LS 24,R3
RS 24,R3
OR C_MAS,R3 ;(C2=0)
LS 16,R3
STI R3,*AR5 ;SEND 2 HIGH
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
LDI C_RCV,R0 ;CHANGE CONTROL TO RECEIVE
LS 16,R0
STI R0,*+AR5(CTL) ;@COMM_CTL
*
* WAIT FOR SLAVE TO SIGNIFY DONE (C1=0)
*
LDI 30,R5 ;TIMEOUT
CML1XX DEC R5
BLT CMERROR10
LDI *AR5,R0
RS 16,R0
TSTB C_C1,R0
BNZ CML1XX
*
* MASTER TELLS SLAVE IT IS LISTENING (C2=1)
*
LDI @RECEIVE_BUFFERI,AR2 ;SETUP RECEIVE BUFFER
LDI C_C2|C_MAS,R0 ;SET C2=HI
LS 16,R0
STI R0,*AR5
* GET SLAVES BUFFER LENGTH
* BUFFER LENGTH IS X 2
* 4 BYTES LENGTH MSB, LSB, COMP MSB, COMP LSB
*
LDP COMM_IO
LDI C_C1,R5
LS 16,R5
LDI 300,AR3
PWL2M TSTB @COMM_IO,R5
DBZ AR3,PWL2M
TSTB 8000H,AR3
BNZD CMERROR1 ;ERROR IN TIMEOUT
NOP
LDI 300,AR3
LDI @COMM_IO,R7 ;GET MSB
;---->BNZD CMERROR1
PWL3M TSTB @COMM_IO,R5
DBNZ AR3,PWL3M
TSTB 8000H,AR3
BNZD CMERROR2 ;ERROR IN TIMEOUT
NOP
LDI @COMM_IO,R6 ;GET LSB
LS 8,R6
;---->BNZD CMERROR2
LDI 300,AR3
PWL4M TSTB @COMM_IO,R5
DBZ AR3,PWL4M
TSTB 8000H,AR3
BNZD CMERROR1 ;ERROR IN TIMEOUT
NOP
LDI 300,AR3
NOT @COMM_IO,R4 ;GET MSB COMPLEMENT
;---->BNZD CMERROR1
PWL5M TSTB @COMM_IO,R5
DBNZ AR3,PWL5M
TSTB 8000H,AR3
BNZD CMERROR2 ;ERROR IN TIMEOUT
NOP
NOT @COMM_IO,R2 ;GET LSB COMPLEMENT
LS 8,R2
;---->BNZD CMERROR2
LS 8,R4
LS 8,R7
RS 24,R2
RS 24,R4
RS 24,R6
RS 24,R7
CMPI R2,R6
BNE CMERROR3 ;ERROR IN LENGTH
CMPI R4,R7
BNE CMERROR3 ;ERROR IN LENGTH
LSH 8,R7
ADDI R6,R7,AR6
CMPI 140H,AR6 ;LENGTH ERROR
BGE CMERROR3 ;TOO LONG
CMPI 0,AR6 ;SLAVE LENGTH ZERO...
BEQ CMERROR3
DEC AR6 ;THIS IS THE LENGTH INDEX
*
* GET SLAVES BUFFER
*
SETDP
STI AR6,@RBUFF_LEN
LDP @COMM_IO
CLRI R3 ;RESET CKSUM
LDI 0FFH,R2
LSH 16,R2
LDI 300,AR3
WL2M TSTB @COMM_IO,R5
DBZ AR3,WL2M
TSTB 8000H,AR3
BNZD CMERROR4 ;YES...QUIT
LDI 300,AR3
NOP
AND R2,*AR5,R6
;----> BNZD CMERROR4
ADDI R6,R3
STI R6,*AR2++
WL3M TSTB *AR5,R5
DBNZ AR3,WL3M
TSTB 8000H,AR3
BNZD CMERROR5 ;YES...QUIT
NOP
NOP
AND R2,*AR5,R6
;----> BNZD CMERROR5
DBUD AR6,WL2M
ADDI R6,R3
STI R6,*AR2++
LDI 300,AR3
;---->DBUD AR6,WL2M
*GET SLAVES CKSUM
WL2MC TSTB @COMM_IO,R5
DBZ AR3,WL2MC
TSTB 8000H,AR3
BNZD CMERROR6 ;YES...QUIT
NOP
LDI 300,AR3
LDI @COMM_IO,R6 ;MSB CKSUM
;----> BNZD CMERROR6
WL3MC TSTB @COMM_IO,R5
DBNZ AR3,WL3MC
TSTB 8000H,AR3
BNZD CMERROR7 ;YES...QUIT
RS 8,R6
AND 0FF00h,R6
LDI @COMM_IO,R7 ;LSB CKSUM
;----> BNZD CMERROR7
RS 16,R7
AND 0FFh,R7
ADDI R6,R7
RS 16,R3
CMPI R7,R3
BNE CMERROR8 ;CKSUM ERROR
M0LENGTH
COMM_MASTER_X
LDP @COMM_MASTER_TRANSES
INCM @COMM_MASTER_TRANSES
COMM_MASTER_ERR_X
LDI C_MAS,R0 ;SET C2=0
LS 16,R0
STI R0,*AR5
LDI C_RCV,R0 ;SET DATA CONTROL TO RECEIVE
LS 16,R0
STI R0,*+AR5(CTL)
SETDP
LDI 0,R0
STI R0,@COMMFLAG ;COMMUNICATIONS IS OVER
EINT
RETS
.globl CMERROR1
CMERROR1 B COMM_MASTER_ERROR ;LENGTH TIMEOUT
CMERROR2 B COMM_MASTER_ERROR ;LENGTH TIMEOUT
CMERROR3 B COMM_MASTER_ERROR ;BAD LENGTH
CMERROR4 B COMM_MASTER_ERROR ;DATA TIMEOUT
CMERROR5 B COMM_MASTER_ERROR ;DATA TIMEOUT
CMERROR6 B COMM_MASTER_ERROR ;CKSUM TIMEOUT
CMERROR7 B COMM_MASTER_ERROR ;CKSUM TIMEOUT
CMERROR8 B COMM_MASTER_ERROR ;BAD CKSUM
CMERROR9 B COMM_MASTER_ERROR ;MASTER SEND TIMEOUT
CMERROR10 B COMM_MASTER_ERROR ;MASTER END TIMEOUT (SLAVE ERR)
CMERRORL B COMM_MASTER_ERROR ;LENGTH TOO LONG
CMERRORDEAD
LDI 1,R0 ;YES OTHER GAME IS DEAD, LEAVE...
STI R0,@TRANSMISSION_DEAD
B COMM_MASTER_ERROR ;WENT DEAD...
COMM_MASTER_ERROR
LDP @COMM_MASTER_TRANSES
INCM @COMM_MASTER_ERROR_CNT
SETDP
LDI 0,R0
STI R0,@RBUFF_LEN ;RECEIVE BUFFER CLEARED ON ERROR
; LDI C_C2|C_MAS,R0 ;SET C2=HI
; LS 16,R0
; STI R0,*AR5
B COMM_MASTER_ERR_X
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
COMM_IRQ:
PUSH ST
PUSH DP
PUSH R0
ANDN INT2_M,IF
;determine if I am a master being interrupted
;
LDP @DIPRAM
LDI @DIPRAM,R0
TSTB CMDP_MASTER,R0
BNZ DO_SLAVE_SYNC
POP R0
POP DP
POP ST
RETI
DO_SLAVE_SYNC:
PUSH R1
PUSH IE
LDI INT1_M|INT2_M,IE ;disable everything except TV30 interrupt & comm int
ANDN INT2_M,IF ;we wont irq ourself
LDP @CPU_WS
LDI @CPU_WS,R0
PUSH R0
LDI SOFT_WS,R0
STI R0,@CPU_WS
;sync the systems...
;
;
LDP @FIFO_CONTROL
LDI @FIFO_CONTROL,R0
ANDN FIFO_CONTROL_DMA_RUNSEL,R0
STI R0,@FIFO_CONTROL
WTLP LDI @FIFO_STATUS,R0
AND FIFO_STATUS_FD_CRITICAL,R0
BNZ WTLP
;same LDP @CRT_VCNT
LDI @CRT_VCNT,R0
AND 1FFh,R0
; CMPI 400,R0
; LDIEQ 1b0h,R0
; LDIGT 1b1h,R0
; LDILT 1afh,R0
LDI 1B0H,R1
SUBI 400,R0
CMPI -1,R0 ;GRACE AREA DUDES
LDILT 1afh,R1
CMPI 1,R0
LDIGT 1b1h,R1
STI R1,@CRT_VTTL
LDI @FIFO_CONTROL,R0
OR FIFO_CONTROL_DMA_RUNSEL,R0
STI R0,@FIFO_CONTROL
POP R0
LDP @CPU_WS
STI R0,@CPU_WS
POP IE
POP R1
POP R0
POP DP
; LDI INT1_M|INT2_M|INT3_M|INT0_M,IE
POP ST
RETI
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*CALLED FROM THE MAIN LOOP
*
*SET C0 HIGH
*WAIT FOR C2 TO GO HIGH
*BEGIN TRANSFER
*END OF TRANSFER
*SET ALL LOW
*
*
COMM_SLAVE:
SETDP
LDI @COMM_IOI,AR5 ;AR5=COMM I/O ADDRESS
LDI @RECEIVE_BUFFERI,AR2 ;AR2=RECEIVE BUFFER
LDI C_C2,R5 ;R5=C_C2 MASK
LS 16,R5
*CHECK ONE PLAYER MODE
LDI @ONEFLAG,R0
BZ CS1
RETS ;WE'RE IN ONE PLAYER, EXIT
CS1
TSTB *AR5,R5
BZ CS2 ;C2=1, MASTER IN ONE PLAYER, EXIT
LDI 0,R0
STI R0,@TRANSMISSION_DEAD
STI R0,@TRANSMISSION_ACTIVE
RETS
*SYNC UP
CS2
LDI 120,R3 ;WAIT 120 FRAMES IF NOT DEAD
LDI @TRANSMISSION_DEAD,R0 ;GET TIMEOUT VALUES
BZ CS20
LDI 1,R3 ;WAIT 1 IF DEAD
ADDI @INFRAMES,R3
CMPI 4,R3
LDIGT 4,R3
CS20
LDI 1,R0
STI R0,@TRANSMISSION_ACTIVE
LDI C_C0|C_SLA,R0
LS 16,R0
STI R0,*AR5 ;SEND C0=1
WTLPI
CMPI @INFRAMES,R3 ;WAITING TOO LONG?
BLE CSERRORDEAD ;YES, ITS DEAD...
TSTB *AR5,R5 ;WAIT C2=1
BZ WTLPI
LDI C_SLA,R0 ;SEND C0=0
LS 16,R0
STI R0,*AR5
LDI 0,R0
STI R0,@TRANSMISSION_DEAD
LDI 10000,AR3 ;TIMEOUT VALUE
WTLPI2
TSTB *AR5,R5 ;WAIT C2=0
DBNZ AR3,WTLPI2
TSTB 8000H,AR3 ;TIMEOUT?
BZ CS3 ;NO
RETS ;YES, LEAVE
*END SYNC
CS3
DINT
*SET DATA CONTROL TO RECEIVE ;CM_A 1
LDI C_RCV,R0
LS 16,R0
STI R0,*+AR5(CTL)
*TELL MASTER WE ARE LISTENING (C0=0,C1=1)
LDI C_C1|C_SLA,R0
LS 16,R0
STI R0,*AR5
*GET MASTERS BUFFER LENGTH
*BUFFER LENGTH IS X 2
*FIRST BYTE IS LENGTH
*SECOND BYTE IS COMPLEMENT OF LENGTH
LDP @COMM_IO
LDI 300,AR3
PWL2 TSTB @COMM_IO,R5
DBZ AR3,PWL2
TSTB 8000H,AR3
BNZD CSERROR1 ;ERROR IN TIMEOUT
NOP
LDI 300,AR3
LDI @COMM_IO,R7 ;GET MSB
;---->BNZD CSERROR1
PWL3 TSTB @COMM_IO,R5
DBNZ AR3,PWL3
TSTB 8000H,AR3
BNZD CSERROR2 ;ERROR IN TIMEOUT
NOP
LDI @COMM_IO,R6 ;GET LSB
LS 8,R6
;---->BNZD CSERROR2
LDI 300,AR3
PWL4 TSTB @COMM_IO,R5
DBZ AR3,PWL4
TSTB 8000H,AR3
BNZD CSERROR1 ;ERROR IN TIMEOUT
NOP
LDI 300,AR3
NOT @COMM_IO,R4 ;GET MSB COMPLEMENT
;---->BNZD CSERROR1
PWL5 TSTB @COMM_IO,R5
DBNZ AR3,PWL5
TSTB 8000H,AR3
BNZD CSERROR2 ;ERROR IN TIMEOUT
NOP
NOT @COMM_IO,R2 ;GET LSB COMPLEMENT
LS 8,R2
;---->BND CSERROR2
LS 8,R4
LS 8,R7
RS 24,R2
RS 24,R4
RS 24,R6
RS 24,R7
CMPI R2,R6
BNE CSERROR3 ;ERROR IN LENGTH
CMPI R4,R7
BNE CSERROR3 ;ERROR IN LENGTH
LSH 8,R7
ADDI R6,R7,AR6
DEC AR6 ;THIS IS THE LENGTH INDEX
CMPI 140H,AR6 ;LENGTH ERROR
BGE CSERROR3 ;TOO LONG
*
*GET MASTERS BUFFER
*
SETDP
STI AR6,@RBUFF_LEN
LDP @COMM_IO
CLRI R3 ;RESET CKSUM
LDI 0FFH,R2
LSH 16,R2
LDI 300,AR3
WL2 TSTB @COMM_IO,R5
DBZ AR3,WL2
TSTB 8000H,AR3
BNZD CSERROR4 ;YES...QUIT
LDI 300,AR3
NOP
AND R2,*AR5,R6
;----> BNZD CSERROR4 ;YES...QUIT
ADDI R6,R3
STI R6,*AR2++
WL3 TSTB *AR5,R5
DBNZ AR3,WL3
TSTB 8000H,AR3
BNZD CSERROR5 ;YES...QUIT
NOP
NOP
AND R2,*AR5,R6
;----> BNZD CSERROR5 ;YES...QUIT
DBUD AR6,WL2
ADDI R6,R3
STI R6,*AR2++
LDI 300,AR3
*GET MASTERS CKSUM
WL2C TSTB @COMM_IO,R5
DBZ AR3,WL2C
TSTB 8000H,AR3
BNZD CSERROR6 ;YES...QUIT
NOP
LDI 300,AR3
LDI @COMM_IO,R6 ;MSB CKSUM
;----> BNZD CSERROR6 ;YES...QUIT
WL3C TSTB @COMM_IO,R5
DBNZ AR3,WL3C
TSTB 8000H,AR3
BNZD CSERROR7 ;YES...QUIT
RS 8,R6
AND 0FF00h,R6
LDI @COMM_IO,R7 ;LSB CKSUM
;----> BNZD CSERROR7 ;YES...QUIT
RS 16,R7
AND 0FFh,R7
ADDI R6,R7
RS 16,R3
CMPI R7,R3
BNE CSERROR8 ;CKSUM ERROR
* LOWER SLAVES C1
* (tell master we are prepared to send)
*
SETDP
LDI C_SLA,R0
LS 16,R0
STI R0,*AR5
*
* SLAVE SEND
*
* WAIT FOR MASTER TO LISTEN (C2=1)
LDI 50,R5 ;TIMEOUT
CML1S DEC R5
BLT CSERROR9
LDI *AR5,R0
RS 16,R0
TSTB C_C2,R0
BZ CML1S
LDI C_SND,R0 ;CHANGE DATA BUFFER DIRECTION TO SEND
LS 16,R0
STI R0,*+AR5(CTL)
* SEND SLAVE LENGTH
*SEND MESSAGE LENGTH TO MASTER
*MESSAGE LENGTH IS MULTIPLE OF 2
SETDP
LDI @SEND_BUFFER_A_LEN,R6
LDI @SEND_BUFFER_AI,AR2
ADDI R6,AR2,AR0 ;ADD 2 NULLS TO THE END DUDES
LDI CB_NULL,R2
STI R2,*AR0
STI R2,*+AR0(1)
ADDI 1,R6
RS 1,R6
LDI R6,AR6
NOT R6,R7
LDI R7,R5
LSH -8,R7
LDI R6,R4
LSH -8,R6
AND 0FFH,R7
AND 0FFH,R6
AND 0FFH,R5
AND 0FFH,R4
*SEND LENGTH (BYTE 1 MSB)
OR C_SLA|C_C1,R6 ; (C2=1)
LS 16,R6
STI R6,*AR5 ;SEND C2 HIGH WITH DATA
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
*SEND LENGTH (BYTE 2 LSB)
OR C_SLA,R4 ; (C2=1)
LS 16,R4
STI R4,*AR5 ;SEND C2 HIGH WITH DATA
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
*SEND LENGTH (BYTE 3 MSB COMPLEMENTED)
OR C_SLA|C_C1,R7 ; (C2=1)
LS 16,R7
STI R7,*AR5 ;SEND C2 HIGH WITH DATA
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
*SEND LENGTH (BYTE 4 LSB COMPLEMENTED)
OR C_SLA,R5
LS 16,R5
STI R5,*AR5 ;SEND C2 LOW WITH DATA
RPTS 65
NOP
DEC AR6
LDI 0FFh,R4
*
* SLAVE SEND BUFFER TO MASTER
*
LDI 0,R3 ;CHECKSUM
*byte1
AND *AR2++,R4,R6
ADDI R6,R3 ;FORM CHECKSUM
OR C_SLA|C_C1,R6 ;(C1=1)
SSDLP
LS 16,R6
STI R6,*AR5
RPTS TIME_DELAY
NOP
*byte2
AND *AR2++,R4,R6
ADDI R6,R3
OR C_SLA,R6 ;(C1=0)
LS 16,R6
STI R6,*AR5
RPTS TIME_DELAY
NOP
DBUD AR6,SSDLP
AND *AR2++,R4,R6
ADDI R6,R3 ;FORM CHECKSUM
OR C_SLA|C_C1,R6 ; (C2=1)
;---->DBUD AR6,SSDLP
ANDN C_SLA|C_C1,R6
SUBI R6,R3 ;ONE OVER!!!
*SEND THE CHECKSUM
AND 0FFFFH,R3 ;MASK CKSUM TO 16 BITS
LDI R3,R6 ;SEND MSB
RS 8,R6
OR C_SLA|C_C1,R6 ;(C1=1)
LS 16,R6
STI R6,*AR5 ;SEND DATA
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
LS 24,R3
RS 24,R3
OR C_SLA,R3 ;(C1=0)
LS 16,R3
STI R3,*AR5 ;SEND DATA
RPTS TIME_DELAY ;HOLD FOR A SEC
NOP
*WAIT FOR MASTER TO INDICATE O.K. C2=0
LENGTHOF0
LDI 50,R5 ;TIMEOUT
CML1WT DEC R5
BLT CSERROR11
LDI *AR5,R0
RS 16,R0
TSTB C_C2,R0
BNZ CML1WT
COMM_SLAVE_X
LDP @COMM_SLAVE_TRANSES
INCM @COMM_SLAVE_TRANSES
COMM_SLAVE_ERR_X
SETDP
LDI C_SLA,R0 ;SET C0=0,C1=0, NO ERROR
LS 16,R0
STI R0,*AR5
LDI C_RCV,R0 ;CHANGE CONTROL TO RECEIVE
LS 16,R0
STI R0,*+AR5(CTL) ;@COMM_CTL
LDI 0,R0
STI R0,@COMMFLAG ;COMMUNICATIONS IS OVER
EINT
RETS
CSERROR1 B COMM_SLAVE_ERROR ;LENGTH TIMEOUT
CSERROR2 B COMM_SLAVE_ERROR ;LENGTH TIMEOUT
CSERROR3 B COMM_SLAVE_ERROR ;BAD LENGTH
CSERROR4 B COMM_SLAVE_ERROR ;DATA TIMEOUT
CSERROR5 B COMM_SLAVE_ERROR ;DATA TIMEOUT
CSERROR6 B COMM_SLAVE_ERROR ;CKSUM TIMEOUT
CSERROR7 B COMM_SLAVE_ERROR ;CKSUM TIMEOUT
CSERROR8 B COMM_SLAVE_ERROR ;BAD CKSUM
CSERROR9 B COMM_SLAVE_ERROR ;SLAVE SEND TIMEOUT
CSERROR11 B COMM_SLAVE_ERROR ;MASTER ERROR END TIMEOUT
CSERRORDEAD
LDI 1,R0 ;YES OTHER GAME IS DEAD, LEAVE...
STI R0,@TRANSMISSION_DEAD
B COMM_SLAVE_ERROR ;WENT DEAD...
COMM_SLAVE_ERROR
LDP @COMM_SLAVE_ERROR_CNT
INCM @COMM_SLAVE_ERROR_CNT
SETDP
LDI 0,R0
STI R0,@RBUFF_LEN ;RECEIVE BUFFER CLEARED ON ERROR
BU COMM_SLAVE_ERR_X
*----------------------------------------------------------------------------
.END