;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		zChat v1.2		;
;Platform:	MirageOS (TI-83+)	;
;Author:	Paul Marks		;
;E-Mail:	paul248@techie.com	;
;AIM:		Paul26400		;
;Website:	http://paul248.cjb.net	;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

#include	"ti83plus.inc"			;General TI-83 Plus include file
#include	"mirage.inc"			;MirageOS include file

locRow		= SafeRam1	;Local Row
locCol		= locRow+$01	;Local Column
locChar		= locCol+$01	;Local Character
locString	= locChar+$01	;Local String

remRow		= locString+$31 ;Remote Row
remCol		= remRow+$01	;Remote Column
remChar		= remCol+$01	;Remote Character
remString	= remChar+$01	;Remote String

ptrRow		= remString+$31	;Pointer To Local/Remote Row
ptrString	= ptrRow+$02	;Pointer To Local/Remote String
ptrChar		= ptrString+$02	;Pointer To Local/Remote Character

chrLink		= ptrChar+$02	;Last Value Of The Link Icon

chrBlank	= ' '
chrCursor	= '_'

chrLink1	= $5C	;Solid Line
chrLink0	= $EE	;Dotted Line

Qit		= $80	;Quit Key
Clr		= $81	;Clear Key
Del		= $82	;Delete Key
Ent		= $83	;Enter Key
Alp		= $84	;Alpha Key


	.org	$9d93				;Origin (set back two to account for AsmPrgm)
	.db	$BB,$6D				;Compiled AsmPrgm token
	ret					;So TIOS wont run the program
	.db	1				;Identifier as MirageOS program
	.db	%00000000,%00000000
	.db	%01111100,%01111100
	.db	%01000100,%01000100
	.db	%01000100,%01000100
	.db	%01111100,%01111100
	.db	%01010100,%01010100
	.db	%01101100,%01101100
	.db	%01010100,%01010100
	.db	%01111100,%01111100
	.db	%00010000,%00010000
	.db	%00100111,%11001000
	.db	%01000100,%10000100
	.db	%00110001,%00010100
	.db	%00000010,%01001000
	.db	%00000111,%11000000
	.db	"zChat v1.2 by Paul Marks",0		;Zero terminated description

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		Initialization
;Action:	Sets variables to defaults.
;		Draws the chat area.
;		Draws the chrCursor
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	ld	a,Ent
	ld	(locChar),a

	call	PointToLocal
	call	BlankOut
	call	PointToRemote
	call	BlankOut

	bcall(_ClrLCDFull)
	call	PutCursor
	
	ld	a,3		;Put Checkered Boxes In 4th Row
	call	DrawLine
	
	ld	a,7
	call	DrawLine	;Put Checkered Boxes In 4th Row
	
	ld	hl,$0107
	ld	(curRow),hl
	ld	hl,LinkText
	bcall(_PutS)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		Main Routine
;Action:	Gets a letter, sends it out the link port,
;		displays it on the screen, moves the chrCursor,
;		Reads the linkport, displays remote character
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

MainLoop:
	ld	hl,NormalTable
	call	GetLetter

	ld	a,c
	cp	Qit		;Exit If Mode[Quit] was pressed
	ret	z

	ld	hl,locChar
	ld	a,(hl)		;a=the old character
	ld	(hl),c		;c=the new character
	cp	c
	jr	z,SendZero	;don't display if char is the same as the last char

	ld	a,c
	or	a
	jr	z,SendZero	;don't display if char is zero

	call	SendByteTiOS	;Sends the character
	jr	nz,NoLocalChar	;don't display Character if it couldn't be sent

	call	PointToLocal
	ld	b,0	;String Row

	call	ShowChar
	call	PutCursor
NoLocalChar:

	call	GetByteTiOS	;Get a byte from the linkport
	jr	nz,ShowNoLink	;If byte couldn't be received, Show the Broken Link Icon

	ld	b,chrLink1	;Otherwise, show the Connected Icon
	call	ShowLink

	or	a		;cp 0
	jr	z,NoRemoteChar	;Don't display a character 0
	ld	(remChar),a

	call	PointToRemote
	ld	b,4	;String Row

	call	ShowChar	;Put the character on the screen
