Created: 8th December 1999
Last Modified: 15th December 1999
Some games include multiplayer support using the linkport (Port 7). This page explains how to access the linkport and includes the ACZ ReceiveByte and SendByte routines.
Possibly the most obvious port on the ti86 is the linkport. This is in fact Port 7. I've skipped Ports 3 to 6 for a number of reasons. Port 3 doesn't do anything useful - it lets you read the ON key. Port 4's function is not widely known, and rarely useful. Ports 5 and 6 are very useful but I'll explain them later.
The linkport takes a 2.5mm male Stereo Jack. When you look at one of these you'll see three wires, code-named black, red and white. The diagram below shows which is which.
Turning wires on and off isn't as simple as you might think. The table below describes what happens depending on what you write to the link port. 'On' means the voltage between the black wire and the wire being tested is ~5 Volts and 'Off' means the voltage between the black wire and the wire being tested is ~0 Volts.
| Value Written | Red Wire | White Wire |
|---|---|---|
| %11111100 | Off | Off |
| %11101000 | On | Off |
| %11010100 | Off | On |
| %11000000 | On | On |
Reading the wires is even more complicated. You must first and the
value you get in with 3, then compare to the following table:
| Value Read | Red Wire | White Wire |
|---|---|---|
| 0 | Off | Off |
| 1 | On | Off |
| 2 | Off | On |
| 3 | On | On |
If you want to write a program that supports multiplayer you could use the linkport to enable multi-calculator communication. There are a few routines that do this, I've included the ACZ routines that were written by Pascal Bouron and Jimmy Mardell. I have resisted the urge to make these routines better (ie slightly optimised). Please don't ask me how these routines work - I haven't studied them in detail. I've left the original comments (?) in to help (???) you work out what's going on.
This routine sends a byte of information to another calculator. It takes one input - the a register contains the value to send. It destroys all registers and op1 (a floating point 'register'). The carry flag is set on exit if there has been an error.
;====================================================== ; SendByte [Assembly Coder's Zenith] ; Originally by Pascal Bouron and Jimmy Mardell ; ; in: A = byte to send ; out: carry set = error ; destroyed: all registers, OP1 ;====================================================== SendByte: ld hl,0 ld (_OP1),hl ld b,8 ld c,a ;byte to send ld a,$C0 out (7),a sbw_setport3: in a,(7) and 3 cp 3 jr z,sbcalc_bit call sbSendTest_ON jr sbw_setport3 sbcalc_bit: ld a,c and 1 jr z,sbsend_one sbsend_zero: ld a,$E8 out (7),A jr sbwait_setport sbsend_one: ld a,$D4 out (7),A sbwait_setport: call sbSendTest_ON in a,(7) and 3 jr nz,sbwait_setport ld a,$C0 out (7),A srl c djnz sbw_setport3 xor a ret sbSendTest_ON: ld a,%00111111 out (1),a nop nop in a,(1) bit 6,a ret nz pop hl ret
This routine returns in a a value sent by SendByte. It destroys all registers and op1. The carry flag will be set if there has been an error.
;====================================================== ; ReceiveByte [Assembly Coder's Zenith] ; Originally by Pascal Bouron and Jimmy Mardell ; ; out: A = received byte carry set = error ; destroyed: all registers, OP1 ;====================================================== ReceiveByte: ld hl,0 ld (_OP1),hl ld e,1 ; for the OR ld c,0 ; byte receive ld b,8 ; counter ld a,$c0 out (7),a rb_w_Start: in a,(7) and 3 cp 3 jr nz,rb_get_bit call rbTest_ON jr rb_w_Start rb_get_bit: cp 2 jr z,rb_receive_zero ld a,c or e ld c,a ld a,$D4 out (7),a jr rb_waitStop rb_receive_zero: ld a,$E8 out (7),a rb_waitStop: call rbTest_ON in a,(7) and 3 jr z,rb_waitStop ld a,$c0 out (7),a rl e djnz rb_w_Start ld a,c ret rbTest_ON: ld a,(_OP1) inc a ld (_OP1),a cp 255 ret nz pop hl xor a ret