1; Generic console driver - VT52 + ZX Codes
2;
3; Supported VT52 codes:
4;
5; * = With VT52x
6;
7;  [ESC] A - Move the cursor to beginning of line above.
8;  [ESC] B - Move the cursor to beginning of line below.
9;  [ESC] C - Move the cursor right by one.
10;  [ESC] D - Move the cursor left by one
11;  [ESC] E - Clear the screen and place the cursor in the upper left corner.
12;  [ESC] H - Move the cursor to the upper left corner.
13;  // ![ESC] I - Move the cursor to beginning of line above.
14;  *[ESC] J - Erase all lines after our current line
15;  *[ESC] K - Clear the current line from the current cursor position.
16;  [ESC] Y - row col 'Goto' Coordinate mode - first will change line number, then cursor position (both ASCII - 32)
17;  [ESC] b - Byte after 'b' sets new foreground color (ASCII - 32)
18;  [ESC] c - Byte after 'c' sets new background color (ASCII -32)
19;  [ESC] p - start inverse video
20;  [ESC] q - stop inverse video
21;  *[ESC] 0 - start underlined
22;  *[ESC] 1 - stop underlined
23;  *[ESC] 2 - start bold
24;  *[ESC] 3 - stop bold
25;  [ESC] s - Enable/disable vertical scrolling
26;  [ESC] r [char] - Print character (raw)
27;   8      - move cursor left
28;  10      - linefeed
29;  12 = cls
30;
31; Supported ZX Codes:
32;
33;  4,[0|1] = enable/disable vertical scroll
34;  8 = backspace
35;  9 = right
36; 10 = line feed
37; 11 = up
38; 13 = down
39; 16, 32 +n = set ink
40; 17, 32 +n = set paper
41; 22,y+32,x+32 = Move to position
42
43
44		; Variables that can be adjusted by platform specific code
45		PUBLIC		generic_console_flags
46
47		EXTERN		generic_console_scrollup
48		EXTERN		generic_console_printc
49		EXTERN		generic_console_cls
50		EXTERN		generic_console_set_ink
51		EXTERN		generic_console_set_paper
52		EXTERN		generic_console_set_attribute
53		EXTERN		generic_console_set_attribute
54		EXTERN		__console_x
55		EXTERN		__console_y
56		EXTERN		__console_w
57		EXTERN		__console_h
58
59
60
61; extern int __LIB__ fputc_cons(char c);
62	ld	hl,2
63	add	hl,sp
64	ld	d,(hl)
65IF __CPU_INTEL__
66	ld	hl,(__console_x)
67	ld	c,l
68	ld	b,h
69ELIF __CPU_GBZ80__
70	ld	hl,__console_x
71	ld	c,(hl)
72	inc	hl
73	ld	b,(hl)
74ELSE
75	ld	bc,(__console_x)		;coordinates
76ENDIF
77	ld	hl,params_left
78	ld	a,(hl)
79	and	a
80	jr	nz,handle_parameter
81
82	; Check for raw flag here
83	ld	a,(generic_console_flags)
84	ld	e,1
85	rrca
86;	jr	nz,handle_character
87
88	dec	e				;-> e = 0 (look at zxcodes)
89	call	check_parameters		;Leaves e untouched
90	ret	c				;Return if we processed the escape/it was a valid escape
91handle_character:
92	ld	hl,generic_console_flags
93	; At this point:
94	;hl = generic_console_flags
95	; c = x position
96	; b = y position
97	; d = character to print
98	; e = raw character mode
99	ld	a,(__console_h)
100	dec	a
101	cp	b
102	jr	nc,handle_character_no_scroll
103	sub	b
104	neg
105	ld	b,a
106scroll_loop:
107IF __CPU_INTEL__
108	ld	a,(hl)
109	rlca
110	rlca
111	call	nc,generic_console_scrollup
112ELSE
113	bit	6,(hl)
114	call	z,generic_console_scrollup
115ENDIF
116	djnz	scroll_loop
117	ld	a,(__console_h)
118	dec	a
119	ld	b,a
120	ld	c,0
121IF __CPU_GBZ80__ | __CPU_INTEL__
122	ld	(__console_x+1),a		;a holds vlaue of b
123	ld	a,c
124	ld	(__console_x),a
125ELSE
126	ld	(__console_x),bc
127ENDIF
128handle_character_no_scroll:
129	ld	a,d
130	push	bc		;save coordinates
131	call	generic_console_printc
132	pop	bc
133	inc	c
134	ld	a,(__console_w)
135	cp	c
136	jr	nz,store_coords
137	ld	c,0
138	inc	b
139	jr	store_coords
140
141
142; Entry: hl = flags
143;         d = character
144IF SUPPORT_vt52
145set_escape:
146	; We need to look at the escape table now
147	ld	e,1			;Consider ANSI side
148	call	check_parameters
149	ret	c		; Processed
150	; Just print it in raw mode then
151print_raw:
152	ld	e,1
153	jr	handle_character
154ENDIF
155
156handle_parameter:
157	dec	(hl)
158	jr	z,parameter_dispatch
159	inc	hl	;Now points to parameters
160	ld	(hl),d
161	ret
162parameter_dispatch:
163IF __CPU_GBZ80__
164	ld	hl,parameter_processor
165	ld	a,(hl+)
166	ld	h,(hl)
167	ld	l,a
168ELSE
169	ld	hl,(parameter_processor)
170ENDIF
171	ld	a,d		;Get parameter into a
172do_dispatch:
173	push	hl
174	ld	hl,generic_console_flags
175	ret
176
177check_parameters:
178	ld	hl,parameter_table
179parameter_loop:
180	ld	a,(hl)
181	inc	hl
182IF SUPPORT_vt52
183  IF __CPU_INTEL__
184        push   de
185        ld     d,a
186        ld     a,e
187        rrca
188        jp     nc,not_ansi
189        ld     d,(hl)
190not_ansi:
191        ld     a,d
192        pop    de
193  ELSE
194	bit	0,e
195	jr	z,not_ansi
196	ld	a,(hl)
197not_ansi:
198   ENDIF
199ENDIF
200	inc	hl		;points to parameter count now
201	and	a		;nc
202	ret	z
203	cp	255
204	jr	z,try_again
205	cp	d
206	jr	nz, try_again
207	; We matched a command
208	ld	a,(hl)
209	ld	(params_left),a
210	ld	e,a
211	inc	hl
212	ld	a,(hl)
213	inc	hl
214	ld	h,(hl)
215	ld	l,a
216IF __CPU_GBZ80__
217	ld	(parameter_processor),a
218	ld	a,h
219	ld	(parameter_processor+1),a
220ELSE
221	ld	(parameter_processor),hl
222ENDIF
223	ld	a,e
224	and	a		;Immediate action?
225	ld	a,d		;The character
226	ccf
227	jr	z,do_dispatch
228	ret
229try_again:
230	inc	hl
231	inc	hl
232	inc	hl
233	jr	parameter_loop
234
235
236
237; hl = flags
238; bc = coordinates
239;  d = x
240; (parameter) = y
241set_xypos:
242IF __CPU_GBZ80__
243	ld	hl,__console_w
244	ld	a,(hl+)
245	ld	h,(hl)
246	ld	l,a
247ELSE
248	ld	hl,(__console_w)		;l = width, h = height
249ENDIF
250	ld	a,d
251	sub	32
252	ld	c,a
253	ld	a,l
254	dec	a
255	cp	c
256	ret	c		;out of range
257	ld	a,(parameters)
258	sub	32
259	ld	b,a
260	ld	a,h
261	dec	a
262	cp	b
263	ret	c	;out of range
264	jr	store_coords
265
266; Move print position left
267left:	ld	a,c
268	and	a
269	jr	nz,left_1
270	ld	a,(__console_w)
271	dec	a
272	ld	c,a
273	jr	up
274left_1: dec	c
275store_coords:
276IF __CPU_GBZ80__ | __CPU_INTEL__
277	ld	a,c
278	ld	(__console_x),a
279	ld	a,b
280	ld	(__console_x+1),a
281ELSE
282	ld	(__console_x),bc
283ENDIF
284	scf
285	ret
286
287; Move print position up
288up:	ld	a,b
289	and	a
290	jr	z,store_coords
291	dec	b
292	jr	store_coords
293
294down:	ld	a,(__console_h)
295	dec	a
296	cp	b
297	ret	z
298	inc	b
299	jr	store_coords
300
301right:	ld	a,(__console_w)
302	dec	a
303	cp	c
304	ret	z
305	inc	c
306	jr	store_coords
307
308set_vscroll:
309IF __CPU_INTEL__
310	ld	e,a
311	ld	a,(hl)
312	and	@10111111
313	ld	(hl),a
314	ld	a,e
315	rrca
316	ret	c
317	ld	a,(hl)
318	or	@01000000
319	ld	(hl),a
320	scf
321	ret
322ELSE
323	res	6,(hl)
324	rrca
325	ret	c
326	set	6,(hl)
327ENDIF
328	scf
329	ret
330
331set_ink:
332	call	generic_console_set_ink
333	scf
334	ret
335
336set_paper:
337	call	generic_console_set_paper
338	scf
339	ret
340
341
342cls:	call	generic_console_cls
343move_home:
344	ld	bc,0
345	jr	store_coords
346
347IF SUPPORT_vt52
348set_inverse_ansi:
349	dec	a		;p = 70 = on, q = 71 = off
350ENDIF
351set_inverse:			;Entry hl = flags
352IF __CPU_INTEL__
353	ld	e,@01111111
354	ld	d,@10000000
355	rra
356	jr	c,set_inverse_doit
357	ld	d,@00000000
358set_inverse_doit:
359	ld	a,(hl)
360	and	e
361	or	d
362	ld	(hl),a
363ELSE
364	rl	(hl)		;drop bit 7
365	rra
366	rr	(hl)		;get it back again
367ENDIF
368set_inverse_call_generic:
369	call	generic_console_set_attribute
370	scf
371	ret
372
373
374IF SUPPORT_vt52x
375; bc = coordinates
376clear_eol:
377	ld	a,b
378clear_eol_loop:
379	push	af		;save row
380	ld	e,0		;not raw
381	ld	a,' '
382	call	handle_character	;exits with bc=coordinates
383	pop	af
384	cp	b
385	jr	nz,clear_eol_loop
386	scf
387	ret
388
389; bc = coordinates
390clear_eos:
391	call	clear_eol		;exit, bc = coordinates
392	ld	a,(__console_h)
393	sub	b
394clear_eos_loop:
395	push	af
396	call	clear_eol
397	pop	af
398	dec	a
399	jr	nz,clear_eos_loop
400	scf
401	ret
402ENDIF
403
404
405handle_cr:
406	ld	a,(__console_h)
407	sub	b
408	jr	nc,handle_cr_no_need_to_scroll
409	dec	a
410	jr	nz,handle_cr_no_need_to_scroll
411	; Check if scroll is enabled
412IF __CPU_INTEL__
413	ld	a,(hl)
414	rlca
415	rlca
416	call	nc,generic_console_scrollup
417ELSE
418	bit	6,(hl)
419	call	z,generic_console_scrollup
420ENDIF
421
422	ld	a,(__console_h)
423	sub	2
424	ld	b,a
425handle_cr_no_need_to_scroll:
426	inc	b
427	ld	c,0
428	jp	store_coords
429
430
431
432IF SUPPORT_vt52x
433set_underlined_ansi:
434	;'0' = 48 = on, '1' = 49 = off
435	dec	a
436	and	@00001000
437	ld	c,a
438	ld	a,(hl)
439	and	@11110111
440	or	c
441	ld	(hl),a
442call_set_attribute:
443	call	generic_console_set_attribute
444	scf
445	ret
446
447set_bold_ansi:
448	;'2' = 50 = on, '3' = 51 = off
449	sub	3	;So 47, 48
450	and	@00001000
451	rlca
452	ld	c,a
453	ld	a,(hl)
454	and	@11101111
455	or	c
456	ld	(hl),a
457	jr	call_set_attribute
458ENDIF
459
460
461
462
463	SECTION	rodata_clib
464
465; defb ZXCode, ANSICode
466; defb parameter_count
467; defw process_routine
468;
469; If code is 255 then not valid for this mode, so skip
470parameter_table:
471IF SUPPORT_vt52
472	defb	27,255	;ESC
473	defb	1	;We expect one parameter
474	defw	set_escape
475ENDIF
476	defb	8, 8
477	defb	0
478	defw	left
479	defb	10, 10
480	defb	0
481	defw	handle_cr
482	defb	12, 12
483	defb	0
484	defw	cls
485
486	defb	9, 'D'
487	defb	0
488        defw	right
489        defb	11, 'A'
490	defb	0
491        defw	up
492        defb	13, 'B'
493	defb	0
494        defw	down
495IF SUPPORT_vt52
496        defb	255, 'D'
497	defb	0
498        defw	left
499ENDIF
500        defb	22, 'Y'
501	defb	2
502	defw	set_xypos
503IF SUPPORT_vt52
504	defb	255, 'E'
505	defb	0
506	defw	cls
507	defb	255, 'H'
508	defb	0
509	defw	move_home
510ENDIF
511	defb	4 , 's'
512	defb	1
513	defw	set_vscroll
514	defb	16, 'b'
515	defb	1
516	defw	set_ink
517	defb	17, 'c'
518	defb	1
519	defw	set_paper
520IF SUPPORT_zxcodes
521	defb	20, 255
522	defb	1
523	defw	set_inverse
524ENDIF
525IF SUPPORT_vt52
526	defb	255, 'p'
527	defb	0
528	defw	set_inverse_ansi
529	defb	255, 'q'
530	defb	0
531	defw	set_inverse_ansi
532ENDIF
533IF SUPPORT_vt52x
534	defb	255, '0'
535	defb	0
536	defw	set_underlined_ansi
537	defb	255, '1'
538	defb	0
539	defw	set_underlined_ansi
540	defb	255, '2'
541	defb	0
542	defw	set_bold_ansi
543	defb	255, '3'
544	defb	0
545	defw	set_bold_ansi
546	defb	255, 'K'
547	defb	0
548	defw	clear_eol
549	defb	255,'J'
550	defb	0
551	defw	clear_eos
552ENDIF
553IF SUPPORT_vt52
554	defb	255, 'r'
555	defb	1
556	defw	print_raw
557ENDIF
558	defb	0	;endmarker
559
560		SECTION		bss_clib
561
562params_left:	defb	0		; Number of parameters left to read
563parameters:	defb	0		; We only have up-to two parameters
564parameter_processor:	defw	0	; Where we go to when we need to process
565
566generic_console_flags:		defb	0		; bit 0 = raw mode enabled
567							; bit 3 = underline
568							; bit 4 = bold
569							; bit 6 = vscroll disabled
570							; bit 7 = inverse on
571
572