1; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
2; SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
3; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
4; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
5; IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
6; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
7; FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
8; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
9; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
10; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
11
12.386
13
14_DATA   SEGMENT BYTE PUBLIC USE32 'DATA'
15
16INCLUDE psmacros.inc
17INCLUDE TWEAK.INC
18INCLUDE VGAREGS.INC
19
20extd _gr_var_bwidth
21
22extd _modex_line_vertincr
23extd _modex_line_incr1
24extd _modex_line_incr2
25	_modex_line_routine	dd ?
26extd _modex_line_x1
27extd _modex_line_y1
28extd _modex_line_x2
29extd _modex_line_y2
30extb _modex_line_Color
31
32	SavedColor      db ?
33
34LEFT_MASK1      = 1000b
35LEFT_MASK2      = 1100b
36LEFT_MASK3      = 1110b
37RIGHT_MASK1     = 0001b
38RIGHT_MASK2     = 0011b
39RIGHT_MASK3     = 0111b
40ALL_MASK        = 1111b
41
42tmppal          db 768 dup (0)
43fb_pal          dd ?
44fb_add          dw ?
45fb_count        dd ?
46
47MaskTable1  db  ALL_MASK AND RIGHT_MASK1,
48				ALL_MASK AND RIGHT_MASK2,
49				ALL_MASK AND RIGHT_MASK3,
50				ALL_MASK,
51				LEFT_MASK3 AND RIGHT_MASK1,
52				LEFT_MASK3 AND RIGHT_MASK2,
53				LEFT_MASK3 AND RIGHT_MASK3,
54				LEFT_MASK3,
55				LEFT_MASK2 AND RIGHT_MASK1,
56				LEFT_MASK2 AND RIGHT_MASK2,
57				LEFT_MASK2 AND RIGHT_MASK3,
58				LEFT_MASK2,
59				LEFT_MASK1 AND RIGHT_MASK1,
60				LEFT_MASK1 AND RIGHT_MASK2,
61				LEFT_MASK1 AND RIGHT_MASK3,
62				LEFT_MASK1,
63
64MaskTable2  db  ALL_MASK,RIGHT_MASK1,
65				ALL_MASK,RIGHT_MASK2,
66				ALL_MASK,RIGHT_MASK3,
67				ALL_MASK,ALL_MASK,
68				LEFT_MASK3,RIGHT_MASK1,
69				LEFT_MASK3,RIGHT_MASK2,
70				LEFT_MASK3,RIGHT_MASK3,
71				LEFT_MASK3,ALL_MASK,
72				LEFT_MASK2,RIGHT_MASK1,
73				LEFT_MASK2,RIGHT_MASK2,
74				LEFT_MASK2,RIGHT_MASK3,
75				LEFT_MASK2,ALL_MASK,
76				LEFT_MASK1,RIGHT_MASK1,
77				LEFT_MASK1,RIGHT_MASK2,
78				LEFT_MASK1,RIGHT_MASK3,
79				LEFT_MASK1,ALL_MASK
80
81DrawTable   dd  DrawMR,
82				DrawMR,
83				DrawMR,
84				DrawM,
85				DrawLMR,
86				DrawLMR,
87				DrawLMR,
88				DrawLM,
89				DrawLMR,
90				DrawLMR,
91				DrawLMR,
92				DrawLM,
93				DrawLMR,
94				DrawLMR,
95				DrawLMR,
96				DrawLM
97
98_DATA   ENDS
99
100DGROUP  GROUP _DATA
101
102
103_TEXT   SEGMENT BYTE PUBLIC USE32 'CODE'
104
105		ASSUME  DS:_DATA
106		ASSUME  CS:_TEXT
107
108PUBLIC  gr_sync_display_
109
110gr_sync_display_:
111
112		push    ax
113		push    dx
114		mov     dx, VERT_RESCAN
115VS2A:   in      al, dx
116		and     al, 08h
117		jnz     VS2A        ; Loop until not in vertical retrace
118VS2B:   in      al, dx
119		and     al, 08h
120		jz      VS2B        ; Loop until in vertical retrace
121
122		pop     dx
123		pop     ax
124		ret
125
126
127PUBLIC  gr_modex_uscanline_
128
129gr_modex_uscanline_:
130		push    edi
131
132		; EAX = X1  (X1 and X2 don't need to be sorted)
133		; EDX = X2
134		; EBX = Y
135		; ECX = Color
136
137		mov     SavedColor, cl
138
139		;mov     ebx, _RowOffset[ebx*4]
140		mov	edi, _gr_var_bwidth
141		imul	edi, ebx
142		add     edi, 0A0000h
143		cmp     eax, edx
144		jle     @f
145		xchg    eax, edx
146@@:     mov     bl, al
147		shl     bl, 2
148		mov     bh, dl
149		and     bh, 011b
150		or      bl, bh
151		and     ebx, 0fh
152		; BX = LeftRight switch command. (4bit)
153		shr     eax, 2
154		shr     edx, 2
155		add     edi, eax
156		; EDI = Offset into video memory
157		mov     ecx, edx
158		sub     ecx, eax
159		; ECX = X2/4 - X1/4 - 1
160		jnz     LargerThan4
161
162;======================= ONE GROUP OF 4 OR LESS TO DRAW ====================
163
164		mov     dx, SC_INDEX
165		mov     al, SC_MAP_MASK
166		out     dx, al
167		inc     dx
168		mov     al, MaskTable1[ebx]
169		out     dx, al
170		mov     al, SavedColor
171		mov     [edi], al           ; Write the one pixel
172		pop     edi
173		ret
174
175LargerThan4:
176		dec     ecx
177		jnz     LargerThan8
178
179;===================== TWO GROUPS OF 4 OR LESS TO DRAW ====================
180
181		mov     cx, WORD PTR MaskTable2[ebx*2]
182		mov     bl, SavedColor
183		mov     dx, SC_INDEX
184		mov     al, SC_MAP_MASK
185		out     dx, al
186		inc     dx
187		mov     al, cl
188		out     dx, al
189		mov     [edi], bl           ; Write the left pixel
190		mov     al, ch
191		out     dx, al
192		mov     [edi+1], bl         ; Write the right pixel
193		pop     edi
194		ret
195
196;========================= MANY GROUPS OF 4 TO DRAW ======================
197LargerThan8:
198		mov     dx, SC_INDEX
199		mov     al, SC_MAP_MASK
200		out     dx, al
201		inc     dx
202		; DX = SC_INDEX
203		mov     al, SavedColor
204		mov     ah, al
205		; AL,AH = color of pixel
206		jmp     NEAR32 PTR DrawTable[ebx*4]
207
208
209DrawM:  ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index
210		mov     al, ALL_MASK
211		out     dx, al
212		mov     al, ah
213		cld
214		add     ecx, 2
215		shr     ecx, 1
216		rep     stosw       ; Write the middle pixels
217		jnc     @F
218		stosb               ; Write the middle odd pixel
219@@:     pop     edi
220		ret
221
222DrawLM:
223		;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index
224		mov     al, BYTE PTR MaskTable2[ebx*2]
225		out     dx, al
226		mov     [edi], ah       ; Write leftmost pixels
227		inc     edi
228		mov     al, ALL_MASK
229		out     dx, al
230		mov     al, ah
231		cld
232		inc     ecx
233		shr     ecx, 1
234		rep     stosw       ; Write the middle pixels
235		jnc     @F
236		stosb               ; Write the middle odd pixel
237@@:     pop     edi
238		ret
239
240
241DrawLMR: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index
242		mov     bx, WORD PTR MaskTable2[ebx*2]
243		mov     al, bl
244		out     dx, al
245		mov     [edi], ah       ; Write leftmost pixels
246		inc     edi
247		mov     al, ALL_MASK
248		out     dx, al
249		mov     al, ah
250		cld
251		shr     ecx, 1
252		rep     stosw       ; Write the middle pixels
253		jnc     @F
254		stosb               ; Write the middle odd pixel
255@@:     mov     al, bh
256		out     dx, al
257		mov     [edi], ah   ; Write the rightmost pixels
258		pop     edi
259		ret
260
261DrawMR: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index
262		mov     bx, WORD PTR MaskTable2[ebx*2]
263		mov     al, ALL_MASK
264		out     dx, al
265		mov     al, ah
266		cld
267		inc     ecx
268		shr     ecx, 1
269		rep     stosw       ; Write the middle pixels
270		jnc     @F
271		stosb               ; Write the middle odd pixel
272@@:     mov     al, bh
273		out     dx, al
274		mov     [edi], ah   ; Write the rightmost pixels
275		pop     edi
276		ret
277
278
279PUBLIC gr_modex_setmode_
280
281gr_modex_setmode_:
282
283	push  ebx
284	push  ecx
285	push  edx
286	push  esi
287	push  edi
288
289	mov   ecx, eax
290	dec   ecx
291
292	cmp   ecx, LAST_X_MODE
293	jbe   @f
294	mov   ecx, 0
295@@:
296
297	;call  turn_screen_off
298
299	push  ecx                   ; some bios's dont preserve cx
300
301	;mov ax, 1201h
302	;mov bl, 31h     ; disable palette loading at mode switch
303	;int 10h
304	mov   ax,13h                ; let the BIOS set standard 256-color
305	int   10h                   ;  mode (320x200 linear)
306	;mov ax, 1200h
307	;mov bl, 31h     ; enable palette loading at mode switch
308	;int 10h
309
310	pop   ecx
311
312	mov   dx,SC_INDEX
313	mov   ax,0604h
314	out   dx,ax                 ; disable chain4 mode
315
316	mov   dx,SC_INDEX
317	mov   ax,0100h
318	out   dx,ax                 ; synchronous reset while setting Misc
319								;  Output for safety, even though clock
320								;  unchanged
321
322	mov   esi, dword ptr ModeTable[ecx*4]
323	lodsb
324
325	or    al,al
326	jz    DontSetDot
327
328	mov   dx,MISC_OUTPUT
329	out   dx,al               ; select the dot clock and Horiz
330							  ;  scanning rate
331
332	;mov   dx,SC_INDEX
333	;mov   al,01h
334	;out   dx,al
335	;inc   dx
336	;in    al, dx
337	;or    al, 1000b
338	;out   dx, al
339
340DontSetDot:
341	mov   dx,SC_INDEX
342	mov   ax,0300h
343	out   dx,ax        ; undo reset (restart sequencer)
344
345	mov   dx,CRTC_INDEX       ; reprogram the CRT Controller
346	mov   al,11h              ; VSync End reg contains register write
347	out   dx,al               ; protect bit
348	inc   dx                  ; CRT Controller Data register
349	in    al,dx               ; get current VSync End register setting
350	and   al,07fh             ; remove write protect on various
351	out   dx,al               ; CRTC registers
352	dec   dx                  ; CRT Controller Index
353	cld
354	xor   ecx,ecx
355	lodsb
356	mov   cl,al
357
358SetCRTParmsLoop:
359	lodsw                     ; get the next CRT Index/Data pair
360	out   dx,ax               ; set the next CRT Index/Data pair
361	loop  SetCRTParmsLoop
362
363	mov   dx,SC_INDEX
364	mov   ax,0f02h
365	out   dx,ax       ; enable writes to all four planes
366	mov   edi, 0A0000h        ; point ES:DI to display memory
367	xor   ax,ax               ; clear to zero-value pixels
368	mov   ecx,8000h           ; # of words in display memory
369	rep   stosw               ; clear all of display memory
370
371	;  Set pysical screen dimensions
372
373	xor   eax, eax
374	lodsw                               ; Load scrn pixel width
375	mov   cx, ax
376	shl   eax, 16
377
378	mov   dx,CRTC_INDEX
379	mov   al,CRTC_OFFSET
380	out   dx,al
381	inc   dx
382	mov   ax,cx
383	shr   ax,3
384	out   dx,al
385
386	;mov     si, 360
387	;@@:
388	;mov     ax, 04f06h
389	;mov     bl, 0
390	;mov     cx, si
391	;int     10h
392	;cmp     cx, si
393	;je      @f
394	;inc     si
395	;jmp     @B
396	;@@:
397	;movzx     eax, si
398
399	lodsw                               ; Load Screen Phys. Height
400
401	;call  turn_screen_on
402
403	pop  edi
404	pop  esi
405	pop  edx
406	pop  ecx
407	pop  ebx
408
409	ret
410
411PUBLIC gr_modex_setplane_
412
413gr_modex_setplane_:
414
415		push    cx
416		push    dx
417
418		mov     cl, al
419
420		; SELECT WRITE PLANE
421		and     cl,011b             ;CL = plane
422		mov     ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg
423		shl     ah,cl               ;set only the bit for the required
424									; plane to 1
425		mov     dx,SC_INDEX         ;set the Map Mask to enable only the
426	   out     dx,ax               ; pixel's plane
427
428		; SELECT READ PLANE
429		mov     ah,cl               ;AH = plane
430		mov     al,READ_MAP         ;AL = index in GC of the Read Map reg
431		mov     dx,GC_INDEX         ;set the Read Map to read the pixel's
432		out     dx,ax               ; plane
433
434		pop     dx
435		pop     cx
436
437		ret
438
439PUBLIC  gr_modex_setstart_
440
441gr_modex_setstart_:
442
443		; EAX = X
444		; EDX = Y
445		; EBX = Wait for retrace
446
447		push    ebx
448		push    ecx
449		push	ebx
450
451		mov	ecx, _gr_var_bwidth
452		imul	ecx, edx
453
454		shr     eax, 2
455		add     eax, ecx
456
457		mov     ch, ah
458		mov     bh, al
459
460		mov     bl, CC_START_LO
461		mov     cl, CC_START_HI
462
463		cli
464		mov     dx, VERT_RESCAN
465WaitDE: in      al, dx
466		test    al, 01h
467		jnz     WaitDE
468
469		mov     dx, CRTC_INDEX
470		mov     ax, bx
471		out     dx, ax      ; Start address low
472		mov     ax, cx
473		out     dx, ax      ; Start address high
474		sti
475
476		pop	ebx
477		cmp	ebx, 0
478		je	NoWaitVS
479		mov     dx, VERT_RESCAN
480WaitVS: in      al, dx
481		test    al, 08h
482		jz      WaitVS      ; Loop until in vertical retrace
483NoWaitVS:
484
485		pop     ecx
486		pop     ebx
487
488		ret
489
490
491
492
493ModeXAddr       macro
494; given: ebx=x, eax=y, return cl=plane mask, ebx=address, trash eax
495	mov	cl, bl
496	and	cl, 3
497	shr	ebx, 2
498	imul	eax, _gr_var_bwidth
499	add	ebx, eax
500	add	ebx, 0A0000h
501	endm
502
503
504;-----------------------------------------------------------------------
505;
506; Line drawing function for all MODE X 256 Color resolutions
507; Based on code from "PC and PS/2 Video Systems" by Richard Wilton.
508
509PUBLIC gr_modex_line_
510
511gr_modex_line_:
512	pusha
513
514	mov	dx,SC_INDEX	; setup for plane mask access
515
516; check for vertical line
517
518	mov	esi,_gr_var_bwidth
519	mov	ecx,_modex_line_x2
520	sub	ecx,_modex_line_x1
521	jz	VertLine
522
523; force x1 < x2
524
525	jns	L01
526
527	neg	ecx
528
529	mov	ebx,_modex_line_x2
530	xchg	ebx,_modex_line_x1
531	mov	_modex_line_x2,ebx
532
533	mov	ebx,_modex_line_y2
534	xchg	ebx,_modex_line_y1
535	mov	_modex_line_y2,ebx
536
537; calc dy = abs(y2 - y1)
538
539L01:
540	mov	ebx,_modex_line_y2
541	sub	ebx,_modex_line_y1
542	jnz	short skip
543	jmp     HorizLine
544skip:		jns	L03
545
546	neg	ebx
547	neg	esi
548
549; select appropriate routine for slope of line
550
551L03:
552	mov	_modex_line_vertincr,esi
553	mov	_modex_line_routine,offset LoSlopeLine
554	cmp	ebx,ecx
555	jle	L04
556	mov	_modex_line_routine,offset HiSlopeLine
557	xchg	ebx,ecx
558
559; calc initial decision variable and increments
560
561L04:
562	shl	ebx,1
563	mov	_modex_line_incr1,ebx
564	sub	ebx,ecx
565	mov	esi,ebx
566	sub	ebx,ecx
567	mov	_modex_line_incr2,ebx
568
569; calc first pixel address
570
571	push	ecx
572	mov	eax,_modex_line_y1
573	mov	ebx,_modex_line_x1
574	ModeXAddr
575	mov	edi,ebx
576	mov	al,1
577	shl	al,cl
578	mov	ah,al		; duplicate nybble
579	shl	al,4
580	add	ah,al
581	mov	bl,ah
582	pop	ecx
583	inc	ecx
584	jmp	[_modex_line_routine]
585
586; routine for verticle lines
587
588VertLine:
589	mov	eax,_modex_line_y1
590	mov	ebx,_modex_line_y2
591	mov	ecx,ebx
592	sub	ecx,eax
593	jge	L31
594	neg	ecx
595	mov	eax,ebx
596
597L31:
598	inc	ecx
599	mov	ebx,_modex_line_x1
600	push	ecx
601	ModeXAddr
602
603	mov	ah,1
604	shl	ah,cl
605	mov	al,MAP_MASK
606	out	dx,ax
607	pop	ecx
608	mov	ax, word ptr _modex_line_Color
609
610; draw the line
611
612L32:
613	mov	[ebx],al
614	add	ebx,esi
615	loop	L32
616	jmp	Lexit
617
618; routine for horizontal line
619
620HorizLine:
621
622	mov	eax,_modex_line_y1
623	mov	ebx,_modex_line_x1
624	ModeXAddr
625
626	mov	edi,ebx     ; set dl = first byte mask
627	mov	dl,00fh
628	shl	dl,cl
629
630	mov	ecx,_modex_line_x2 ; set dh = last byte mask
631	and	cl,3
632	mov	dh,00eh
633	shl	dh,cl
634	not	dh
635
636; determine byte offset of first and last pixel in line
637
638	mov	eax,_modex_line_x2
639	mov	ebx,_modex_line_x1
640
641	shr	eax,2     ; set ax = last byte column
642	shr	ebx,2    ; set bx = first byte column
643	mov	ecx,eax    ; cx = ax - bx
644	sub	ecx,ebx
645
646	mov    	eax,edx    ; mov end byte masks to ax
647	mov	dx,SC_INDEX ; setup dx for VGA outs
648	mov     bl,_modex_line_Color
649
650; set pixels in leftmost byte of line
651
652	or	ecx,ecx      ; is start and end pt in same byte
653	jnz	L42        ; no !
654	and	ah,al      ; combine start and end masks
655	jmp	short L44
656
657L42:            push    eax
658	mov     ah,al
659	mov     al,MAP_MASK
660	out     dx,ax
661	mov	al,bl
662	stosb
663	dec	ecx
664
665; draw remainder of the line
666
667L43:
668	mov	ah,0Fh
669	mov	al,MAP_MASK
670	out	dx,ax
671	mov	al,bl
672	rep	stosb
673	pop     eax
674
675; set pixels in rightmost byte of line
676
677L44:
678	mov	al,MAP_MASK
679	out	dx, ax
680	mov     byte ptr [edi],bl
681	jmp	Lexit
682
683
684; routine for dy >= dx (slope <= 1)
685
686LoSlopeLine:
687	mov	al,MAP_MASK
688	mov	bh,byte ptr _modex_line_Color
689L10:
690	mov	ah,bl
691
692L11:
693	or	ah,bl
694	rol	bl,1
695	jc	L14
696
697; bit mask not shifted out
698
699	or	esi,esi
700	jns	L12
701	add	esi,_modex_line_incr1
702	loop	L11
703
704	out	dx,ax
705	mov	[edi],bh
706	jmp	short Lexit
707
708L12:
709	add	esi,_modex_line_incr2
710	out	dx,ax
711	mov	[edi],bh
712	add	edi,_modex_line_vertincr
713	loop	L10
714	jmp	short Lexit
715
716; bit mask shifted out
717
718L14:            out	dx,ax
719	mov	[edi],bh
720	inc	edi
721	or	esi,esi
722	jns	L15
723	add	esi,_modex_line_incr1
724	loop	L10
725	jmp	short Lexit
726
727L15:
728	add	esi,_modex_line_incr2
729	add	edi,_modex_line_vertincr
730	loop	L10
731	jmp	short Lexit
732
733; routine for dy > dx (slope > 1)
734
735HiSlopeLine:
736	mov	ebx,_modex_line_vertincr
737	mov	al,MAP_MASK
738L21:    out	dx,ax
739	push	eax
740	mov	al,_modex_line_Color
741	mov	[edi],al
742	pop	eax
743	add	edi,ebx
744
745L22:
746	or	esi,esi
747	jns	L23
748
749	add	esi,_modex_line_incr1
750	loop	L21
751	jmp	short Lexit
752
753L23:
754	add	esi,_modex_line_incr2
755	rol	ah,1
756	adc	edi,0
757lx21:	loop	L21
758
759; return to caller
760
761Lexit:
762	popa
763	ret
764
765
766
767_TEXT   ENDS
768
769
770		END
771