NoRemoteChar:
	jr	MainLoop

SendZero:			;Sends a 0 out the linkport
	xor	a	;ld a,0
	call	SendByteTiOS
	jr	NoLocalChar

ShowNoLink:
	ld	b,chrLink0	;Shows the broken link icon
	call	ShowLink
	jr	NoRemoteChar
	
ShowLink:
	ld	d,a
	ld	a,(chrLink)
	cp	b
	call	nz,ShowLink2	;Displays icon if it's diffent from what's already there
	ld	a,d
	ret
ShowLink2:
	ld	hl,$0607
	ld	(curRow),hl
	ld	a,b
	bcall(_PutC)
	ld	(chrLink),a
	ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		Show Character
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Inputs:	b=Row To Put String On
;		ptrRow=Pointer to variable with current row
;		ptrChar=Pointer to variable with character to display
;		ptrString=Pointer to Remote/Local text
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Output:	Puts The Character On The Screen
;Destroys:	a,b,c,d,e,h,l
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ShowChar:
	ld	a,b		;Sets chrCursor Location To (B,0)
	ld	(curRow),a
	xor	a		;like ld a,0
	ld	(curCol),a
	
	ld	hl,(ptrRow)
	ld	b,(hl)	;b=remRow
	inc	hl
	ld	c,(hl)	;c=remCol

	call	FindPosition

	ld	de,(ptrChar)
	ld	a,(de)

	cp	Ent
	jr	z,EnterPressed

	cp	Del
	jr	z,DeletePressed

	cp	Clr
	jr	z,ClearPressed

	ld	(hl),a	;Add Current Character To String//

	call	NextCharPosition

ShowString:
	ld	hl,(ptrString)
	bcall(_PutS)

	ld	hl,(ptrRow)	;
	ld	(hl),b		;
	inc	hl		;
	ld	(hl),c		;load stuff back into ram
	ret

EnterPressed:
	call	NextLine
	jr	ShowString

ClearPressed:
	call	BlankOut
	jr	ShowString

DeletePressed:
	ld	a,c
	or	a
	call	z,PrevLine
	dec	c

	call	FindPosition
	ld	(hl),chrBlank
	jr	ShowString
PrevLine:
	inc	c		;Move chrCursor right one in case you're off the top left
	ld	a,b
	or	a
	ret	z		;Don't move up if already at the top

	dec	b		;Decrement Row
	ld	c,16		;Move chrCursor to the right
	ret


NextCharPosition:
	inc	c	;move to next column
	ld	a,c
	cp	16	;check to see if you're off the right edge
	call	z,NextLine	;move down
	ret

NextLine:			;Moves Down A Line
	inc	b		;Increment Row
	ld	c,0		;Move To Left

	ld	a,b
	cp	3	
	jr	z,ShiftUp	;Call ShiftUp If At The Bottom
	ret

ShiftUp:
	ld	hl,(ptrString)
	ld	de,16
	add	hl,de
	ld	de,(ptrString)
	ld	bc,32
	ldir			;Moves Lines 2 and 3 -> 1 and 2
	
	ld	h,d
	ld	l,e
	inc	de
	ld	bc,15
	ld	(hl),chrBlank	;Fills Line 3 With chrBlanks
	ldir
	
	ld	bc,$0200	;Move To The Left Of The Bottom
	ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		Find Position
;Inputs:	b=row / c=column
;		ptrString=Pointer To Remote Or Local Text
;Output:	hl=Memory Location of current character
;Destroys:	a,d,e,h,l
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FindPosition:		;converts b(row) and c(col) to de(position)
	ld	hl,(ptrString)

	ld	a,b	;a=b

	add	a,a	;
	add	a,a	;
	add	a,a	;
	add	a,a	;a*=16
	add	a,c	;a+=c

	ld	d,0	;
	ld	e,a	;de=a
	add 	hl,de	;add position to beginning of string
	ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		Get Letter
