1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19*/
20//
21// surf8.s
22// x86 assembly-language 8 bpp surface block drawing code.
23//
24
25#include "asm_i386.h"
26#include "quakeasm.h"
27#include "asm_draw.h"
28
29#if	id386
30
31	.data
32
33sb_v:		.long	0
34
35	.text
36
37	.align 4
38.globl C(R_Surf8Start)
39C(R_Surf8Start):
40
41//----------------------------------------------------------------------
42// Surface block drawer for mip level 0
43//----------------------------------------------------------------------
44
45	.align 4
46.globl C(R_DrawSurfaceBlock8_mip0)
47C(R_DrawSurfaceBlock8_mip0):
48	pushl	%ebp				// preserve caller's stack frame
49	pushl	%edi
50	pushl	%esi				// preserve register variables
51	pushl	%ebx
52
53//		for (v=0 ; v<numvblocks ; v++)
54//		{
55	movl	C(r_lightptr),%ebx
56	movl	C(r_numvblocks),%eax
57
58	movl	%eax,sb_v
59	movl	C(prowdestbase),%edi
60
61	movl	C(pbasesource),%esi
62
63Lv_loop_mip0:
64
65//			lightleft = lightptr[0];
66//			lightright = lightptr[1];
67//			lightdelta = (lightleft - lightright) & 0xFFFFF;
68	movl	(%ebx),%eax			// lightleft
69	movl	4(%ebx),%edx		// lightright
70
71	movl	%eax,%ebp
72	movl	C(r_lightwidth),%ecx
73
74	movl	%edx,C(lightright)
75	subl	%edx,%ebp
76
77	andl	$0xFFFFF,%ebp
78	leal	(%ebx,%ecx,4),%ebx
79
80//			lightptr += lightwidth;
81	movl	%ebx,C(r_lightptr)
82
83//			lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
84//			lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
85//			lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
86//					0xF0000000;
87	movl	4(%ebx),%ecx	// lightptr[1]
88	movl	(%ebx),%ebx		// lightptr[0]
89
90	subl	%eax,%ebx
91	subl	%edx,%ecx
92
93	sarl	$4,%ecx
94	orl		$0xF0000000,%ebp
95
96	sarl	$4,%ebx
97	movl	%ecx,C(lightrightstep)
98
99	subl	%ecx,%ebx
100	andl	$0xFFFFF,%ebx
101
102	orl		$0xF0000000,%ebx
103	subl	%ecx,%ecx	// high word must be 0 in loop for addressing
104
105	movl	%ebx,C(lightdeltastep)
106	subl	%ebx,%ebx	// high word must be 0 in loop for addressing
107
108Lblockloop8_mip0:
109	movl	%ebp,C(lightdelta)
110	movb	14(%esi),%cl
111
112	sarl	$4,%ebp
113	movb	%dh,%bh
114
115	movb	15(%esi),%bl
116	addl	%ebp,%edx
117
118	movb	%dh,%ch
119	addl	%ebp,%edx
120
121	movb	0x12345678(%ebx),%ah
122LBPatch0:
123	movb	13(%esi),%bl
124
125	movb	0x12345678(%ecx),%al
126LBPatch1:
127	movb	12(%esi),%cl
128
129	movb	%dh,%bh
130	addl	%ebp,%edx
131
132	rorl	$16,%eax
133	movb	%dh,%ch
134
135	addl	%ebp,%edx
136	movb	0x12345678(%ebx),%ah
137LBPatch2:
138
139	movb	11(%esi),%bl
140	movb	0x12345678(%ecx),%al
141LBPatch3:
142
143	movb	10(%esi),%cl
144	movl	%eax,12(%edi)
145
146	movb	%dh,%bh
147	addl	%ebp,%edx
148
149	movb	%dh,%ch
150	addl	%ebp,%edx
151
152	movb	0x12345678(%ebx),%ah
153LBPatch4:
154	movb	9(%esi),%bl
155
156	movb	0x12345678(%ecx),%al
157LBPatch5:
158	movb	8(%esi),%cl
159
160	movb	%dh,%bh
161	addl	%ebp,%edx
162
163	rorl	$16,%eax
164	movb	%dh,%ch
165
166	addl	%ebp,%edx
167	movb	0x12345678(%ebx),%ah
168LBPatch6:
169
170	movb	7(%esi),%bl
171	movb	0x12345678(%ecx),%al
172LBPatch7:
173
174	movb	6(%esi),%cl
175	movl	%eax,8(%edi)
176
177	movb	%dh,%bh
178	addl	%ebp,%edx
179
180	movb	%dh,%ch
181	addl	%ebp,%edx
182
183	movb	0x12345678(%ebx),%ah
184LBPatch8:
185	movb	5(%esi),%bl
186
187	movb	0x12345678(%ecx),%al
188LBPatch9:
189	movb	4(%esi),%cl
190
191	movb	%dh,%bh
192	addl	%ebp,%edx
193
194	rorl	$16,%eax
195	movb	%dh,%ch
196
197	addl	%ebp,%edx
198	movb	0x12345678(%ebx),%ah
199LBPatch10:
200
201	movb	3(%esi),%bl
202	movb	0x12345678(%ecx),%al
203LBPatch11:
204
205	movb	2(%esi),%cl
206	movl	%eax,4(%edi)
207
208	movb	%dh,%bh
209	addl	%ebp,%edx
210
211	movb	%dh,%ch
212	addl	%ebp,%edx
213
214	movb	0x12345678(%ebx),%ah
215LBPatch12:
216	movb	1(%esi),%bl
217
218	movb	0x12345678(%ecx),%al
219LBPatch13:
220	movb	(%esi),%cl
221
222	movb	%dh,%bh
223	addl	%ebp,%edx
224
225	rorl	$16,%eax
226	movb	%dh,%ch
227
228	movb	0x12345678(%ebx),%ah
229LBPatch14:
230	movl	C(lightright),%edx
231
232	movb	0x12345678(%ecx),%al
233LBPatch15:
234	movl	C(lightdelta),%ebp
235
236	movl	%eax,(%edi)
237
238	addl	C(sourcetstep),%esi
239	addl	C(surfrowbytes),%edi
240
241	addl	C(lightrightstep),%edx
242	addl	C(lightdeltastep),%ebp
243
244	movl	%edx,C(lightright)
245	jc		Lblockloop8_mip0
246
247//			if (pbasesource >= r_sourcemax)
248//				pbasesource -= stepback;
249
250	cmpl	C(r_sourcemax),%esi
251	jb		LSkip_mip0
252	subl	C(r_stepback),%esi
253LSkip_mip0:
254
255	movl	C(r_lightptr),%ebx
256	decl	sb_v
257
258	jnz		Lv_loop_mip0
259
260	popl	%ebx				// restore register variables
261	popl	%esi
262	popl	%edi
263	popl	%ebp				// restore the caller's stack frame
264	ret
265
266
267//----------------------------------------------------------------------
268// Surface block drawer for mip level 1
269//----------------------------------------------------------------------
270
271	.align 4
272.globl C(R_DrawSurfaceBlock8_mip1)
273C(R_DrawSurfaceBlock8_mip1):
274	pushl	%ebp				// preserve caller's stack frame
275	pushl	%edi
276	pushl	%esi				// preserve register variables
277	pushl	%ebx
278
279//		for (v=0 ; v<numvblocks ; v++)
280//		{
281	movl	C(r_lightptr),%ebx
282	movl	C(r_numvblocks),%eax
283
284	movl	%eax,sb_v
285	movl	C(prowdestbase),%edi
286
287	movl	C(pbasesource),%esi
288
289Lv_loop_mip1:
290
291//			lightleft = lightptr[0];
292//			lightright = lightptr[1];
293//			lightdelta = (lightleft - lightright) & 0xFFFFF;
294	movl	(%ebx),%eax			// lightleft
295	movl	4(%ebx),%edx		// lightright
296
297	movl	%eax,%ebp
298	movl	C(r_lightwidth),%ecx
299
300	movl	%edx,C(lightright)
301	subl	%edx,%ebp
302
303	andl	$0xFFFFF,%ebp
304	leal	(%ebx,%ecx,4),%ebx
305
306//			lightptr += lightwidth;
307	movl	%ebx,C(r_lightptr)
308
309//			lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
310//			lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
311//			lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
312//					0xF0000000;
313	movl	4(%ebx),%ecx	// lightptr[1]
314	movl	(%ebx),%ebx		// lightptr[0]
315
316	subl	%eax,%ebx
317	subl	%edx,%ecx
318
319	sarl	$3,%ecx
320	orl		$0x70000000,%ebp
321
322	sarl	$3,%ebx
323	movl	%ecx,C(lightrightstep)
324
325	subl	%ecx,%ebx
326	andl	$0xFFFFF,%ebx
327
328	orl		$0xF0000000,%ebx
329	subl	%ecx,%ecx	// high word must be 0 in loop for addressing
330
331	movl	%ebx,C(lightdeltastep)
332	subl	%ebx,%ebx	// high word must be 0 in loop for addressing
333
334Lblockloop8_mip1:
335	movl	%ebp,C(lightdelta)
336	movb	6(%esi),%cl
337
338	sarl	$3,%ebp
339	movb	%dh,%bh
340
341	movb	7(%esi),%bl
342	addl	%ebp,%edx
343
344	movb	%dh,%ch
345	addl	%ebp,%edx
346
347	movb	0x12345678(%ebx),%ah
348LBPatch22:
349	movb	5(%esi),%bl
350
351	movb	0x12345678(%ecx),%al
352LBPatch23:
353	movb	4(%esi),%cl
354
355	movb	%dh,%bh
356	addl	%ebp,%edx
357
358	rorl	$16,%eax
359	movb	%dh,%ch
360
361	addl	%ebp,%edx
362	movb	0x12345678(%ebx),%ah
363LBPatch24:
364
365	movb	3(%esi),%bl
366	movb	0x12345678(%ecx),%al
367LBPatch25:
368
369	movb	2(%esi),%cl
370	movl	%eax,4(%edi)
371
372	movb	%dh,%bh
373	addl	%ebp,%edx
374
375	movb	%dh,%ch
376	addl	%ebp,%edx
377
378	movb	0x12345678(%ebx),%ah
379LBPatch26:
380	movb	1(%esi),%bl
381
382	movb	0x12345678(%ecx),%al
383LBPatch27:
384	movb	(%esi),%cl
385
386	movb	%dh,%bh
387	addl	%ebp,%edx
388
389	rorl	$16,%eax
390	movb	%dh,%ch
391
392	movb	0x12345678(%ebx),%ah
393LBPatch28:
394	movl	C(lightright),%edx
395
396	movb	0x12345678(%ecx),%al
397LBPatch29:
398	movl	C(lightdelta),%ebp
399
400	movl	%eax,(%edi)
401	movl	C(sourcetstep),%eax
402
403	addl	%eax,%esi
404	movl	C(surfrowbytes),%eax
405
406	addl	%eax,%edi
407	movl	C(lightrightstep),%eax
408
409	addl	%eax,%edx
410	movl	C(lightdeltastep),%eax
411
412	addl	%eax,%ebp
413	movl	%edx,C(lightright)
414
415	jc		Lblockloop8_mip1
416
417//			if (pbasesource >= r_sourcemax)
418//				pbasesource -= stepback;
419
420	cmpl	C(r_sourcemax),%esi
421	jb		LSkip_mip1
422	subl	C(r_stepback),%esi
423LSkip_mip1:
424
425	movl	C(r_lightptr),%ebx
426	decl	sb_v
427
428	jnz		Lv_loop_mip1
429
430	popl	%ebx				// restore register variables
431	popl	%esi
432	popl	%edi
433	popl	%ebp				// restore the caller's stack frame
434	ret
435
436
437//----------------------------------------------------------------------
438// Surface block drawer for mip level 2
439//----------------------------------------------------------------------
440
441	.align 4
442.globl C(R_DrawSurfaceBlock8_mip2)
443C(R_DrawSurfaceBlock8_mip2):
444	pushl	%ebp				// preserve caller's stack frame
445	pushl	%edi
446	pushl	%esi				// preserve register variables
447	pushl	%ebx
448
449//		for (v=0 ; v<numvblocks ; v++)
450//		{
451	movl	C(r_lightptr),%ebx
452	movl	C(r_numvblocks),%eax
453
454	movl	%eax,sb_v
455	movl	C(prowdestbase),%edi
456
457	movl	C(pbasesource),%esi
458
459Lv_loop_mip2:
460
461//			lightleft = lightptr[0];
462//			lightright = lightptr[1];
463//			lightdelta = (lightleft - lightright) & 0xFFFFF;
464	movl	(%ebx),%eax			// lightleft
465	movl	4(%ebx),%edx		// lightright
466
467	movl	%eax,%ebp
468	movl	C(r_lightwidth),%ecx
469
470	movl	%edx,C(lightright)
471	subl	%edx,%ebp
472
473	andl	$0xFFFFF,%ebp
474	leal	(%ebx,%ecx,4),%ebx
475
476//			lightptr += lightwidth;
477	movl	%ebx,C(r_lightptr)
478
479//			lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
480//			lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
481//			lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
482//					0xF0000000;
483	movl	4(%ebx),%ecx	// lightptr[1]
484	movl	(%ebx),%ebx		// lightptr[0]
485
486	subl	%eax,%ebx
487	subl	%edx,%ecx
488
489	sarl	$2,%ecx
490	orl		$0x30000000,%ebp
491
492	sarl	$2,%ebx
493	movl	%ecx,C(lightrightstep)
494
495	subl	%ecx,%ebx
496
497	andl	$0xFFFFF,%ebx
498
499	orl		$0xF0000000,%ebx
500	subl	%ecx,%ecx	// high word must be 0 in loop for addressing
501
502	movl	%ebx,C(lightdeltastep)
503	subl	%ebx,%ebx	// high word must be 0 in loop for addressing
504
505Lblockloop8_mip2:
506	movl	%ebp,C(lightdelta)
507	movb	2(%esi),%cl
508
509	sarl	$2,%ebp
510	movb	%dh,%bh
511
512	movb	3(%esi),%bl
513	addl	%ebp,%edx
514
515	movb	%dh,%ch
516	addl	%ebp,%edx
517
518	movb	0x12345678(%ebx),%ah
519LBPatch18:
520	movb	1(%esi),%bl
521
522	movb	0x12345678(%ecx),%al
523LBPatch19:
524	movb	(%esi),%cl
525
526	movb	%dh,%bh
527	addl	%ebp,%edx
528
529	rorl	$16,%eax
530	movb	%dh,%ch
531
532	movb	0x12345678(%ebx),%ah
533LBPatch20:
534	movl	C(lightright),%edx
535
536	movb	0x12345678(%ecx),%al
537LBPatch21:
538	movl	C(lightdelta),%ebp
539
540	movl	%eax,(%edi)
541	movl	C(sourcetstep),%eax
542
543	addl	%eax,%esi
544	movl	C(surfrowbytes),%eax
545
546	addl	%eax,%edi
547	movl	C(lightrightstep),%eax
548
549	addl	%eax,%edx
550	movl	C(lightdeltastep),%eax
551
552	addl	%eax,%ebp
553	movl	%edx,C(lightright)
554
555	jc		Lblockloop8_mip2
556
557//			if (pbasesource >= r_sourcemax)
558//				pbasesource -= stepback;
559
560	cmpl	C(r_sourcemax),%esi
561	jb		LSkip_mip2
562	subl	C(r_stepback),%esi
563LSkip_mip2:
564
565	movl	C(r_lightptr),%ebx
566	decl	sb_v
567
568	jnz		Lv_loop_mip2
569
570	popl	%ebx				// restore register variables
571	popl	%esi
572	popl	%edi
573	popl	%ebp				// restore the caller's stack frame
574	ret
575
576
577//----------------------------------------------------------------------
578// Surface block drawer for mip level 3
579//----------------------------------------------------------------------
580
581	.align 4
582.globl C(R_DrawSurfaceBlock8_mip3)
583C(R_DrawSurfaceBlock8_mip3):
584	pushl	%ebp				// preserve caller's stack frame
585	pushl	%edi
586	pushl	%esi				// preserve register variables
587	pushl	%ebx
588
589//		for (v=0 ; v<numvblocks ; v++)
590//		{
591	movl	C(r_lightptr),%ebx
592	movl	C(r_numvblocks),%eax
593
594	movl	%eax,sb_v
595	movl	C(prowdestbase),%edi
596
597	movl	C(pbasesource),%esi
598
599Lv_loop_mip3:
600
601//			lightleft = lightptr[0];
602//			lightright = lightptr[1];
603//			lightdelta = (lightleft - lightright) & 0xFFFFF;
604	movl	(%ebx),%eax			// lightleft
605	movl	4(%ebx),%edx		// lightright
606
607	movl	%eax,%ebp
608	movl	C(r_lightwidth),%ecx
609
610	movl	%edx,C(lightright)
611	subl	%edx,%ebp
612
613	andl	$0xFFFFF,%ebp
614	leal	(%ebx,%ecx,4),%ebx
615
616	movl	%ebp,C(lightdelta)
617//			lightptr += lightwidth;
618	movl	%ebx,C(r_lightptr)
619
620//			lightleftstep = (lightptr[0] - lightleft) >> blockdivshift;
621//			lightrightstep = (lightptr[1] - lightright) >> blockdivshift;
622//			lightdeltastep = ((lightleftstep - lightrightstep) & 0xFFFFF) |
623//					0xF0000000;
624	movl	4(%ebx),%ecx	// lightptr[1]
625	movl	(%ebx),%ebx		// lightptr[0]
626
627	subl	%eax,%ebx
628	subl	%edx,%ecx
629
630	sarl	$1,%ecx
631
632	sarl	$1,%ebx
633	movl	%ecx,C(lightrightstep)
634
635	subl	%ecx,%ebx
636	andl	$0xFFFFF,%ebx
637
638	sarl	$1,%ebp
639	orl		$0xF0000000,%ebx
640
641	movl	%ebx,C(lightdeltastep)
642	subl	%ebx,%ebx	// high word must be 0 in loop for addressing
643
644	movb	1(%esi),%bl
645	subl	%ecx,%ecx	// high word must be 0 in loop for addressing
646
647	movb	%dh,%bh
648	movb	(%esi),%cl
649
650	addl	%ebp,%edx
651	movb	%dh,%ch
652
653	movb	0x12345678(%ebx),%al
654LBPatch16:
655	movl	C(lightright),%edx
656
657	movb	%al,1(%edi)
658	movb	0x12345678(%ecx),%al
659LBPatch17:
660
661	movb	%al,(%edi)
662	movl	C(sourcetstep),%eax
663
664	addl	%eax,%esi
665	movl	C(surfrowbytes),%eax
666
667	addl	%eax,%edi
668	movl	C(lightdeltastep),%eax
669
670	movl	C(lightdelta),%ebp
671	movb	(%esi),%cl
672
673	addl	%eax,%ebp
674	movl	C(lightrightstep),%eax
675
676	sarl	$1,%ebp
677	addl	%eax,%edx
678
679	movb	%dh,%bh
680	movb	1(%esi),%bl
681
682	addl	%ebp,%edx
683	movb	%dh,%ch
684
685	movb	0x12345678(%ebx),%al
686LBPatch30:
687	movl	C(sourcetstep),%edx
688
689	movb	%al,1(%edi)
690	movb	0x12345678(%ecx),%al
691LBPatch31:
692
693	movb	%al,(%edi)
694	movl	C(surfrowbytes),%ebp
695
696	addl	%edx,%esi
697	addl	%ebp,%edi
698
699//			if (pbasesource >= r_sourcemax)
700//				pbasesource -= stepback;
701
702	cmpl	C(r_sourcemax),%esi
703	jb		LSkip_mip3
704	subl	C(r_stepback),%esi
705LSkip_mip3:
706
707	movl	C(r_lightptr),%ebx
708	decl	sb_v
709
710	jnz		Lv_loop_mip3
711
712	popl	%ebx				// restore register variables
713	popl	%esi
714	popl	%edi
715	popl	%ebp				// restore the caller's stack frame
716	ret
717
718
719.globl C(R_Surf8End)
720C(R_Surf8End):
721
722//----------------------------------------------------------------------
723// Code patching routines
724//----------------------------------------------------------------------
725	.data
726
727	.align 4
728LPatchTable8:
729	.long	LBPatch0-4
730	.long	LBPatch1-4
731	.long	LBPatch2-4
732	.long	LBPatch3-4
733	.long	LBPatch4-4
734	.long	LBPatch5-4
735	.long	LBPatch6-4
736	.long	LBPatch7-4
737	.long	LBPatch8-4
738	.long	LBPatch9-4
739	.long	LBPatch10-4
740	.long	LBPatch11-4
741	.long	LBPatch12-4
742	.long	LBPatch13-4
743	.long	LBPatch14-4
744	.long	LBPatch15-4
745	.long	LBPatch16-4
746	.long	LBPatch17-4
747	.long	LBPatch18-4
748	.long	LBPatch19-4
749	.long	LBPatch20-4
750	.long	LBPatch21-4
751	.long	LBPatch22-4
752	.long	LBPatch23-4
753	.long	LBPatch24-4
754	.long	LBPatch25-4
755	.long	LBPatch26-4
756	.long	LBPatch27-4
757	.long	LBPatch28-4
758	.long	LBPatch29-4
759	.long	LBPatch30-4
760	.long	LBPatch31-4
761
762	.text
763
764	.align 4
765.globl C(R_Surf8Patch)
766C(R_Surf8Patch):
767	pushl	%ebx
768
769	movl	C(colormap),%eax
770	movl	$LPatchTable8,%ebx
771	movl	$32,%ecx
772LPatchLoop8:
773	movl	(%ebx),%edx
774	addl	$4,%ebx
775	movl	%eax,(%edx)
776	decl	%ecx
777	jnz		LPatchLoop8
778
779	popl	%ebx
780
781	ret
782
783#endif	// id386
784