1 ;
2 ;	swgrph	 -	SW screen graphics
3 ;
4 ;	Copyright (C) 1984-2003 David L. Clark.
5 ;	This program is free software; you can redistribute it and/or modify it under
6 ;	the terms of the GNU General Public License as published by the Free Software
7 ;	Foundation; either version 2 of the License, or (at your option) any later
8 ;	version. This program is distributed in the hope that it will be useful,
9 ;	but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 ;	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 ;	more details. You should have received a copy of the GNU General Public
12 ;	License along with this program; if not, write to the Free Software Foundation,
13 ;	Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
14 ;
15 ;	Modification History:
16 ;			84-02-21	Development
17 ;			84-06-13	PCjr Speed-up
18 ;			85-11-05	Atari
19 ;			87-03-10	Microsoft compiler
20 ;			87-03-13	Splatted ox display
21 ;			94-12-18	C6 Compiler
22 ;			2003-01-27	GNU General Public License
23 ;
24 ;
25 
26 
27 %	.MODEL	model,lang
28 	INCLUDE mixed.inc
29 
30 	.CODE
31 
32 	include segments.h
33 	include sw.ha
34 
35 	public	swdisp
36 	public	swground
37 	public	swputsym
38 	public	swputcol
39 	public	swclrcol
40 	public	swpntsym
41 	public	swpntcol
42 	public	get_type
43 	public	set_type
44 	public	setvdisp
45 	public	setadisp
46 
47 	extrn	dispoxsplat:near
48 
49 
50 
51 ;----------------------------------------------------------------------------
52 
53 
54 swdisp:
55 	push	BP			; save registers
56 	push	DI
57 	push	SI
58 	push	ES
59 
60 ;
61 ;	setup display in video ram
62 ;
63 	call	setvdisp
64 
65 ;
66 ;	for each object, delete the object from the screen if it currently
67 ;	displayed, and re-draw the object if still on the screen
68 ;
69 
70 	mov	BX,objtop		; address of first object
71 
72 disploop:
73 	or	BX,BX			; last object?
74 	jnz	disp00			;    NO  - continue
75 	jmp	dispdel 		;    YES - leave
76 
77 disp00: mov	AX,OB_DELFLG[BX]	; is the object being deleted and
78 	and	AX,OB_DRWFLG[BX]	; redrawn?
79 	jz	disp0			;   NO - continue
80 	cmp	word ptr OB_SYMHGT[BX],1; is the object trivial?
81 	je	disp0			;   YES- continue
82 	mov	AX,OB_OLDSYM[BX]	; are the old object display and the
83 	cmp	AX,OB_NEWSYM[BX]	; new object display the same
84 	jne	disp0			;   NO - continue
85 	mov	AX,OB_Y[BX]		; is the object moving
86 	cmp	AX,OB_OLDY[BX]		; vertically?
87 	jne	disp0			;   YES - continue
88 	mov	AX,OB_OLDX[BX]		; is the object moving
89 	add	AX,displx		; with the player in
90 	cmp	AX,OB_X[BX]		; the x direction?
91 	jnz	disp0			;   NO - continue
92 	jmp	disp11			; test display function
93 
94 disp0:
95 	cmp	word ptr OB_DELFLG[BX],0; is this object to be deleted?
96 	jz	disp1			;    NO  - skip
97 	mov	DI,OB_OLDY[BX]		;    YES - save old object y coord
98 	mov	SI,OB_OLDX[BX]		;		old object x coord
99 	mov	BP,OB_OLDSYM[BX]	;	   old symbol
100 	mov	AX,OB_CLR[BX]		;	   color of object
101 	call	drawsym 		;	   remove by xor draw
102 
103 disp1:	cmp	word ptr OB_DRWFLG[BX],0; is the object to be drawn
104 	jz	disp3			;    NO  - skip
105 	mov	SI,OB_X[BX]		;    YES - load object x coord
106 	cmp	SI,displx		;	   object past left margin?
107 	jl	disp2			;	      YES - skip
108 	cmp	SI,disprx		;	   object past right margin?
109 	jg	disp2			;	      YES - skip
110 	sub	SI,displx		;	   get object x coord
111 	call	testox			;	   hidden due to splatted ox?
112 	je	disp2			;	      YES - skip
113 
114 	mov	OB_OLDX[BX],SI		;	   save object x coord
115 	mov	DI,OB_Y[BX]		;	   save object y coord
116 	mov	OB_OLDY[BX],DI
117 	mov	BP,OB_NEWSYM[BX]	;		new symbol
118 	mov	AX,OB_CLR[BX]		;		color of object
119 	call	drawsym 		;	   draw the object
120 
121 disp11: cmp	word ptr OB_DRAWF[BX],0 ;	   is there a display function?
122 	jz	disp3			;	      NO - skip
123 	push	BX			;	      YES- save object pointer
124 	call	word ptr OB_DRAWF[BX]	;		   call function
125 	pop	BX			;		   restore BX
126 	jmp	disp3
127 
128 disp2:	mov	word ptr OB_DRWFLG[BX],0; indicate object not drawn
129 disp3:	mov	BX,OB_NEXT[BX]		; get next object in list
130 	jmp	disploop		; loop back
131 
132 ;
133 ;	for each object in the newly deleted object list, delete
134 ;	any images on screen
135 ;
136 
137 dispdel:
138 
139 	mov	BX,deltop		; start of deleted object list
140 
141 dispdlop:
142 	or	BX,BX			; last object on list?
143 	jz	dispret 		;   YES - leave
144 
145 	cmp	word ptr OB_DELFLG[BX],0; is this object to be deleted?
146 	jz	dispd1			;    NO  - skip
147 	mov	DI,OB_OLDY[BX]		;    YES - save old object y coord
148 	mov	SI,OB_OLDX[BX]		;		old object x coord
149 	mov	BP,OB_OLDSYM[BX]	;	   old symbol
150 	mov	AX,OB_CLR[BX]		;	   color of object
151 	call	drawsym 		;	   remove by xor draw
152 
153 dispd1: mov	BX,OB_NEXT[BX]		; get next object in list
154 	jmp	dispdlop		; loop back
155 
156 dispret:
157 	cmp	word ptr oxsplatted,1	; ox splatted on screen?
158 	je	dispdone		;    YES - leave
159 	call	dispgrnd		; update ground display
160 	cmp	word ptr splatox,0	; hit the ox?
161 	jz	dispdone		;    NO - skip
162 	call	dispoxsplat		;    YES- splat the ox
163 
164 dispdone:
165 	mov	word ptr dispinit,0	; reset initialized display flag
166 	mov	word ptr forcdisp,0	; reset force display flag
167 	pop	ES			; restore registers
168 	pop	SI
169 	pop	DI
170 	pop	BP
171 	ret
172 
173 
174 ;-----------------------------------------------------------------------------
175 
176 testox:
177 	cmp	word ptr oxsplatted,1	; OX splatted?
178 	jne	testr			;    NO - leave
179 
180 	push	AX			; save registers
181 	push	DX			;
182 	mov	AX,SI			; X coordinate in AX
183 	mov	DL,106			; divide by 320/3
184 	div	DL			;
185 	test	AL,1			; test if to display
186 	pop	DX			; restore registers
187 	pop	AX			;
188 
189 testr:	ret				; return
190 
191 ;-----------------------------------------------------------------------------
192 
193 dispgrnd:
194 	cld				; clear direction flag
195 	cmp	word ptr dispinit,1	; first display after initialization?
196 	je	dg1			;   YES - skip erase of old ground
197 	cmp	dispdx,0		;	  is screen moving?
198 	jnz	dg0			;	  YES - continue
199 	cmp	forcdisp,0		;	  NO  - is display to be forced
200 	jnz	dg0			;		YES - continue
201 	ret				;		NO  - return
202 
203 dg0:	lea	SI,grndsave		;   NO	- erase old ground by xor
204 	call	dispg			;	  redraw of ground
205 
206 dg1:	mov	AX,DS			; set ES to DS for ground save
207 	mov	ES,AX
208 	lea	SI,ground		; start of ground address
209 	add	SI,displx		; start address of displayed ground
210 	mov	BX,SI			; save it
211 	lea	DI,grndsave		; address of ground save area
212 	mov	CX,(SCR_WDTH/2) 	; screen width in words
213 	rep	movsw			; save ground being displayed
214 
215 	mov	SI,BX			; start address of displayed ground
216 	call	dispg			; display it
217 	ret
218 
219 dispg:	mov	DX,disproff		; down raster line offset in DX
220 	mov	BX,DX
221 	sub	BX,SCR_LINW		; up raster line offset in BX
222 
223 	mov	AL,[SI] 		; initial ground height in AL
224 	mov	CL,AL			;			in CL
225 	sub	AL,(SCR_HGHT-1) 	; inverted ground height
226 	neg	AL			;
227 	shr	AL,1			; adjust for even/odd scan lines
228 	mov	CH,SCR_LINW		; line width
229 	mul	CH			; byte offset of first dot in AX
230 
231 	test	CL,1			; is first dot on an odd scanline
232 	jnz	dg2			;    NO - skip
233 	add	AX,DX			;    YES- move to next segment
234 	neg	BX			;	  reverse up/down offsets
235 	neg	DX
236 	xchg	BX,DX
237 
238 dg2:	add	AX,dispoff		; add display offset
239 	mov	DI,AX			; set final register
240 
241 	mov	BP,SI			; start of ground to display
242 	add	BP,SCR_WDTH		; end of ground to display
243 	mov	CH,0C0H 		; initial ground dot mask
244 	mov	AH,[SI] 		; initial 'last ground height'
245 	mov	ES,dispseg		; screen segment
246 
247 dgloop:
248 	lodsb				; get next ground height
249 	cmp	AL,AH			; compare new height to old
250 	ja	dga			;   ABOVE
251 	jb	dgb			;   BELOW
252 
253 	xor	ES:[DI],CH		;   EQUAL - plot dot
254 	jmp	dgn			;	    get next pixel
255 
256 dga:	add	DI,BX			;   ABOVE - move up a scan line
257 	neg	BX			;	    reverse up/down offsets
258 	neg	DX
259 	xchg	BX,DX
260 	xor	ES:[DI],CH		;	    plot dot
261 	inc	AH			;	    move up a height
262 	cmp	AL,AH			;	    where we want to be?
263 	jne	dga			;	       NO - up again
264 	jmp	dgn			;	       YES- get next pixel
265 
266 dgb:	add	DI,DX			;   BELOW - move down a scan line
267 	neg	BX			;	    reverse up/down offsets
268 	neg	DX
269 	xchg	BX,DX
270 	xor	ES:[DI],CH		;	    plot dot
271 	dec	AH			;	    move down a height
272 	cmp	AL,AH			;	    where we want to be?
273 	jne	dgb			;	       NO - up again
274 
275 dgn:	shr	CH,1			; shift plot mask right 2 bits
276 	shr	CH,1			;
277 	or	CH,CH			; end of byte?
278 	jnz	dgloop			;   NO - get next ground height
279 	inc	DI			;   YES- increment a byte
280 	mov	CH,0C0H 		;	 reset plot mask
281 	cmp	SI,BP			;	 end of ground display?
282 	jb	dgloop			;	    NO - get next ground height
283 	ret				;	    YES- bye
284 
285 
286 
287 ;-----------------------------------------------------------------------------
288 
289 swground:
290 	push	BP			; save registers
291 	push	DI
292 	push	SI
293 	push	ES
294 	call	dispgrnd		; display ground for title screen
295 	pop	ES			; restore registers
296 	pop	SI
297 	pop	DI
298 	pop	BP
299 	ret
300 
301 
302 
303 
304 ;-----------------------------------------------------------------------------
305 
306 swclrcol:
307 	push	DI			; save registers
308 	push	SI
309 	push	ES
310 
311 	cld				; clear direction flag
312 	mov	ES,dispseg		; get current display segment
313 	mov	SI,dispoff		; get current display offset
314 	add	SI,(((SCR_HGHT/2)-1)*SCR_LINW) ; offset of last line
315 	call	clearhalf		; clear even lines
316 	add	SI,disproff
317 	call	clearhalf		; clear odd lines
318 
319 	pop	ES			; restore registers
320 	pop	SI
321 	pop	DI
322 	ret
323 
324 
325 clearhalf proc near
326 	mov	DI,SI			; starting address
327 	mov	CX,8			; clear 8 lines
328 	xor	AX,AX			; zero pattern in AX
329 
330 cloop:	stosw				; clear 48 pixels
331 	stosw
332 	stosw
333 	stosw
334 	stosw
335 	stosw
336 	sub	DI,(SCR_LINW+12)	; reset to previous line
337 	loop	cloop			; do 8 times
338 	ret
339 clearhalf endp
340 
341 
342 ;-----------------------------------------------------------------------------
343 
344 swputsym:
345 	mov	BX,SP			; new frame pointer
346 	push	BP			; save other registers
347 	push	SI
348 	push	DI
349 	push	ES
350 
351 	mov	SI,2[BX]		; load symbol x ccord
352 	mov	DI,4[BX]		;      symbol y coord
353 	mov	BX,6[BX]		;      object address
354 	mov	BP,OB_NEWSYM[BX]	;      current symbol
355 	mov	AX,OB_CLR[BX]		;      color of object
356 	call	drawsym 		; draw symbol
357 
358 	pop	ES			; restore registers
359 	pop	DI
360 	pop	SI
361 	pop	BP
362 	ret
363 
364 
365 ;-----------------------------------------------------------------------------
366 
367 swpntsym:
368 	push	BP			; save SI
369 	mov	BP,SP			; new frame pointer
370 	push	SI			; save other registers
371 	push	DI
372 	push	ES
373 
374 	mov	SI,4[BP]		; load point x ccord
375 	mov	DI,6[BP]		;      point y coord
376 	mov	BP,8[BP]		;      point color
377 	call	drawpnt 		; display point
378 
379 	pop	ES			; restore registers
380 	pop	DI
381 	pop	SI
382 	pop	BP
383 	ret
384 
385 
386 ;-----------------------------------------------------------------------------
387 
388 swputcol:
389 	mov	BX,SP			; new frame pointer
390 	push	BP			; save other registers
391 	push	SI
392 	push	DI
393 	push	ES
394 
395 	mov	SI,2[BX]		; load symbol x ccord
396 	mov	DI,4[BX]		;      symbol y coord
397 	mov	BX,6[BX]		;      object address
398 	mov	BP,OB_NEWSYM[BX]	;      current symbol
399 
400 	call	setup			; setup display parameters
401 	jnz	putc0			; symbol is a point?
402 	call	drawpntc		;    YES - draw point
403 	jmp	putcret 		;	   return
404 
405 ;	plot a rastor line of a symbol to the video ram.  Register
406 ;	values at this time are
407 ;		AL - byte count of segment display
408 ;		AH - byte count of horizontal wraparound
409 ;		BX - offset from end of symbol line to beginning of next
410 ;		CL - number of bits to shift each byte
411 ;		BP - number of lines to display
412 ;		SI - pointer to first symbol byte to display
413 ;		DI - pointer to first video ram byte to use
414 
415 putc0:
416 	mov	retcode,0		; zero return code
417 putc1:
418 	push	AX			; save segment lengths AL
419 	push	DI			; save current video ram location
420 	xor	CH,CH			; reset byte rotation hold areas
421 	push	BX			; save line to line adjustment
422 	lea	BX,CS:trans		; address of byte translation table
423 	call	dispputc		; display segment
424 
425 	cmp	AH,0			; wrap around segment ?
426 	jl	putc2			;  NO-	 goto normal carry processing
427 	mov	AL,AH			;  YES-  add wrap segment length
428 	xor	AH,AH			;	 to symbol address SI
429 	add	SI,AX
430 	jmp	putc3			;	 jump carry
431 
432 putc2:
433 	cmp	CH,0			; shift carry present
434 	jz	putc3			;  NO -goto loop increment
435 	mov	DH,CH			; byte to plot
436 	call	collide 		; collision detection
437 	xor	ES:[DI],CH		; plot carry to ram
438 putc3:
439 	pop	BX			; restore line to line adjustment
440 	pop	DI			; restore old start location
441 	add	DI,BX			; destination to start of new line
442 	xchg	BX,adjrast		; exchange line to line offsets
443 	pop	AX			; restore segment lengths
444 	dec	BP			; decrement line counter
445 	jnz	putc1			; loop until line counter is 0
446 
447 	mov	AL,retcode		; return code
448 	xor	AH,AH
449 
450 putcret:
451 	pop	ES			; restore registers
452 	pop	DI
453 	pop	SI
454 	pop	BP
455 	ret
456 
457 ;	plot a rastor line segment to the video ram.  Register
458 ;	values at this time are
459 ;		AL - byte count of segment
460 ;		AH - ---don't care---
461 ;		BX - translate table address
462 ;		CL - number of bits to shift each byte
463 ;		CH - carry from previous shift
464 ;		DX - screen line length in bytes
465 ;		SI - pointer to first symbol byte to display
466 ;		DI - pointer to first video ram byte to use
467 
468 dispputc:
469 	xor	DL,DL			; clear shift carry area
470 	mov	DH,[SI] 		; symbol character
471 	shr	DX,CL			; shift right CL bits
472 	or	DH,CH			; or carry from previous shift
473 	call	collide 		; collision detection
474 	xor	ES:[DI],DH		; plot to video ram
475 	mov	CH,DL			; save carry
476 	inc	SI			; increment symbol pointer
477 	inc	DI			; video ram pointer
478 	dec	AL			; decrement byte counter
479 	jnz	dispputc		; loop until segment done
480 
481 	ret
482 
483 
484 
485 ;-----------------------------------------------------------------------------
486 
487 swpntcol:
488 	push	BP			; save BP
489 	mov	BP,SP			; new frame pointer
490 	push	SI			; save other registers
491 	push	DI
492 	push	ES
493 
494 	mov	SI,4[BP]		; load point x ccord
495 	mov	DI,6[BP]		;      point y coord
496 	mov	BP,8[BP]		;      point color
497 	call	drawpntc		; display point
498 
499 	pop	ES			; restore registers
500 	pop	DI
501 	pop	SI
502 	pop	BP
503 	ret
504 
505 
506 ;-----------------------------------------------------------------------------
507 
508 drawsym:
509 	push	BX			; save object pointer
510 
511 	push	BX			; set up mask for xor color adj.
512 	mov	BX,AX			;
513 	and	BX,3			;
514 	mov	AL,CS:cmsktab[BX]	;
515 	mov	colmask,AL		;
516 	pop	BX			;
517 
518 	call	setup			; setup display parameters
519 	jnz	ds1			; symbol is a point?
520 	call	drawpnt 		;    YES - draw point
521 	jmp	dsret			;	   return
522 
523 ;	plot a rastor line of a symbol to the video ram.  Register
524 ;	values at this time are
525 ;		AL - byte count of segment display
526 ;		AH - byte count of horizontal wraparound
527 ;		BX - offset from end of symbol line to beginning of next
528 ;		CL - number of bits to shift each byte
529 ;		BP - number of lines to display
530 ;		SI - pointer to first symbol byte to display
531 ;		DI - pointer to first video ram byte to use
532 
533 ds1:
534 	push	AX			; save segment lengths AL
535 	push	DI			; save current video ram location
536 	xor	CH,CH			; reset byte rotation hold areas
537 	push	BX			; save line to line adjustment
538 	lea	BX,CS:trans		; address of byte translation table
539 	call	dispds			; display segment
540 
541 	cmp	AH,0			; wrap around segment ?
542 	jl	ds2			;  NO-	 goto normal carry processing
543 	mov	AL,AH			;  YES-  add wrap segment length
544 	xor	AH,AH			;	 to symbol address SI
545 	add	SI,AX
546 	jmp	ds3			;	 jump carry
547 
548 ds2:
549 	cmp	CH,0			; shift carry present
550 	jz	ds3			;  NO -goto loop increment
551 	mov	DH,CH			; plot carry into ram using
552 	call	adjcolor		; color adjustment
553 	xor	ES:[DI],DH		;
554 ds3:
555 	pop	BX			; restore line to line adjustment
556 	pop	DI			; restore old start location
557 	add	DI,BX			; destination to start of new line
558 	xchg	BX,adjrast		; exchange line to line offsets
559 	pop	AX			; restore segment lengths
560 	dec	BP			; decrement line counter
561 	jnz	ds1			; loop until line counter is 0
562 
563 dsret:
564 	pop	BX			; restore registers
565 	ret
566 
567 
568 
569 ;	plot a rastor line segment to the video ram.  Register
570 ;	values at this time are
571 ;		AL - byte count of segment
572 ;		AH - ---don't care---
573 ;		BX - rastor line offset
574 ;		CL - number of bits to shift each byte
575 ;		CH - carry from previous shift
576 ;		DX - screen line length in bytes
577 ;		SI - pointer to first symbol byte to display
578 ;		DI - pointer to first video ram byte to use
579 
580 dispds:
581 	xor	DL,DL			; clear shift carry area
582 	mov	DH,[SI] 		; symbol character
583 	shr	DX,CL			; shift right CL bits
584 	or	DH,CH			; or carry from previous shift
585 
586 	call	adjcolor		; adjust symbol for color of object
587 
588 	xor	ES:[DI],DH		; plot to video ram
589 	mov	CH,DL			; save carry
590 	inc	SI			; increment symbol pointer
591 	inc	DI			; video ram pointer
592 	dec	AL			; decrement byte counter
593 	jnz	dispds			; loop until segment done
594 
595 	ret
596 
597 
598 
599 ;-----------------------------------------------------------------------------
600 
601 drawpnt:
602 
603 ;	invert row requested
604 
605 	sub	DI,(SCR_HGHT - 1 )
606 	neg	DI
607 
608 ;	calculate the number of bits to rotate the colour
609 ;	the column position is not byte aligned.  (CL)
610 
611 	mov	CX,SI			; pixel column requested
612 	and	CL,03H			; pixel offset in CL
613 	sub	CL,3			; inverted
614 	neg	CL
615 	shl	CL,1			; bits to rotate in CL
616 
617 ;	determine first video ram byte to use and store in AX
618 
619 	mov	AX,DI			; starting row in AX.
620 	shr	AX,1			; divide by 2 for even/odd rastor lines
621 	mov	DX,SCR_WDTH
622 	mul	DX			; end of previous row in DX:AX
623 	add	AX,SI			; pixel offset in DX:AX
624 	adc	DX,0			; handle carry into DX
625 	shr	DX,1			; shift DX:AX by 2
626 	rcr	AX,1
627 	shr	DX,1
628 	rcr	AX,1			; byte offset in AX
629 	mov	SI,AX			;	      in SI
630 
631 ;	adjust byte offset if line odd
632 
633 	test	DI,01H			; Row odd?
634 	jz	dp1			;   NO - skip
635 	add	SI,disproff		; first video ram byte
636 dp1:
637 	mov	AX,dispseg		; save video ram segment
638 	mov	ES,AX
639 	add	SI,dispoff
640 
641 ;	plot the current colour, or exclusive or the current colour based
642 ;	on the first bit of the colour.
643 
644 	mov	AX,BP
645 	and	AL,83H
646 	test	AL,80H
647 	jnz	dp2
648 
649 	mov	CH,03H
650 	shl	CH,CL
651 	mov	DH,ES:[SI]
652 	and	CH,DH
653 	xor	DH,CH
654 	rol	AL,CL
655 	or	DH,AL
656 	mov	ES:[SI],DH
657 	ret
658 
659 dp2:	and	AL,7FH
660 	shl	AL,CL
661 	xor	ES:[SI],AL
662 	ret
663 
664 
665 
666 ;-----------------------------------------------------------------------------
667 
668 drawpntc:
669 
670 ;	invert row requested
671 
672 	sub	DI,(SCR_HGHT - 1 )
673 	neg	DI
674 
675 ;	calculate the number of bits to rotate the colour
676 ;	the column position is not byte aligned.  (CL)
677 
678 	mov	CX,SI			; pixel column requested
679 	and	CL,03H			; pixel offset in CL
680 	sub	CL,3			; inverted
681 	neg	CL
682 	shl	CL,1			; bits to rotate in CL
683 
684 ;	determine first video ram byte to use and store in AX
685 
686 	mov	AX,DI			; starting row in AX.
687 	shr	AX,1			; divide by 2 for even/odd rastor lines
688 	mov	DX,SCR_WDTH
689 	mul	DX			; end of previous row in DX:AX
690 	add	AX,SI			; pixel offset in DX:AX
691 	adc	DX,0			; handle carry into DX
692 	shr	DX,1			; shift DX:AX by 2
693 	rcr	AX,1
694 	shr	DX,1
695 	rcr	AX,1			; byte offset in AX
696 	mov	SI,AX			;	      in BX
697 
698 ;	adjust byte offset if line odd
699 
700 	test	DI,01H			; Row odd?
701 	jz	dpc1			;   NO - skip
702 	add	SI,disproff		; first video ram byte
703 dpc1:
704 	mov	AX,dispseg		; save video ram segment
705 	mov	ES,AX
706 	add	SI,dispoff
707 
708 ;	create	mask to return colour of point previous to plot
709 
710 	mov	CH,03H
711 	shl	CH,CL
712 	and	CH,ES:[SI]
713 
714 ;	plot the current colour, or exclusive or the current colour based
715 ;	on the first bit of the colour.
716 
717 	mov	AX,BP
718 	and	AL,83H
719 	test	AL,80H
720 	jnz	dpc2
721 
722 	xor	ES:[SI],CH
723 	rol	AL,CL
724 	or	ES:[SI],AL
725 	jmp	dpc3
726 
727 dpc2:	and	AL,7FH
728 	shl	AL,CL
729 	xor	ES:[SI],AL
730 
731 ;
732 ;	return the color code found
733 ;
734 
735 dpc3:
736 	shr	CH,CL
737 	mov	AL,CH
738 	xor	AH,AH
739 	ret
740 
741 
742 ;----------------------------------------------------------------------------
743 
744 ;
745 ;	if symbol height and width are 1, signal point code
746 ;
747 
748 setup:
749 	cmp	word ptr OB_SYMHGT[BX],1
750 	jne	stp1
751 	cmp	word ptr OB_SYMWDT[BX],1
752 	jne	stp1
753 	ret
754 
755 ;	invert row requested
756 
757 stp1:
758 	sub	DI,(SCR_HGHT - 1 )
759 	neg	DI
760 
761 ;	calculate the number of bits to rotate a symbol byte if
762 ;	the column position is not byte aligned.  (CL)
763 
764 	mov	CX,SI			; pixel column requested
765 	and	CL,03H			; bit offset in CL
766 	shl	CL,1			; bits to rotate in CL
767 
768 ;	calculate byte count for on scan line taking into account vertical
769 ;	screen boundaries.  Place in AL.    Place any overwrap in AH.
770 
771 	mov	AX,OB_SYMWDT[BX]	; symbol width in pixels
772 	shr	AX,1			;	  then in bytes in AL
773 	shr	AX,1
774 
775 	mov	DX,SI			; pixel column requested
776 	shr	DX,1			; pixel byte offset in DL
777 	shr	DX,1
778 	sub	DL,SCR_LINW		; screen width in bytes
779 	neg	DL			; available bytes for symbol in DL
780 
781 	mov	AH,AL
782 	sub	AH,DL			; symbol width less than available?
783 	jle	stp2			; YES - skip
784 	mov	AL,DL			; NO -	available bytes in AL
785 stp2:
786 
787 ;	calculate line count for the symbol taking into account horizontal
788 ;	boundaries, and push in stack
789 
790 	push	AX			; save AX, segment length count
791 	mov	AX,OB_SYMHGT[BX]	; symbol height in AX
792 	mov	DX,SCR_HGHT		; screen height
793 	sub	DX,DI			; available lines for symbol in DX
794 	cmp	AX,DX			; symbol height less than available?
795 	jbe	stp3			; YES - skip
796 	mov	AX,DX			; NO -	available lines in DI
797 stp3:
798 	push	AX
799 
800 ;	determine first video ram byte to use and store in AX
801 
802 	mov	AX,DI			; starting row in AX.
803 	shr	AX,1			; divide by 2 for even/odd rastor lines
804 	mov	DX,SCR_WDTH
805 	mul	DX			; end of previous row in DX:AX
806 	add	AX,SI			; pixel offset in DX:AX
807 	adc	DX,0			; handle carry into DX
808 	shr	DX,1			; shift DX:AX by 2
809 	rcr	AX,1
810 	shr	DX,1
811 	rcr	AX,1			; byte offset in AX
812 
813 ;	store rastor line width in DX, and calculate line to line offsets
814 ;	as 'rastor line offset' and DX - 'rastor line offset'
815 
816 	mov	DX,SCR_LINW		; line width in bytes in DX
817 	mov	BX,disproff		; even to odd line offset in BX
818 	mov	adjrast,DX
819 	sub	adjrast,BX		; odd to even line offset
820 
821 ;	adjust first video ram byte to use, and reverse rastor line
822 ;	offsets if starting on an odd line
823 
824 	test	DI,01H			; Row odd?
825 	jz	stp4			;   NO - skip
826 	add	AX,BX			; first video ram byte
827 	xchg	BX,adjrast		; exchange offsets
828 stp4:
829 
830 ;	setup final registers for display
831 
832 	mov	SI,dispseg		; save video ram segment
833 	mov	ES,SI
834 	mov	SI,BP			; access pointer to symbol
835 	mov	DI,AX			; set video ram destination
836 	add	DI,dispoff
837 	pop	BP			; line count for display
838 	pop	AX			; restore segment length
839 
840 	or	AX,AX			; return not zero
841 	ret
842 
843 
844 ;-----------------------------------------------------------------------------
845 ;
846 ;	routine to perform collision detection between DH and ES:[DI]
847 ;
848 
849 collide:
850 	push	AX			; save AX
851 	mov	AL,DH			; byte to plot in AL
852 	xlat	CS:trans		; translate
853 	and	AL,ES:[DI]		; non-zero if collision
854 	or	retcode,AL
855 	pop	AX
856 	ret
857 
858 
859 ;------------------------------------------------------------------------------
860 ;
861 ;	routine to adjust the color of an object
862 ;
863 
864 adjcolor:
865 	push	AX			; save AX
866 	mov	AL,DH			; byte to plot in AL
867 	xlat	CS:trans		; translate to ones for xor
868 	and	AL,colmask		; mask off if color 1
869 	xor	DH,AL			; convert 01-10 if color 2
870 	pop	AX			; restore AX
871 	ret
872 
873 ;
874 ;	translation table corresponding to any 2-bit non zero portion
875 ;	of a byte set to 11.
876 ;
877 trans	db	00H,03H,03H,03H,0CH,0FH,0FH,0FH,0CH,0FH,0FH,0FH,0CH,0FH,0FH,0FH
878 	db	30H,33H,33H,33H,3CH,3FH,3FH,3FH,3CH,3FH,3FH,3FH,3CH,3FH,3FH,3FH
879 	db	30H,33H,33H,33H,3CH,3FH,3FH,3FH,3CH,3FH,3FH,3FH,3CH,3FH,3FH,3FH
880 	db	30H,33H,33H,33H,3CH,3FH,3FH,3FH,3CH,3FH,3FH,3FH,3CH,3FH,3FH,3FH
881 	db	0C0H,0C3H,0C3H,0C3H,0CCH,0CFH,0CFH,0CFH,0CCH,0CFH,0CFH,0CFH,0CCH,0CFH,0CFH,0CFH
882 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
883 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
884 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
885 	db	0C0H,0C3H,0C3H,0C3H,0CCH,0CFH,0CFH,0CFH,0CCH,0CFH,0CFH,0CFH,0CCH,0CFH,0CFH,0CFH
886 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
887 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
888 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
889 	db	0C0H,0C3H,0C3H,0C3H,0CCH,0CFH,0CFH,0CFH,0CCH,0CFH,0CFH,0CFH,0CCH,0CFH,0CFH,0CFH
890 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
891 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
892 	db	0F0H,0F3H,0F3H,0F3H,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH,0FCH,0FFH,0FFH,0FFH
893 
894 ;
895 ;	mask for xor color adjustments
896 ;
897 
898 cmsktab db	0,0,0FFH,0
899 
900 
901 
902 ;------------------------------------------------------------------------------
903 ;
904 ;	get_type();
905 ;	set_type( type );
906 ;
907 ;	get/set screen types
908 ;
909 
910 
911 get_type:
912 	mov	AH,15			; get state function
913 	int	10H			; get video state in AL
914 	xor	AH,AH			;		  in AX
915 	ret				; return
916 
917 
918 set_type:
919 	push	BP			; save frame pointer
920 	mov	BP,SP			; new frame pointer
921 	mov	AL,@AB[BP]		; get mode in AL
922 	xor	AH,AH			; set video mode function
923 	int	10H			; do it
924 	pop	BP			; restore frame pointer
925 	ret				; return
926 
927 
928 
929 ;------------------------------------------------------------------------------
930 ;
931 ;	setvdisp();
932 ;	setadisp();
933 ;
934 ;	set current display to video/alternate buffer
935 ;
936 
937 
938 setvdisp:
939 	mov	word ptr dispseg,SCR_SEGM
940 	mov	word ptr dispoff,0
941 	mov	word ptr disproff,SCR_ROFF
942 	ret
943 
944 
945 setadisp:
946 	mov	word ptr dispseg,DS
947 	mov	word ptr dispoff,( offset DGROUP:auxdisp - 1000H )
948 	mov	word ptr disproff,1000H
949 	ret				; return
950 
951 
952 
953 
954 	.DATA
955 
956 adjrast  dw	?			; rastor line offset save area
957 colmask  db	?			;
958 retcode  db	?			; return code
959 grndsave db	SCR_WDTH dup (?)	; ground save area
960 dispseg  dw	?			; Display segment
961 dispoff  dw	?			;	  offset
962 disproff dw	?			;	  inter bank offset
963 
964 	extrn	displx:word		; Display left and right bounds
965 	extrn	disprx:word
966 	extrn	dispdx:word		; Display shift
967 	extrn	auxdisp:byte		; auxiliary display buffer
968 	extrn	ground:byte		; Ground height by pixel
969 	extrn	dispinit:word		; Initialized display flag
970 	extrn	forcdisp:word		; Force display flag
971 	extrn	objtop:word		; First object in object list
972 	extrn	deltop:word		; First object in deleted object list
973 	extrn	splatox:word		; display splatted ox
974 	extrn	oxsplatted:word 	; an ox has bben splatted
975 
976 	end
977 