ASSEMBLY LANGUAGE - WEEK III					November 9, 1986


VIDEO ROUTINES

The Z-80 must communicate with other devices:
		Screen (Video output)
		Keyboard
		Printer
		Other I/O ports:
			Joystick
			RS-232
			Hard Disk
			Floppy Disk
			Cassette Tape Recorder

In the TRS-80, the screen display is hardware specific. The memory locations starting at 3C00H are output (displayed) directly to the video screen.

One other memory location that we must keep in mind are the two bytes located at 4020H and 4021H. These two bytes store the current cursor position. The Least Significant Byte of the current cursor position is located at 4020H. The Most Significant Byte of the current cursor position is located at 4021H.

We will use other video routines that are located in ROM. the three that we will work with today are:

0033H - Loads DE with address of Video DCB (Device Control Block) and displays character stored in A at the current cursor position.

01C9H - Clears the screen and homes the cursor

021BH - (Model III only) - a video line display routine. Displays the text starting at address in HL. The text must be terminated by a carriage return (0DH) which is printed , or by an (03H) which is not printed.
Uses the HL, DE, and AF registers.

The purpose of the following series of exercises will be to instruct the computer to display a message we have stored in memory on the screen. We will start out with the simple video routine at 33H, work our way up to using the display message routine at 021BH. We will use DEBUG to enter the ML code into memory. To help us understand what the code is trying to do, I have placed the mnemonic instructions on the left. DEBUG just needs the hexadecimal code on the right.


Start at memory location 7003H
		
		OUTC		EQU	0033H
		START	LD	HL, MSG		21 40 70
		LOOP		LD	A,(HL)		7E
				CALL OUTC			CD 33 00
				INC	HL			23
				LD	A,(HL)		7E
				CP	0DH			FE L0D
				JP	NZ, LOOP		C2 06 70

Now we have to store a message at 7040H

Using an ASCII table, we can list the hexadecimal equivalents of Alphabetic characters. There is an ASCII table in your Model I or your Model III manual.

		MSG		DEFM	"HELLO THERE!"
					48 45 4C 4C 4F 20 54 48 45 52 45 21
				DEFB	0D
					0D

If we try to run this program, we won't see anything on the Model III screen. That is because DEBUG refreshes the screen before we can see our message. We have to add a scan keyboard routine so DEBUG waits until we press a special character :

Add the following code at 7080H:
	
		CHKIO	EQU	002BH
		HOLD		CALL	CHKIO	CD 2B 00
				JP	Z,HOLD	CA 80 70
				CP	40H		FE 40
				JP 	NZ,HOLD	C2 80 70

Now we have to jump to 7080H from our main display program. Add the following code to the end of the program.

				JP	HOLD		C3 80 70

Now check the program by jumping 50 7003, with a breakpoint at 708B. Press the @ key to return to DEBUG.

How would we clear the screen before displaying our message?

Add the following code at 7000H:
		
		CLS		EQU	01C9H
				CALL	CLS		CD C9 01

Run the program by jumping to 7000H, breakpoint at 708B.

Now we can save ourselves some code writing by using the message output routine at 012Bh.

Let's use our original program, and write the revision, changing all the bytes of code we no longer need to 00H (NOP's). The computer will "do nothing" when it sees a NOP, and just proceed to the next instruction.

Our program should look like:

		CLS		CALL	CLS		CD C9 01
		START	LD	HL,MSG	21 40 70
				CALL DISPLAY	CD 1B 02
				NOP			00
				NOP			00
				NOP			00
				NOP			00
				NOP			00
				NOP			00
				NOP			00
				NOP			00
				JP	HOLD		C3 80 70

Now what if we wanted to display a message at a particular place on the screen? If we wanted to use these two ROM screen display routines, we would have to put the location where we wanted the message to start in memory locations 4020H and 4021H (the current cursor position)

For instance, if we wanted to display the message at the center of the screen, we could have the message start at screen location 3dd8H, we could write:

				CALL CLS			CD C9 01
				LD 	HL,MSG		21 70 40
				LD	DE, 3DD8H		11 D8 3D
				LD 	(4020),DE		ED 52 20 40
				CALL	021BH		CD 1B 02
				JP 	HOLD			C3 80 70

What if we want to put the message at more than one place on the screen? How about at each corner and the center. Hmmm..we can store the message start locations at 7050 - they would be:
			3C45H
			3665H
			3DD8H
			3F85H
			3FA5H

Remember to store them LSB, MSB. We can use the B register to store our count. The DJNZ instruction with the relative jump displacement will keep track of our count quite nicely. We can use the HL register to store the memory location of our screen message start. The screen display start location will be moved into DE, and then stored at 4020H and 4021H. However, the message out routine uses the register pair HL. Therefore, before we call the message out routine, we have to save the value we have stored (actually a pointer to a memory location) by PUSHing the contents of the HL register pair onto the stack, and then POPing the contents from the stack back into the register pair HL. Always make sure you PUSH and POP as a pair. Try the following routine:

		START	EQU	7000H
		CLEAR	CALL	CLS			CD C9 01
				LD	B,05H		06 05
				LD   HL,7050H		21 50 70
				LD	E,(HL)		5E
				INC	HL			23
				LD	D,(HL)		56
				INC	HL			23
				PUSH HL			E5
				LD	(4020),DE		ED 53 20 40
				LD	HL,MSG		21 40 70
				CALL 021BH		CD 1B 02
				POP	HL			E1
				DJNZ $-18			10 EE
				JP	HOLD			C3 80 70

Place the following screen addresses @ 7050:

				DEFW	3C45H		45 3C
				DEFW	3C65H		65 3C
				DEFW	3DD8H		D8 3D
				DEFW	3F85H		85 3F
				DEFW	3FA5H		A5 3F


QUESTIONS:

Could the screen address been put directly into locations 4020 and 4021? Would it have saved any instructions steps?

Why must I load the MSG address into HL every time?

                                                                                                                                                                       