	PAGE 60
	ENTRY PUTG,PUTGBD,PUTGDE,MULTAC,IARGT
	PUBLIC XMING,YMING,XMAXG,YMAXG
	.Z80
	.COMMENT #

PUTG(IX,IY,IP)

setzt das Grauwert-Pixel (IX,IY) auf den Grauwert IP (0..15).

		Die Koordinaten beginnen mit 1,1 (links oben!).
ACHTUNG!!	Die Pixel sind zwar mit x,y-Koordinaten anzugeben,
		aber y=1 ist oben und waechst nach unten.

Einsprung ueber Entry
- PUTG   mit Adresse von IX in HL, von IY in DE und von IP in BC.
- PUTGBD mit x in BC, y in DE und Grauwert in A.
	 In beiden Faellen gelten die Koordinaten bezgl. des Fensters
	 XMING <= x-1 <= XMAXG und YMING <= y-1 <= YMAXG.
	 Falls die Grenzen ueberschritten sind, wird kein Grauwert gesetzt.
- PUTGDE mit x in E, y in D und Grauwert in A
	 Hier werden absolute Schirmkoordinaten erwartet.
	 Die Grenzen werden nicht abgetestet.

	 Falls der Grauwert groesser als 15 ist, wird 15 gesetzt.

Die Grauwerte (0..15) sind als Punktmuster in der oberen Haelfte des 2.
Character-EPROM 2732 von Video80 abgelegt. Jeder Character enthaelt zwei
uebereinanderliegende Pixel, das untere Halb-Byte das obere Pixel und das
obere Halb-Byte das untere Pixel. Im unteren Halb-Byte werden alle Grauwerte 
von 0 bis 15 verwendet, im oberen nur die Grauwerte 0 bis 7. Damit ergeben 
sich 8x16=128 Pixel-Kombinationen (i.e. genau die 128 Zeichen der EPROM-
Haelfte). Um die hoeheren Grauwerte fuer die oberen Halb-Bytes darzustellen, 
muss das Zeichen invertiert werden (Attribut-Bit Nr.0 gesetzt). Dazu ist die 
Komplementierung beider Pixel-Werte noetig.

Die Byte-Position im Video-RAM wird wie folgt bestimmt:
x' = XMING+x-1
y' = YMING+y-1	y"=[y'/2]
DE = VRAMA + y"*COLS + x'		Attribut-Byte-Pos. im Video RAM
HL = COFFS + DE				Char.-Byte-Pos.

Falls y' mod 2 = 0, steht der Grauwert im unteren Halb-Byte von B,
falls y' mod 2 = 1, im oberen Halb-Byte von B.

Die globalen Variablen XMING,YMING und XMAXG,YMAXG enthalten die Grenzen
des momentanen Plott-Fensters. Ihr Wertebereich ist 0,0 bis 79,47.
Sie werden mit der Routine WINDWG gesetzt.

A.Herrmann	23.02.85
#
LINES	EQU 24		; Zeilen auf Bildschirm
COLS	EQU 80		; Spalten auf Bildschirm
VRAMA	EQU 0E000H	; Video RAM Adresse der Attribute
COFFS	EQU 00800H	; Offset zur Video RAM Adresse der Zeichen
VPORT	EQU 28H		; Video Port Adresse
GCS	EQU 12H		; Attribut fuer Grauwert-Zeichensatz
;
PUTG:	LD A,(BC)	; Grauwert in A
	LD C,(HL)
	INC HL
	LD B,(HL)
	DEC BC		; x-1 in BC
	EX DE,HL
	LD E,(HL)
	INC HL
	LD D,(HL)
	DEC E		; y-1 in DE
;
PUTGBD:	LD HL,(XMING)
	PUSH HL
	ADD HL,BC
	LD B,H
	LD C,L		; x' in BC
	POP HL
	SCF
	SBC HL,BC
	JP P,PUTG10	; x' < XMING ?
	LD HL,(XMAXG)
	SCF
	CCF
	SBC HL,BC
	JP C,PUTG10	; x' > XMAXG ?
	LD HL,(YMING)
	PUSH HL
	ADD HL,DE
	EX DE,HL	; y' in DE
	POP HL
	SCF
	SBC HL,DE
	JP P,PUTG10	; y' < YMING ?
	LD HL,(YMAXG)
	SCF
	CCF
	SBC HL,DE
	JP C,PUTG10	; y' > YMAXG ?