;Input:		Keypad
;Output:	c=Letter
;Destroys:	a,b,c,d,e,h,l
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
GetLetter:
	ld	d,(hl)
	inc	hl
ReadKeyPad:
	ld	a,$FF
	out	(1),a
	ld	a,(hl)		;Send Key Group's Value To Keypad
	out	(1),a
	in	a,(1)		;Retrieves Key Group State

	ld	bc,$0800

FindOffBit:
	rrca			;Circulate until the off bit is found
	cp	%01111111	;
	jr	z,SetLetter	;
	djnz	FindOffBit	;

	dec	d
	ld	a,d
	or	a
	ret	z
	
	ld	bc,9
	add	hl,bc
	jr	ReadKeyPad

SetLetter:
	ld	d,0
	ld	e,b
	add	hl,de
	ld	c,(hl)
	ld	a,c
	cp	Alp
	jr	z,GetShiftKey
	ret

GetShiftKey:
	ld	hl,ShiftTable
	jr	GetLetter

	
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		PutCursor
;Inputs:	b=Row, c=Column
;Action:	Puts the chrCursor at (b,c)
;Destroys:	a,b,c,h,l
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PutCursor:
	ld	hl,curRow
	ld	(hl),b
	inc	hl
	ld	(hl),c
	ld	a,chrCursor
	bcall(_PutC)
	ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		BlankOut
;Inputs:	ptrRow=Pointer to the location of the string on the screen
;		ptrString=Pointer to the string itself
;Action:	Clears the string and moves to the top left
;Destroys	b,c,d,e,h,l
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BlankOut:
	ld	hl,(ptrRow)
	ld	(hl),0
	inc	hl
	ld	(hl),0
	
	ld	hl,(ptrString)
	ld	d,h
	ld	e,l
	inc	de
	ld	bc,47
	ld	(hl),chrBlank
	ldir

	inc	hl
	ld	(hl),0
	ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		Set Pointers
;Input:		None
;Action:	Sets The Pointers To Either Local or Remote Variables
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PointToLocal:
	ld	hl,locRow
	ld	(ptrRow),hl
	ld	hl,locString
	ld	(ptrString),hl
	ld	hl,locChar
	ld	(ptrChar),hl
	ret
	
PointToRemote:
	ld	hl,remRow
	ld	(ptrRow),hl
	ld	hl,remString
	ld	(ptrString),hl
	ld	hl,remChar
	ld	(ptrChar),hl
	ret



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Name:		DrawLine
;Input:		a=Row
;Action:	Fills Row A With Checkered Boxes
;Destroys:	a,b
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DrawLine:
	ld	(curRow),a
	xor	a	;ld a,0
	ld	(curCol),a
	ld	a,$F1
	ld	b,16
DrawLineLoop:
	bcall(_PutC)
	djnz	DrawLineLoop
	ret
	

;;;;;;;;;;
;  Data  ;
;;;;;;;;;;

NormalTable:
	.db	6
	.db	$BF,Del,Qit,$00,$00,$00,$00,$00,$00
	.db	$DF,Alp,'A','D','I','N','S','X',$00
	.db	$EF,$00,'B','E','J','O','T','Y',' '
	.db	$F7,$00,'C','F','K','P','U','Z',':'
	.db	$FB,$00,$00,'G','L','Q','V','!','?'
	.db	$FD,$00,Clr,'H','M','R','W',$00,Ent
	
ShiftTable:
	.db	4
	.db	$EF,$00,$00,$00,$2C,'7','4','1','0'
	.db	$F7,$00,$00,$00,'(','8','5','2','.'
	.db	$FB,$00,$00,$00,')','9','6','3',$00
	.db	$FD,$00,Clr,'^','/','*','-','+',Ent
	
LinkText:
	.db	"Link",$C1,chrLink0,"]",0
.end
END