The network routines
THE '"N" CHANNEL INPUT' ROUTINE
This routine handles the input of a single byte. When 'EOF' occurs, an error is given,
in case of an other error retries will be made.
3808 N_INPUT PUSH BC Save registers before getting a byte.
3809 PUSH DE
380A PUSH HL
380B NCI_RETRY CALL #3819,NCHAN_IN
380E JR C,#3815,NCI_ACCEPT Jump if byte acceptable.
3810 JR Z,#380B,NCI_RETRY Try again if no byte has been read.
3812 JP #2956,REP_27 Give error if end of file.
3815 NCI_ACCEPT POP HL Restore registers and exit.
3816 POP DE
3817 POP BC
3818 RET
THE '"N" CHANNEL INPUT' ROUTINE
The actual "n" input involves the reading of the byte from the network buffer. If no
other bytes are found in the buffer, a further data block is to be received (provided
that the 'current' block is not the 'EOF' one) before reading the byte.
3819 NCHAN_IN LD IX,#1E3D Fetch start of "n" channel.
381D LD A,(IX+16)
3820 AND A
3821 JP NZ,#2944,REP_18 Jump if it isn't a "read" file.
3824 TEST_BUFF LD A,(IX+20) Fetch number of bytes in input buffer.
3827 AND A
3828 JR Z,#383E,TEST_N_EOF Jump if buffer is empty.
382A LD E,(IX+19) Otherwise fetch the current position.
382D DEC A Decrease number of bytes to be read.
382E SUB E
382F JR C,#383E,TEST_N_EOF Jump if all bytes have been read.
3831 LD D,0 Clear D.
3833 INC E
3834 LD (IX+19),E Update byte position.
3837 ADD IX,DE Point to 'byte to be read - 20'.
3839 LD A,(IX+20) Read the byte.
383C SCF Signal 'acceptable byte'.
383D RET
If no data is found in the buffer, consider whether this is the last data block.
383E TEST_N_EOF LD A,(IX+15) Fetch packet type.
3841 AND A Jump if it is a normal packet (packet
3842 JR Z,#3845,GET_N_BUF type of EOF = 1).
3844 RET Otherwise return with both Zero and
Carry flags reset to signal 'EOF'.
A further data block is to be received if the current data block is not the 'EOF' one.
3845 GET_N_BUF CALL #3AF1,NET_BORD Set border colour, store IFF and DI.
3848 TRY_AGAIN CALL #3A09,WT_SCOUT Wait for a 'scout' leader.
384B JR NC,#3861,TIME_OUT Jump if 'time out' occurs.
384D CALL #391E,GET_NBLK Get header and data block.
3850 JR NZ,#3861,TIME_OUT Jump with any error.
3852 CALL #3B02,REST_BORD Restore border and interrupt status.
3855 LD (IX+19),#00 Reset byte position.
3859 LD A,(#1DF9)
385C LD (IX+15),A Store packet type.
385F JR #3824,TEST_BUFF Now try to fetch the byte.
Something went wrong, ignore it when broadcasting.
3861 TIME_OUT LD A,(IX+11) Fetch destination station number.
3864 AND A Jump if broadcasting, then there is no
3865 JR Z,#3848,TRY_AGAIN 'time out'.
3867 CALL #3B02,REST_BORD Restore border and interrupt status.
386A AND 0 Return with Zero flag set and Carry
386C RET reset, to signal 'no data read'.
THE '"N" CHANNEL OUTPUT' ROUTINE
This routine handles the output of a single byte.
386D N_OUTPUT PUSH BC Save registers before outputting the
386E PUSH DE byte.
386F PUSH HL
3870 CALL #3877,NCHAN_OUT
3873 POP HL Restore registers and exit.
3874 POP DE
3875 POP BC
3876 RET
THE '"N" CHANNEL OUTPUT' ROUTINE
The routine that handles the "n" channel output is quite straightforward. It involves
the storing of the byte held in the A register into the 255-byte buffer; whenever this
is filled, the subroutine 'S_PACK_1' is called, so the data block is sent over the
network.
3877 NCHAN_OUT LD IX,#1E3D Point to start of channel.
387B LD B,A
387C LD A,(IX+20)
387F AND A
3880 LD A,B
3881 JP NZ,#2946,REP_19 Give error if it is a 'read' channel.
3884 LD E,(IX+16) Fetch position of previous byte.
3887 INC E Include current byte.
3888 JR NZ,#3892,ST_BUF_POS Jump if the buffer isn't full.
388A PUSH AF
388B XOR A Signal normal packet type.
388C CALL #38B5,S_PACK_1 Send the packet.
388F POP AF
3890 LD E,1 Only 1 byte in buffer now.
3892 ST_BUF_POS LD (IX+16),E Store byte position.
3895 LD D,0
3897 ADD IX,DE Point to 'first free byte - 20'.
3899 LD (IX+20),A Store the byte.
389C RET
THE 'OUT_BLK_N' SUBROUTINE
This subroutine calls the 'OUTPAK' subroutine to send over the network the block of
bytes starting from (HL), and whose length is held in the E register. Then a 'response
byte' is to be received (provided there isn't broadcasted). The Zero flag is returned
reset if no response byte has been received. This subroutine is called from 'SEND_PACK'
below to send the header and then the data block over the network.
389D OUT_BLK_N CALL #3ABC,OUTPAK Send the block.
38A0 LD A,(IX+11)
38A3 AND A
38A4 RET Z Return if broadcasting.
38A5 LD HL,#1DF4 Address of store for network response
38A8 LD (HL),0 code.
38AA LD E,1 A single byte is to be received.
38AC CALL #3A87,INPAK Get response byte.
38AF RET NZ Return if the network was inactive.
38B0 LD A,(#1DF4)
38B3 DEC A The response byte must be 1.
38B4 RET Return with NZ if it wasn't.
THE 'S_PACK_1' SUBROUTINE
This subroutine simply calls 'SEND_PACK' below. If broadcasting, a certain delay is to
be inserted after having sent the packet.
38B5 S_PACK_1 CALL #38BC,SEND_PACK Send the packet.
38B8 RET NZ Return if not broadcasting.
38B9 JP #3915,BR_DELAY Otherwise return via the delay routine.
THE 'SEND_PACK' SUBROUTINE
This subroutine sends over the network a SCOUT leader, followed by the header and the
data block for the "n" channel. On entry, the A register may hold 1 or 0 depending on
whether the block is the 'end of file' one or not. The block number (IX+13,14) is
incremented before returning. The Zero flag is returned set if 'broadcasting' is being
used.
38BC SEND_PACK LD (IX+15),A Store packet type, i.e. #00 for normal,
#01 for end of file.
38BF LD B,(IX+16) Fetch block length.
38C2 CALL #3AF1,NET_BORD Set border, store IFF and DI.
38C5 PUSH IX Make DE point to the start of the
38C7 POP DE "n" channel.
38C8 LD HL,21 Offset to the 255 byte buffer.
38CB ADD HL,DE
Now the checksum of the data block is calculated.
38CC XOR A Clear checksum.
38CD CHKS1 ADD A,(HL) Add this byte.
38CE INC HL Next byte.
38CF DJNZ #38CD,CHKS1 Repeat for all bytes in the block.
38D1 LD (IX+17),A Store the obtained checksum.
38D4 LD HL,11 Now point to the location where the
38D7 ADD HL,DE destination station number is held.
38D8 PUSH HL
The checksum of the header is calculated.
38D9 LD B,7 Checksum is for 7 bytes.
38DB XOR A Clear checksum.
38DC CHKS2 ADD A,(HL) Add this byte.
38DD INC HL Next byte.
38DE DJNZ #38DC,CHKS2 Repeat for all header bytes.
38E0 LD (HL),A Store the checksum.
38E1 SENDSCOUT CALL #3A4A,SEND_SC Send the SCOUT i.e. a leader followed
by the station number.
38E4 POP HL Restore pointer to start of header
38E5 PUSH HL block.
38E6 LD E,8 The header consists of '8' bytes.
38E8 CALL #389D,OUT_BLK_N The header is sent, and the response
code received.
38EB JR NZ,#38E1,SENDSCOUT Repeat until successfull.
38ED PUSH IX Make HL point to the start of the
38EF POP HL "n" channel.
38F0 LD DE,21
38F3 ADD HL,DE Point to the start of the data block.
38F4 LD E,(IX+16) Get block length.
38F7 LD A,E
38F8 AND A If the buffer is empty; no data needs
38F9 JR Z,#3904,INC_BLKN to be sent.
38FB LD B,32 Wait 418 T cycles before proceeding.
38FD SP_DL_1 DJNZ #38FD,SP_DL_1
Now the data block is sent and the block number incremented.
38FF CALL #389D,OUT_BLK_N Send the data block, receive response.
3902 JR NZ,#38E1,SENDSCOUT Repeat until successfull.
3904 INC_BLKN INC (IX+13) Increment low byte of block number.
3907 JR NZ,#390C,SP_N_END The high byte of block number is only
3909 INC (IX+14) incremented when necessary.
390C SP_N_END POP HL Restore pointer to start of header.
390D CALL #3B02,REST_BORD Restore border and interrupt status.
3910 LD A,(IX+11) Get destination station number.
3913 AND A
3914 RET Return with Zero set if broadcasting.
THE 'BR_DELAY' SUBROUTINE
This short subroutine inserts a delay of about 40 msec. when it is called. Its task
is that of separating outputs during broadcast transmissions.
3915 BR_DELAY LD DE,5376 This costs 139791 T states including
3918 DL_LOOP DEC DE the RET instruction. The 3.5 MHz Z80 in
3919 LD A,E the Spectrum takes 39.94 msec to
391A OR D complete this subroutine.
391B JR NZ,#3918,DL_LOOP
391D RET
THE 'GET A HEADER & DATA BLOCK' ROUTINES
The following two subroutines are used to get from the network an 8-byte header and a
data block respectively. Both require that the IX register points to the start of the
"n" channel. The Zero flag is returned reset with any error.
391E GET_NBLK LD HL,#1DF5 Point to the first byte of the header.
3921 LD E,8 A header is 8 bytes long.
3923 CALL #3A87,INPAK Receive the header.
3926 RET NZ Return when no header received.
3927 LD HL,#1DF5 Restore pointer.
Now the header checksum is calculated, and compared with the received checksum.
392A XOR A First clear the checksum.
392B LD B,7 Length of header (without checksum).
392D CHKS3 ADD A,(HL) Add this byte.
392E INC HL Next byte.
392F DJNZ #392D,CHKS3 Repeat for all bytes.
3931 CP (HL) Compare with received checksum.
3932 RET NZ Return if they don't match.
Now some tests are being made: Is the block for this Spectrum, is it from the right
Spectrum and is it the right block?
3933 LD A,(#1DF5) Fetch destination station number.
3936 AND A
3937 JR Z,#3946,BRCAST Jump if broadcasting.
3939 CP (IX+12) Otherwise compare with own station
393C RET NZ number, return if for another Spectrum.
393D LD A,(#1DF6) Source station number.
3940 CP (IX+11) Return if the transmitting Spectrum is
3943 RET NZ not the required one.
3944 JR #394B,TEST_BLKN
3946 BRCAST LD A,(IX+11)
3949 OR A Return if this station is not waiting
394A RET NZ for a broadcast.
394B TEST_BLKN LD HL,(#1DF7) Fetch number of block being
394E LD E,(IX+13) transmitted, fetch number of expected
3951 LD D,(IX+14) block.
3954 AND A
3955 SBC HL,DE Jump if the block being transmitted is
3957 JR Z,#396B,GET_NBUFF the expected one.
3959 DEC HL Accept also the previous block (already
395A LD A,H received, but 'response' has not
395B OR L reached transmitter).
395C RET NZ But refuse other blocks.
395D CALL #396B,GET_NBUFF Receive the block.
3960 DEC (IX+13) Decrease block number, i.e. 'ignore'
3963 JR NC,#3968,GETNB_END this block.
3965 DEC (IX+14)
3968 GETNB_END OR 1 Return with Zero flag reset, so that
396A RET the procedure is repeated.
Now follows the second routine, used to get the data block from the network.
396B GET_NBUFF LD A,(#1DF5)
396E AND A Send the 'response' code for the header
396F CALL NZ,#3AB5,SEND_RESP unless broadcasting.
3972 LD A,(#1DFA) Fetch data block length.
3975 AND A
3976 JR Z,#3999,STORE_LEN Jump if the data block is empty.
3978 PUSH IX Make HL point to the start of the
397A POP HL channel.
397B LD DE,21
397E ADD HL,DE Point to the start of the data buffer.
397F PUSH HL
3980 LD E,A E is holds the length.
3981 CALL #3A87,INPAK Receive the data block.
3984 POP HL
3985 RET NZ Return if the network was inactive.
3986 LD A,(#1DFA) Load the loop variable with the length
3989 LD B,A of the received block.
398A LD A,(#1DFB) Fetch checksum of received block.
398D CHKS4 SUB (HL) Subtract current byte.
398E INC HL Point to next byte.
398F DJNZ #398D,CHKS4 repeat for all bytes in the block.
3991 RET NZ Return if the checksum is wrong.
3992 LD A,(#1DF5)
3995 AND A Send the 'response' code for the data
3996 CALL NZ,#3AB5,SEND_RESP block, unless broadcasting.
3999 STORE_LEN LD A,(#1DFA) Fetch data block length.
399C LD (IX+20),A Store number of bytes in input buffer.
399F INC (IX+13) Increment block number.
39A2 JR NZ,#39A7,GETBF_END
39A4 INC (IX+14)
39A7 GETBF_END CP A Return with Zero flag set to signal
39A8 RET 'block successfully received'.
THE 'OPEN "N" CHANNEL' ROUTINE
The DISCiPLE doesn't support "n" channel use from BASIC. This routine creates a "n"
channel in the DISCiPLE's own RAM. The channel is used for network serving purposes.
39A9 OPEN_N LD A,(#1DDA) Clear network bit of current control
39AC AND #7F port state.
39AE LD (#1DDA),A
39B1 LD DE,#1E3D Start of the channel area.
39B4 LD HL,#39D4,N_CH_DATA Start of "n" channel data.
39B7 LD BC,11 Copy the 11 bytes channel data to the
39BA LDIR channel area.
39BC LD A,(#1E01) Fetch destination station number.
39BF LD (DE),A
39C0 INC DE
39C1 LD A,(#029C) Fetch own station number from NSTAT.
39C4 LD (DE),A
39C5 INC DE
39C6 XOR A
39C7 LD (DE),A Clear the remaining 262 bytes.
39C8 LD H,D
39C9 LD L,E
39CA INC DE
39CB LD BC,262
39CE LDIR
39D0 LD DE,#1E3D Point to the start of the channel.
39D3 RET
THE '"N" CHANNEL DATA' TABLE
The '11' bytes that compose the initial part of a "N" channel are as follows:
39D4 N_CH_DATA DEFW #0008 Main ROM 'output' routine.
39D6 DEFW #0008 Main ROM 'input' routine.
39D8 DEFB "N" Channel specifier.
39D9 DEFW #3877 DISCiPLE ROM 'output' routine.
39DB DEFW #3819 DISCiPLE ROM 'input' routine.
39DD DEFW 276 Length of channel.
THE 'SEND EOF BLOCK' SUBROUTINE
This subroutine is used whenever the remaining buffer contents of the "n" channel have
to be sent as the "end of file" block.
39DF SEND_NEOF LD IX,#1E3D Start of channel.
39E3 LD A,(IX+16) Fetch data block length.
39E6 AND A
39E7 RET Z Return if this is a 'read' channel.
39E8 LD A,#01 Signal 'EOF packet'.
39EA JP #38B5,S_PACK_1 Send packet and exit.
THE 'NETWORK STATE' SUBROUTINE
This subroutine returns when the network is considered to be 'resting', i.e. when the
network line is inactive for 3-4 ms. The exact time is 'randomised' to prevent
Spectrums from claiming the network at the same time over and over again.
39ED NET_STATE LD A,R Get a 'random' value.
39EF OR #C0 Allow only the range 192..255.
39F1 LD B,A Pass it to the loop count variable.
39F2 CALL #39F8,CHK_REST Check network state.
39F5 JR C,#39ED,NET_STATE Repeat until the network is resting, or
SPACE is pressed.
39F7 RET Return when 'ready to claim'.
THE 'CHECK_RESTING' SUBROUTINE
This subroutine checks the state of the network and returns with carry reset if it is
inactive for a 'sufficient' time determined by the value passed in the B register
((B * 54) - 22) T cycles).
39F8 CHK_REST LD A,#7F First check SPACE key.
39FA IN A,(254)
39FC RRCA
39FD JR NC,#3A39,NET_BREAK Give an error if it is pressed.
39FF MAKESURE PUSH BC Wait 21 T cycles.
3A00 POP BC
3A01 IN A,(31) Check network state.
3A03 CPL Invert the bits.
3A04 RLCA Only bit 7. Return if the network is
3A05 RET C already claimed by another Spectrum.
3A06 DJNZ #39FF,MAKESURE Repeat the test.
3A08 RET Return with Carry reset when network is
resting.
THE 'WAIT_SCOUT' SUBROUTINE
This subroutine is used to identify a SCOUT leader from the network. This is done by
checking the network line for about 7000 T cycles, to prove whether it is resting.
After this, the network is examined until it is active. At this point, the SCOUT is
identified. The subroutine returns with the Carry flag reset if 'time-out' has
occurred and no SCOUT has been identified. Remember that there are no 'time-outs' when
broadcasting.
3A09 WT_SCOUT LD HL,450 Set a counter.
3A0C CLAIMED LD B,128 This constant allows the network to be
tested for 6890 T cycles.
3A0E CALL #39F8,CHK_REST Check network state.
3A11 JR NC,#3A20,WT_SYNC Jump for waiting the SCOUT.
3A13 DEC HL Loop again if the network is active,
3A14 DEC HL until the counter reaches zero.
3A15 LD A,H
3A16 OR L
3A17 JR NZ,#3A0C,CLAIMED
3A19 LD A,(IX+11) There is no 'time-out' when
3A1C AND A broadcasting.
3A1D JR Z,#3A0C,CLAIMED
3A1F RET Carry set signals 'time-out'.
Now the SCOUT pulse is waited for.
3A20 WT_SYNC IN A,(31) Read the network line.
3A22 CPL Invert the bits.
3A23 RLCA Only bit 7.
3A24 JR C,#3A3F,SCOUT_END Jump if the SCOUT is identified.
3A26 LD A,#7F Check the SPACE key.
3A28 IN A,(254)
3A2A RRCA
3A2B JR NC,#3A39,NET_BREAK Give an error if it is pressed.
3A2D DEC HL Decrease counter.
3A2E LD A,H
3A2F OR L
3A30 JR NZ,#3A20,WT_SYNC Repeat until it reaches zero.
3A32 LD A,(IX+11)
3A35 AND A Again there is no 'time-out' when
3A36 JR Z,#3A20,WT_SYNC broadcasting.
3A38 RET Carry reset signals 'time-out'.
THE 'NETWORK BREAK' ROUTINE
Whenever the SPACE key is pressed during a network operation, the 'BREAK requested'
error is given.
3A39 NET_BREAK CALL #3B02,REST_BORD Restore border colour.
3A3C JP #2926,REP_3 Give the error.
THE 'WAIT SCOUT' SUBROUTINE CONTINUED
When a SCOUT has been identified, the routine waits until it is finished.
3A3F SCOUT_END LD L,9 Set a counter.
3A41 LP_SCOUT DEC L Decrease it.
3A42 SCF Return with Carry set (to signal
3A43 RET Z 'SCOUT identified') when the counter
3A44 LD B,14 reaches zero.
3A46 DELAY_SC DJNZ #3A46,DELAY_SC Wait a while.
3A48 JR #3A41,LP_SCOUT Go back into the loop.
THE 'SEND_SCOUT' SUBROUTINE
This is the opposite of the preceding routine; the SCOUT leader followed by an 8-bit
station number, is sent over the network. After having sent every bit, a test is made
to see if the network has the expected state from the current bit value; if any error
is found, then the whole procedure is repeated.
3A4A SEND_SC CALL #39ED,NET_STATE Wait until the network is resting.
3A4D LD C,31 Control port.
3A4F LD A,(#1DDA) Fetch current state of control port.
3A52 OR #80 Set network bit.
3A54 LD H,A H holds port 31 value.
3A55 LD L,9 Bit counter.
3A57 LD A,(#029C) Fetch own station number from NSTAT.
3A5A CPL Invert the bits.
3A5B LD E,A
3A5C IN A,(31)
3A5E RLCA Start again if some data is found on
3A5F JR NC,#3A4A,SEND_SC the network line.
3A61 ALL_BITS OUT (C),H Send a bit.
3A63 LD D,0
3A65 RL H Save the bit in D.
3A67 RR D
3A69 RLC E Rotate 'station number' left.
3A6B RR H Bit 7 of station number goes into bit 7
of H.
3A6D LD B,7 Wait 93 T cycles.
3A6F S_SC_DEL DJNZ #3A6F,S_SC_DEL
3A71 IN A,(31) Read the network.
3A73 AND #80 Only bit 7.
3A75 CP D Repeat again the procedure if the
3A76 JR Z,#3A4A,SEND_SC network does not have the right state
from the current bit value.
3A78 DEC L Decrease bit counter.
3A79 JR NZ,#3A61,ALL_BITS Send all bits.
3A7B LD A,(#1DDA) Make network inactive.
3A7E OUT (31),A
3A80 LD A,1
3A82 LD B,13 Wait 171 T cycles before returning.
3A84 END_S_DEL DJNZ #3A84,END_S_DEL
3A86 RET
THE 'INPAK' SUBROUTINE
This basic subroutine is used to receive from the network a block of bytes. On entry,
HL must hold the address from which the bytes will be loaded, while E must hold the
length of the block. The subroutine returns with the Zero flag reset if the network is
found inactive and no data has been read. The bits are read every 40 T cycles.
3A87 INPAK LD B,255 Set a counter.
3A89 N_ACTIVE IN A,(31) Read the network.
3A8B RLA Only bit 7.
3A8C JR NC,#3A92,INPAK_2 Jump if found active.
3A8E DJNZ #3A89,N_ACTIVE Otherwise try again.
3A90 INC B Return with Zero flag reset to indicate
3A91 RET 'network inactive'.
Now the block is received.
3A92 INPAK_2 LD B,E B holds the length of the block.
3A93 LD A,0 Balance the CPL instruction below.
3A95 INPAK_L LD E,#80 Set a marker into bit 7.
3A97 OUT (59),A Set NET-WAIT line. (WAIT if NET=1)
3A99 NOP Wait 48 T cycles at the start of each
3A9A NOP byte.
3A9B INC IX
3A9D DEC IX
3A9F INC IX
3AA1 DEC IX
3AA3 UNTIL_MK LD A,0 Wait 7 T cycles.
3AA5 IN A,(31) Get a bit into the
3AA7 RLA Carry flag.
3AA8 RR E Shift the bit into E.
3AAA JP NC,#3AA3,UNTIL_MK Repeat for 8 bits.
3AAD LD A,E Because of the inverting port in the
3AAE CPL DISCiPLE the byte has to be inverted.
3AAF LD (HL),A Store the received byte.
3AB0 INC HL Next location.
3AB1 DJNZ #3A95,INPAK_L Get next byte.
3AB3 CP A Return with Zero flag set to signal
3AB4 RET 'successfully read'.
THE 'SEND RESPONSE BYTE' SUBROUTINE
A 'response byte' is simply a byte 1 that is sent over the network to confirm that
some data has been successfully received.
3AB5 SEND_RESP LD A,1 This is the response byte.
3AB7 LD HL,#1DF4 Store it.
3ABA LD (HL),A
3ABB LD E,A A 'single byte' is to be sent.
The subroutine continues into 'OUTPAK' below.
THE 'OUTPAK' SUBROUTINE
This is the opposite to the 'INPAK' subroutine and thus, is used to send over the
network a block of bytes. Again, on entry HL must hold the address from which the
block is stored, and E must hold its length. Initially a leader (length 98 T cycles)
is sent, followed by each byte, with an initial 'start' period, and then the 8 bits
(each 40 T cycles).
3ABC OUTPAK LD A,(#1DDA) Reset network line of current state of
3ABF AND #7F control port.
3AC1 LD (#1DDA),A
3AC4 OR #80 Begin with a 'start' leader.
3AC6 OUT (31),A
3AC8 LD B,3 Insert the required delay.
3ACA DEL_O_1 DJNZ #3ACA,DEL_O_1
3ACC OUTPAK_L LD C,(HL) C holds the byte to be sent.
3ACD INC HL Next location.
3ACE AND #7F The start bit is low (high on net).
3AD0 LD B,9 '9' bits to be sent (start, data).
3AD2 JR #3AD8,UNT_MARK_2 Send start bit.
Now a byte is send over the network.
3AD4 UNT_MARK_1 RLA Rotate bit into A while keeping the
3AD5 SRL C other control bits intact.
3AD7 RRA
3AD8 UNT_MARK_2 OUT (31),A Send the bit.
3ADA DJNZ #3AD4,UNT_MARK_1 Loop for all bits.
3ADC RLA
3ADD SCF The stop bit is high (low on net).
3ADE RET NC Wait 5 T cycles
3ADF RR A Extra 4 T cycles (RRA is 4, RR A is 8).
3AE1 OUT (31),A Send the stop bit.
3AE3 PUSH HL Wait 44 T cycles.
3AE4 POP HL
3AE5 PUSH HL
3AE6 POP HL
3AE7 DEC E Decrease block length.
3AE8 JP NZ,#3ACC,OUTPAK_L Loop until all bytes have been sent.
3AEB LD A,(#1DDA)
3AEE OUT (31),A Make the network inactive before
3AF0 RET returning.
THE 'NET_BORDER' SUBROUTINE
This subroutine sets the border colour at "station MOD 8" and stores the state of
the IFF at address #1ACC. It returns with the interrupts disabled.
3AF1 NET_BORD LD A,(#029C) Fetch own station number from NSTAT.
3AF4 AND #07 Keep only bits 0-2.
3AF6 OUT (254),A Set border colour.
3AF8 LD A,I Obtain interrupt status.
3AFA PUSH AF
3AFB EX (SP),HL Move it to HL and
3AFC LD (#1ACC),HL store it into IFF.
3AFF POP HL Restore HL.
3B00 DI Exit with interrupts disabled.
3B01 RET
THE 'RESTORE BORDER COLOUR' SUBROUTINE
This is the opposite to the 'NET_BORD' subroutine and thus, is used to restore the
BORDER colour and the state of the IFF. Note that because of a bug in the Z80 itself
the interrupts can be disabled although they were enabled when the "LD A,I" above was
executed. (See NOTE before #3ECE.)
3B02 REST_BORD LD A,(23624) Get BORDCR (lower screen attribute).
3B05 AND #38 Only the BORDER bits.
3B07 RRCA Rotate colour into bits 0-2.
3B08 RRCA
3B09 RRCA
3B0A OUT (254),A Restore colour.
3B0C PUSH HL
3B0D LD HL,(#1ACC) Fetch previous state of the IFF.
3B10 EX (SP),HL
3B11 POP AF
3B12 JP PO,#3B16,R_B_EXIT Jump if interrupts were disabled.
3B15 EI Otherwise enable interrupts.
3B16 R_B_EXIT RET Exit.