;
	LD D,E		; D=y'
	LD E,C		; E=x'
;
PUTGDE:	LD C,A
	LD B,15		; max.Grauwert=15
	SUB B
	LD A,C
	JR C,PUTG1	; Grauwert > 15 ?
 	LD A,B
PUTG1:	LD B,A
	BIT 0,D		; y' mod 2 = 0 ?
	PUSH AF		; Flags retten
	JR Z,PUTG2
	SLA B
	SLA B
	SLA B
	SLA B		; Grauwert ins richtige Halb-Byte
PUTG2:	SRL D		; D = y", E = x'
	LD A,D
	LD C,COLS
	CALL MULTAC	; HL = A*C
	LD D,0
	ADD HL,DE
	LD DE,VRAMA
	ADD HL,DE	; Attribut-Byte Adresse
	LD DE,COFFS
	EX DE,HL
	ADD HL,DE	; Character-Byte Adresse
	DI
	OUT (VPORT),A
	LD A,(DE)	; Lies Attribut Byte
	OUT (VPORT),A
	EI
	BIT 1,A		; Grauwert-Zeichen?
	JR Z,PUTG3
	BIT 4,A
	JR NZ,PUTG4
PUTG3:	XOR A		; Nein.
	LD C,A
	JR PUTG5
PUTG4:	BIT 0,A		; Ja, invertiertes Komplement
	DI
	OUT (VPORT),A
	LD C,(HL)	; des Zeichen-Byte ?
	OUT (VPORT),A
	EI
	JR Z,PUTG5
	LD A,0FFH
	SUB C		; Ja, komplementieren.
	LD C,A
PUTG5:	POP AF		; Anderes Halb-Byte 
	LD A,C		; wegmaskieren.
	JR Z,PUTG6
	AND 0FH
	JP PUTG7
PUTG6:	AND 0F0H
PUTG7:	OR B		; Halb-Byte dazu.
	BIT 7,A		; Komplement noetig?
	JR Z,PUTG8
	PUSH AF
	LD C,A		; Ja.
	LD A,0FFH
	SUB C
	LD C,A
	POP AF
	LD A,C
PUTG8:	DI
	OUT (VPORT),A
	LD (HL),A	; Schreibe Grauwert-Byte
	LD A,GCS
	JR Z,PUTG9	; Invertierungs-Bit noetig?
	INC A
PUTG9:	LD (DE),A	; Schreibe Attribut-Byte
	OUT (VPORT),A
	EI
PUTG10:	RET		; Exit
;
;
XMING:	DW 0		; min. und
XMAXG:	DW 79		; max. x-Koord.
YMING:	DW 0		; min. und
YMAXG:	DW 47		; max. y-Koord.
;
;
; Subroutine  MULTAC
; multipliziert den Akku mit Register C und liefert das Ergebnis in HL.
; (nach L.A.Leventhal Z80 Assembly Language Programming  p.8-11)
;
MULTAC:	PUSH BC
	PUSH DE
	LD E,A
	LD D,0
	LD A,C
	LD HL,0
	LD B,8
MULT:	ADD HL,HL
	RLA
	JR NC,CHCNT
	ADD HL,DE
CHCNT:	DJNZ MULT
	POP DE
	POP BC
	RET
;
;
; Subroutine IARGT
; besorgt den Transfer von Integer-Argumenten (je 2 Byte) fuer Subroutinen,
; die mehr als drei Parameter haben. Nach den Regeln von Microsoft-Compilern 
; werden diese durch Pointer in einem Parameterblock spezifiziert.
; 
; A	enthaelt die Anzahl der Integer-Argumente
; BC	zeigt auf den Block mit den Pointern auf die Argumente
; DE	enthaelt die Adresse vom LowByte des 1.Arguments
;
; Die Argumentwerte werden in aufeinanderfolgende Worte geschrieben.
;
IARGT:	LD H,B		; Pointer auf Par'block
	LD L,C
IARGT1:	OR A
	RET Z		; Fertig?
	PUSH DE		; Rette Zieladresse
	LD E,(HL)	; Naechster Pointer
	INC HL
	LD D,(HL)	; in DE
	INC HL
	EX DE,HL	; Naechster Parameter
	LD C,(HL)
	INC HL
	LD B,(HL)	; in BC
	POP HL		; Hole Zieladresse
	LD (HL),C
	INC HL
	LD (HL),B
	INC HL
	EX DE,HL
	DEC A
	JR IARGT1
;
	END
