//These are #define's for switching between old R9 polymap/3d and the current ones, for testing purposes.
//O is the old (R9) version of the function(s), which works properly in DOS *ONLY*. Don't bother trying them in windows, they'll just crash.
//N is the current version (being worked on now) of the function(s). See the 'current status' below for more on these.
//You can find these functions in opoly3d.h, opolymap.h, npoly3d.h, and npolymap.h.
#ifdef WINDOWS
#define NPOLY3D
#define NPOLYMAP
#else
#define OPOLY3D
#define OPOLYMAP
#endif

/*

Current status:
	These should be checked, see if they're still the case:
		NPOLY3D looks right in DOS
		NPOLYMAP is doing something screwy with distance - it looks like a cutoff value making everything further than that brighter than usual.
		Text looks wrong with npolymap in DOS, but normal in windows.
	
	
	-SL
*/

/*

	The Third Flare.
	----------------
	Full-3D Graphic Engine.

	Funzioni a 32-bit per disegnare poligoni 3d riempiti di colore
	in grafica 320x200x256. Sul Pentium Š una cannonata: una media
	di 12000 poligoni al secondo, da workstation, con 75 MhZ.

	- Non si deve mai usare il colore nr. 255 per
	  tracciare qualcosa nell'area di lavoro, quando si usa questa
	  routine, perch‚ lo utilizza solo lei per delimitare i poligoni.
	  Se si vuole usare un altro colore per delimitarli, bisogna
	  cambiare tutti i valori 255 nelle funzioni "Segmento" e "poly3d".

	Chiamare initscanlines prima di tracciare alcunchŠ,
	senn• non traccia una bella sega.

	Nato (incredibile a dirsi) per Alpha Dream.
	Ultima revisione 21 Dicembre 1997.

	Aggiunte: ottimizzazione conversioni 3d-2d, 23.6.1997;
		  ciclo di fast-load dei vertici quando sono tutti di fronte
		  alla videocamera (cioŠ quasi sempre), 23.6.1997;
		  clipping intelligente, ottobre '97;
		  texture mapping, febbraio '98.

*/
#include "defs.h"

#ifndef __FLOAT_H
#include <float.h>
#endif

#ifndef __ALLOC_H
#include <alloc.h>
#endif

#ifndef __MATH_H
#include <math.h>
#endif

#ifndef __IO_H
#include <io.h>
#endif

/* Dati sui poligoni (quanti vertici al massimo si pensa di fare). */

#ifndef VERTICI_PER_POLIGONO
#define VERTICI_PER_POLIGONO 4
#endif

/* Area di visualizzazione. */

#ifndef larghezza
#define larghezza 300
#endif

#ifndef altezza
#define altezza   180
#endif

#ifndef x_centro
#define x_centro  160
#endif

#ifndef y_centro
#define y_centro  100
#endif

/*

	Controllo visualizzazione.

					*/

float uneg = 100; /* Un fatto particolarmente curioso: uneg rappresenta
		   la distanza minima alla quale un certo punto non viene
		   considerato alle spalle dell'osservatore. Il bello Š
		   che l'ideazione di questa sigla (ricordo che si
		   pronuncia u-neg) risale a cosŤ tanto tempo fa
		   (si parla della prima versione di Smallest, ovvero
		   dell'aprile '92, attualmente pi— di 5 anni fa)
		   che non ricordo assolutamente che cosa significhi
		   quest'acronimo (era un acronimo, ma chiss… come mi
		   venne in mente, forse da user-neg, negativo all'utente,
		   in riferimento all'effetto di inversione del segno
		   dato dalle funzioni prospettiche quando, per l'appunto,
		   una tripletta di coordinate ha la distanza normale
		   dallo schermo in negativo, ma non sono affatto sicuro. */

float alfa = 0, beta = 0, gamma = 0;
float cam_x = 0, cam_y = 0, cam_z = 0;

const double deg = M_PI / 180.0;

// Distanza dal piano di proiezione.

float dpp = 200.0;
float inv_dpp = 1.0 / dpp;

/* Costanti e variabili di controllo del texture mapping.
	H_MATRIXS e V_MATRIXS specificano le ripetizioni della stessa
	texture sui poligoni, ma per avere la possibilit… di dimezzare
	la texture o di disegnarne solo un quarto, sono state assunte
	come rappresentanti di "quarti di texture". Significa che
	per avere un texturing normale, senza ripetizioni n‚
	dimezzamenti, bisogna assegnare le due variabili a 4,
	non a 1 (che rappresenterebbe un solo quarto).
	E cosŤ via... se si mette 8, si ottiene la ripetizione
	della texture per due volte sul corrispondente asse,
	se si mette a 12 si ottengono tre ripetizioni, eccetera...
	(ps ho cambiato la base a 16, sedicesimi di texture). */

const int	MPIX	      =	           		319; // Massimo PIXEL su X.
const int   MPIY	      =	                        199; // Massimo PIXEL su Y.
const int   TEXTURE_XSIZE =	 	       		256; // Larghezza delle BMP.
const int  TEXTURE_YSIZE =   	       		256; // Altezza delle BMP.

float   EMU_K	      =		                 16.0; // Cost. di emulaz. FPU
Dword    H_MATRIXS     =		         	 16; // Nr. ripetizioni. 16-128
Dword    V_MATRIXS     =		         	 16; // Nr. ripetizioni. 16-128
Dword    XSIZE         =	  TEXTURE_XSIZE * H_MATRIXS; // Calibraz. dimensioni.
Dword    YSIZE         =	  TEXTURE_YSIZE * V_MATRIXS; // Calibraz. dimensioni.
float   XCOEFF        =	     	        EMU_K / dpp; // Coefficente di comodo.
float   YCOEFF        =	       	        EMU_K / dpp; // Coefficente di comodo.

// Inizializza indirizzi scanlines.

#ifdef WINDOWS
Udword riga[200];	//NOTVALID: The length of this should be increased if we increase the display size.
#else
Uword riga[200];
#endif

void initscanlines ()
{
	Uword c;

	for (c=0; c<200; c++)
		riga[c] = 320 * c;

	#ifndef WINDOWS
	_control87 (MCW_EM, MCW_EM); // disattiva i Floating Point Errors.
	#endif
}

// Traccia un segmento senza effettuare controlli sui limiti. Pi— veloce.
// Traccia con colore 255.
// Non effettua controlli, e quindi non va utilizzata per altre cose,
// o per lo meno bisogna stare attenti a far rientrare gli estremi del
// segmento nell'area video utilizzabile.
// Quella che effettua i controlli si trova nella funzione waveline di
// Liquid Player, ed Š sicura al 1000 per mille.

Uword ptr;

Udword xp, yp, xa, ya;
Udword global_x, global_y;

//NOTE: A lot of this function seems to be identical to Stick. (SL)
void Segmento ()
{
	//if (xa<0) xa=0;
	//if (xp<0) xp=0;
	//if (ya<0) ya=0;
	//if (yp<0) yp=0;
	if (xa>=320) xa=319;
	if (xp>=320) xp=319;
	if (ya>=200) ya=199;
	if (yp>=200) yp=199;
	
	Dword a, b, L;

	#ifdef WINDOWS
	Udword pi, pf;
	#else
	Uword pi, pf;
	#endif
	
	if (xp==xa) {
		if (ya>=yp) {
			pi = riga[yp] + xp;
			pf = riga[ya+1];
		}
		else {
			pi = riga[ya] + xp;
			pf = riga[yp+1];
		}
		asm {
			#ifdef WINDOWS
			push esi
			mov esi, [adapted]
			add pi, esi
			add pf, esi
			mov esi, pi
			 }
	   clu:	asm {   mov byte ptr [esi], 255
			add esi, 320
			cmp esi, pf
		   	#else
			les si, dword ptr adapted
			add pi, si
			add pf, si
			mov si, pi }
	   clu:	asm {   mov byte ptr es:[si], 255
			add si, 320
			cmp si, pf
		   	#endif
			jb clu 
		   #ifdef WINDOWS
		   pop esi
		   #endif
		   }
		return;
	}

	asm { 
		#ifdef WINDOWS
		pushad
		#endif
		
		MOV_ESI_DWORD_PTR xa
		SUB_ESI_DWORD_PTR xp
		jnc a_posit
		MOV_EAX_DWORD_PTR xp
		MOV_EBX_DWORD_PTR xa
		MOV_ECX_DWORD_PTR yp
		MOV_EDX_DWORD_PTR ya
		MOV_DWORD_PTR xa, MAYBE_EAX
		MOV_DWORD_PTR xp, MAYBE_EBX
		MOV_DWORD_PTR ya, MAYBE_ECX
		MOV_DWORD_PTR yp, MAYBE_EDX
		DB_0x66; neg MAYBE_ESI }
a_posit:asm {   MOV_DWORD_PTR a, MAYBE_ESI
		MOV_DWORD_PTR L, MAYBE_ESI
		xor ch, ch
		MOV_EAX_DWORD_PTR ya
		SUB_EAX_DWORD_PTR yp
		jnc b_posit
			 not ch
		DB_0x66; neg MAYBE_EAX }
b_posit:asm {   MOV_DWORD_PTR b, MAYBE_EAX
		CMP_EAX_DWORD_PTR L
		jb b_lower
		MOV_DWORD_PTR L, MAYBE_EAX }
b_lower:asm {	INC_DWORD_PTR L
		SHL_DWORD_PTR xa, 16
		MOV_EAX_DWORD_PTR xp
		MOV_EBX_DWORD_PTR yp
		SHL_EAX_16
		SHL_EBX_16
		MOV_DWORD_PTR global_x, MAYBE_EAX
		MOV_DWORD_PTR global_y, MAYBE_EBX
		SHL_DWORD_PTR a, 16
		SAL_DWORD_PTR b, 16
		
			 mov dx, word ptr a[2]
			 mov ax, word ptr a
			 div word ptr L	    // a /= L, 16bit - unsigned
			 mov word ptr a, ax
			 mov word ptr a[2], 0
			 mov dx, word ptr b[2]
			 mov ax, word ptr b
			 div word ptr L     // b /= L, 16bit - false unsigned
			 mov word ptr b, ax
			 mov word ptr b[2], 0
			 test ch, ch
			 jz trace
		NEG_DWORD_PTR b
		
	}

trace:	
	#ifdef WINDOWS
	asm mov esi, [adapted]
	#else
	asm les ax, dword ptr adapted;
	#endif

	/*

		Nota importante:

			Tutte le operazioni precedute dal prefisso 0x66
			vanno considerate con operandi di dimensioni doppie.
			Difatti, poich‚ l'assemblatore in-line non supporta
			i registri a 32 bit, Š necessario aggiungere i
			prefissi d'estensione manualmente.
			CosŤ facendo, i puntatori di tipo word (word ptr)
			vanno considerati come dword ptr, mentre i registri
			sono tutti estesi (per esempio, ax diventa eax).

	*/

	asm {
		#ifdef WINDOWS
		mov eax, dword ptr a    // passa in eax il delta_x (ovvero a).
		mov edx, dword ptr b    // passa in edx il delta_y (ovvero b).
		mov ecx, dword ptr xa } // passa in ecx il limite superiore del ciclo (come coordinata x d'arrivo).

_do:	asm {
		//CHECKME
		movsx ebx, word ptr global_y[2]
		movsx edi, word ptr global_x[2]
		//mov ebx, dword ptr global_y
		//mov edi, dword ptr global_x
		add ebx, ebx
       add dword ptr global_x, eax
		add edi, dword ptr riga[ebx*2]	//add di, word ptr riga[bx]
       add dword ptr global_y, edx
		mov byte ptr [esi+edi], 255		//mov byte ptr [esi+edi+4], 255		//REMOVED4
       cmp dword ptr global_x, ecx
		jb  _do
		#else
		
		db 0x66; mov ax, word ptr a    // passa in eax il delta_x (ovvero a).
		db 0x66; mov dx, word ptr b    // passa in edx il delta_y (ovvero b).
		db 0x66; mov cx, word ptr xa } // passa in ecx il limite superiore del ciclo (come coordinata x d'arrivo).

_do:	asm {   mov bx, word ptr global_y[2]
		mov di, word ptr global_x[2]
		add bx, bx
       db 0x66; add word ptr global_x, ax
		add di, word ptr riga[bx]
       db 0x66; add word ptr global_y, dx
		mov byte ptr es:[di+4], 255
       db 0x66; cmp word ptr global_x, cx
		jb  _do
		#endif
		}
	#ifdef WINDOWS
	asm popad
	#endif
}

// La funzione di tracciamento viene principalmente usata da Noctis,
// ed una delle sue caratteristiche Š di poter fare poligoni semitrasparenti
// che simulano degli aloni luminosi: si attiva con il flag "flares".
// Perch‚ il disegno dei bordi (dei segmenti) non interferisca con tale
// operazione, serve una pagina sana, priva di bordi, diversa da quella su
// cui si va a tracciare.
// Per default, Š la seguente, posta a nulla perch‚ tdpolygs non si
// prepara subito a questa particolare funzione.

char flares = 0;

Dword mp[6*VERTICI_PER_POLIGONO];

Uword max_x, max_y, min_x, min_y;

// Dati globali per conversioni, rototraslazioni e clipping.

char doflag;
Word pvert, nvert, vvert;
Word vr, vr2, vr3, vr4, vr5, vr6;

float zk;
float x2, y2, z2;
float xx, yy, zz;

/*

	Voglio annotarmi le sigle complicate, senn• finisce come per u-neg.

	doflag   = DO-(or-not)-for-each-polygon-FLAG.
		   da quando c'Š il fast-load funge anche come contatore
		   per i vertici da non ritagliare a livello 3d.
		   infatti, se sono tutti in doflag, il poligono non
		   interseca lo schermo e si pu• lasciare com'Š, almeno
		   a livello 3d.
	x2,y2,z2 = variabili di transito nelle rotazioni.
	pvert    = Previous-VERTex.
	nvert    = Next-VERTex.
	vvert    = bella domanda, mi sono scordato anche questa.
		   venuto in mente: Visible VERTex, vertice visibile.
	zk       = Zeta-Constant... costante derivata dal calcolo della
		   differenza tra coordinate zeta normalizzate allo schermo,
		   viene usata nel clipping a livello 3d dalla funz. "poly3d".
		   in realt… Š una costante solo per due equazioni,
		   ma Š meglio calcolarla una volta sola che due.

	xx,yy,zz = in questa inclusione non sono mai usate, ma ci sono sempre
		   state perch‚ una volta servivano a qualcosa (non ricordo
		   per nulla a cosa). attualmente, devono rimanerci perch‚
		   molti programmi le usano come variabili temporanee.

	pun = PUNto, Š un contatore/non esiste pi— dacch‚ ho tradotto in asm.
	rxf = Rototraslated-X-Floating-point-value.
	rwf = Rototraslated-vieW-(or-not)-Flag.
	mp  = Matrice Punti.
	lbx = LowerBound-X.
	ubx = UpperBound-X.

	opt_tsinalfa = OPTimized-Table-of-SINe-for-ALFA-angle.
	opt_psinalfa = OPTimized-Projected-table-of-SINe-for-ALFA-angle.

*/

char rwf[VERTICI_PER_POLIGONO];

float rxf[VERTICI_PER_POLIGONO];
float ryf[VERTICI_PER_POLIGONO];
float rzf[VERTICI_PER_POLIGONO];

// Limiti dell'area video rielaborati.

#define lbx -larghezza/2 + x_centro
#define ubx larghezza/2 + x_centro
#define lby -altezza/2 + y_centro
#define uby altezza/2 + y_centro

Dword lbxl = lbx;
Dword ubxl = ubx;
Dword lbyl = lby;
Dword ubyl = uby;

float lbxf = lbx;
float ubxf = ubx;
float lbyf = lby;
float ubyf = uby;

float x_centro_f = x_centro;
float y_centro_f = y_centro;

// Chiamare dopo aver cambiato l'angolo visuale.
// Aggiorna le seguenti variabili di ottimizzazione, usate da poly3d.

float opt_pcosbeta = dpp;
float opt_psinbeta = 0.0;
float opt_tcosbeta = 1.0;
float opt_tsinbeta = 0.0;
float opt_pcosalfa = dpp;
float opt_psinalfa = 0.0;
float opt_tcosalfa = 1.0;
float opt_tsinalfa = 0.0;

float opt_tcosgamma = 1.0;
float opt_tsingamma = 0.0;

void change_angle_of_view ()
{
	opt_pcosbeta = cos (beta*deg) * dpp;
	opt_psinbeta = sin (beta*deg) * dpp;
	opt_tcosbeta = cos (beta*deg);
	opt_tsinbeta = sin (beta*deg);
	opt_pcosalfa = cos (alfa*deg) * dpp; // 0.833
	opt_psinalfa = sin (alfa*deg) * dpp; // 0.833
	opt_tcosalfa = cos (alfa*deg);
	opt_tsinalfa = sin (alfa*deg);

	opt_tcosgamma = cos (gamma*deg);
	opt_tsingamma = sin (gamma*deg);
}

// Chiamare dopo aver cambiato dpp.
// Cambia l'obiettivo della videocamera.

void change_camera_lens ()
{
	inv_dpp = 1.0 / dpp;

	XCOEFF = EMU_K / dpp;
	YCOEFF = EMU_K / dpp;

	change_angle_of_view ();
}

// Chiamare dopo aver cambiato V_MATRIXS o H_MATRIXS.
// Aggiorna le variabili di lavoro per il texture mapping.

void change_txm_repeating_mode ()
{
	XSIZE = TEXTURE_XSIZE * H_MATRIXS;
	YSIZE = TEXTURE_YSIZE * V_MATRIXS;
}

/* Questa Š la funzione da invocare per ogni poligono da tracciare.

	E` un vero capolavoro: nessun problema, massima ottimizzazione,
	al 99% puro assembly per coprocessori da 387 in su e codice 32-bit,
	probabilmente la pi— complessa e bella funzione ch'io abbia mai
	partorito.

	Chiunque tenter… di capirci qualcosa rimarr… molto scoraggiato.
	Lungo e complesso, ma provate ad eseguirlo ed a monitorarne il flusso:
	vi accorgerete della sua enorme agilit…. */

float uno = 1.0; // sempre uno: Š una costante di comodo.

Uchar entity = 1; /* controlla quantit… generiche nel riempimento
			     dei poligoni con alcuni effetti speciali. */
	// Matrici 3d: tutto sullo stack.

	float ultima_x[2*VERTICI_PER_POLIGONO];
	float ultima_y[2*VERTICI_PER_POLIGONO];
	float ultima_z[2*VERTICI_PER_POLIGONO];

	// Matrici 2d: idem come sopra.

	float video_x0[2*VERTICI_PER_POLIGONO], video_y0[2*VERTICI_PER_POLIGONO];
	float video_x1[3*VERTICI_PER_POLIGONO], video_y1[3*VERTICI_PER_POLIGONO];
	float video_x2[4*VERTICI_PER_POLIGONO], video_y2[4*VERTICI_PER_POLIGONO];
	float video_x3[6*VERTICI_PER_POLIGONO], video_y3[6*VERTICI_PER_POLIGONO];

#ifdef OPOLY3D
#include "opoly3d.h"
#elif defined(NPOLY3D)
#include "npoly3d.h"
#else
void poly3d (float *x, float *y, float *z,
	     Uword nrv, Uchar colore)
{
	#ifdef WINDOWS
	Udword _8n;
	#else
	Uword _8n;
	#endif
    Uchar ent = entity;
	#ifdef WINDOWS
	Udword nrvDW = nrv;
	#endif
	if (nrvDW==0) return;

	// Rototraslazione dei vertici; i dati rimangono ancora 3d.

				doflag = 0;
				#ifdef WINDOWS
				asm {
					pushad
					xor edi, edi
					xor esi, esi
				} vertex: asm {
					mov ebx, [z]
					fld dword ptr [ebx+esi]
				#else
				asm {   xor di, di
					xor si, si }
		       vertex:  asm {
		       		les bx, dword ptr z
					fld dword ptr es:[bx+si]
				#endif
					fsub cam_z
					fst zz
					fmul opt_psinbeta
					#ifdef WINDOWS
					mov ebx, [x]
					fld dword ptr [ebx+esi]
					#else
					les bx, dword ptr x
					fld dword ptr es:[bx+si]
					#endif
					fsub cam_x
					fst xx
					fmul opt_pcosbeta
					faddp
					#ifdef WINDOWS
					fstp dword ptr rxf[esi]
					#else
					fstp dword ptr rxf[si]
					#endif
					fld zz
					fmul opt_tcosbeta
					fld xx
					fmul opt_tsinbeta
					fsubp
					fst z2
					fmul opt_tcosalfa
					#ifdef WINDOWS
					mov ebx, [y]
					fld dword ptr [ebx+esi]
					#else
					les bx, dword ptr y
					fld dword ptr es:[bx+si]
					#endif
					fsub cam_y
					fst yy
					fmul opt_tsinalfa
					faddp
					#ifdef WINDOWS
					fstp dword ptr rzf[esi]
					#else
					fst dword ptr rzf[si]
					#endif
					fcomp uneg
					fstsw ax
					fld yy
					fmul opt_pcosalfa
					fld z2
					fmul opt_psinalfa
					fsubp
					#ifdef WINDOWS
					fstp dword ptr ryf[esi]
					#else
					fstp dword ptr ryf[si]
					#endif
					sahf
					jb rzf_min_uneg
					inc doflag
					#ifdef WINDOWS
					mov byte ptr rwf[edi], 1
					#else
					mov byte ptr rwf[di], 1
					#endif
					jmp convert }
		    rzf_min_uneg:
		    	#ifdef WINDOWS
				asm   mov byte ptr rwf[edi], 0
				#else
				asm   mov byte ptr rwf[di], 0
				#endif
		    convert:
		    	asm {
		    		#ifdef WINDOWS
		    		add esi, 4
		    		inc edi
		    		cmp edi, nrvDW
		    		#else
		    		add si, 4
					inc di
					cmp di, nrv
					#endif
					je end_convert
					jmp vertex }
	
		    end_convert:
					if (!doflag) {
						#ifdef WINDOWS
						asm popad
						#endif
						return;
					}

	// Fast-load per poligoni completamente visibili.

					if (doflag==nrv) {
						asm {
							xor MAYBE_ESI, MAYBE_ESI
							mov cx, nrv
							mov vr2, cx }
					load:
						#ifdef WINDOWS
						asm {
							mov eax, dword ptr rxf[esi]		//mov eax, dword ptr rxf+si
							mov ebx, dword ptr ryf[esi]				//mov ebx, dword ptr ryf+si
							mov edx, dword ptr rzf[esi]				//mov edx, dword ptr rzf+si
							mov dword ptr ultima_x[esi], eax
							mov dword ptr ultima_y[esi], ebx
							mov dword ptr ultima_z[esi], edx

						#else
					
						   asm {
						   	 db 0x66; mov ax, word ptr rxf[si]
							db 0x66; mov bx, word ptr ryf[si]
							db 0x66; mov dx, word ptr rzf[si]
							db 0x66; mov word ptr ultima_x[si], ax
							db 0x66; mov word ptr ultima_y[si], bx
							db 0x66; mov word ptr ultima_z[si], dx
							add si, 4
							dec cx
						#endif
							jnz load }
						goto to_2d;
					}

	/* Conversione punti alle spalle dell'osservatore
	   rispetto al piano dello schermo. */

					asm {   
						mov vr, 0
						#ifdef WINDOWS
						xor edi, edi
						#else
						xor di, di
						#endif
						mov dx, nrv
						dec dx }
			     the_for_1: asm {
			     		#ifdef WINDOWS
			     		movsx esi, vr
			     		cmp byte ptr rwf[esi], 0
			     		#else
			     		mov si, vr
			     		cmp byte ptr rwf[si], 0
			     		#endif
						
						je CONT1
						jmp bypass }
			      CONT1:    asm {
			      		mov ax, vr
						sub ax, 1
						jnc pvert1ok
						mov pvert, dx
						jmp pvert1no }
			      pvert1ok: asm     mov pvert, ax
			      pvert1no: asm {   mov ax, vr
						inc ax
						cmp ax, dx
						jbe nvert1ok
						mov nvert, 0
						jmp nvert1no }
			      nvert1ok: asm     mov nvert, ax
			      nvert1no: asm {
			      		#ifdef WINDOWS
			      		movsx esi, pvert
			      		cmp byte ptr rwf[esi], 0
			      		#else
			      		mov si, pvert
						cmp byte ptr rwf[si], 0
						#endif
						je ctrl1
						jmp JMPR11 }
			      ctrl1:    asm {
			      		#ifdef WINDOWS
			      		movsx esi, nvert
			      		cmp byte ptr rwf[esi], 0
			      		#else
			      		mov si, nvert
						cmp byte ptr rwf[si], 0
						#endif
						jne JMPR11
						jmp STOP1 }
			      JMPR11:   asm {   mov bx, vr
						shl bx, 2
						#ifdef WINDOWS
			      		movsx esi, pvert
			      		mov al, byte ptr rwf[esi]
			      		movsx esi, nvert
			      		add al, byte ptr rwf[esi]
			      		#else
			      		mov si, pvert
						mov al, byte ptr rwf[si]
						mov si, nvert
						add al, byte ptr rwf[si]
						#endif
						cmp al, 2
						je if11
						jmp else11 }
			      if11:     asm {
			      		shl pvert, 2
						shl nvert, 2
						#ifdef WINDOWS
						movsx esi, bx
						fld dword ptr rzf[esi]
						movsx esi, pvert
						fcomp dword ptr rzf[esi]
						#else
						mov si, bx
						fld dword ptr rzf[si]
						mov si, pvert
						fcomp dword ptr rzf[si]
						#endif
						fstsw ax
						sahf
						jne if12
						jmp else12 }
			      if12:     asm {
			      		fld dword ptr uneg
						#ifdef WINDOWS
						fsub dword ptr rzf[esi]
						fld dword ptr rzf[esi]
						movsx esi, bx
						fsubr dword ptr rzf[esi]
						#else
						fsub dword ptr rzf[si]
						fld dword ptr rzf[si]
						mov si, bx
						fsubr dword ptr rzf[si]
						#endif
						fdivp
						fst zk
						#ifdef WINDOWS
						fld dword ptr rxf[esi]
						movsx esi, pvert
						fsub dword ptr rxf[esi]
						fmulp
						fadd dword ptr rxf[esi]
						fstp dword ptr ultima_x[edi]
						#else
						fld dword ptr rxf[si]
						mov si, pvert
						fsub dword ptr rxf[si]
						fmulp
						fadd dword ptr rxf[si]
						fstp dword ptr ultima_x[di]
						#endif
						fld zk
						#ifdef WINDOWS
						movsx esi, bx
						fld dword ptr ryf[esi]
						movsx esi, pvert
						fsub dword ptr ryf[esi]
						fmulp
						fadd dword ptr ryf[esi]
						fstp dword ptr ultima_y[edi]
						#else
						mov si, bx
						fld dword ptr ryf[si]
						mov si, pvert
						fsub dword ptr ryf[si]
						fmulp
						fadd dword ptr ryf[si]
						fstp dword ptr ultima_y[di]
						#endif
						jmp JMPR12 }
			      else12:   asm {
			      		#ifdef WINDOWS
			      		movsx esi, bx
			      		mov eax, dword ptr rxf[esi]
			      		mov dword ptr ultima_x[edi], eax
						mov eax, dword ptr ryf[esi]
						mov dword ptr ultima_y[edi], eax }
						#else
						mov si, bx
						db 0x66; mov ax, word ptr rxf[si]
						db 0x66; mov word ptr ultima_x[di], ax
						db 0x66; mov ax, word ptr ryf[si]
						db 0x66; mov word ptr ultima_y[di], ax }
						#endif
			      JMPR12:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr uneg
						mov dword ptr ultima_z[edi], eax
						movsx esi, bx
						fld dword ptr rzf[esi]
						movsx esi, nvert
						fcomp dword ptr rzf[esi]
						#else
			      		db 0x66; mov ax, word ptr uneg
						db 0x66; mov word ptr ultima_z[di], ax
						mov si, bx
						fld dword ptr rzf[si]
						mov si, nvert
						fcomp dword ptr rzf[si]
						#endif
						fstsw ax
						sahf
						jne neq1
						jmp eq1 }
			      neq1:     asm {   fld dword ptr uneg
						#ifdef WINDOWS
			      		fsub dword ptr rzf[esi]
						fld dword ptr rzf[esi]
						movsx esi, bx
						fsubr dword ptr rzf[esi]
						#else
			      		fsub dword ptr rzf[si]
						fld dword ptr rzf[si]
						mov si, bx
						fsubr dword ptr rzf[si]
						#endif
						fdivp
						fst zk
						#ifdef WINDOWS
			      		fld dword ptr rxf[esi]
						movsx esi, nvert
						fsub dword ptr rxf[esi]
						fmulp
						fadd dword ptr rxf[esi]
						fstp dword ptr ultima_x[edi+4]
						#else
			      		fld dword ptr rxf[si]
						mov si, nvert
						fsub dword ptr rxf[si]
						fmulp
						fadd dword ptr rxf[si]
						fstp dword ptr ultima_x[di+4]
						#endif
						fld zk
						#ifdef WINDOWS
			      		movsx esi, bx
						fld dword ptr ryf[esi]
						movsx esi, nvert
						fsub dword ptr ryf[esi]
						fmulp
						fadd dword ptr ryf[esi]
						fstp dword ptr ultima_y[edi+4]
						#else
			      		mov si, bx
						fld dword ptr ryf[si]
						mov si, nvert
						fsub dword ptr ryf[si]
						fmulp
						fadd dword ptr ryf[si]
						fstp dword ptr ultima_y[di+4]
						#endif
						jmp JMPR13 }
			      eq1:      asm {
			      		#ifdef WINDOWS
			      		movsx esi, bx
						mov eax, dword ptr rxf[esi]
						mov dword ptr ultima_x[edi+4], eax
						mov eax, dword ptr ryf[esi]
						mov dword ptr ultima_y[edi+4], eax }
						#else
			      		mov si, bx
						db 0x66; mov ax, word ptr rxf[si]
						db 0x66; mov word ptr ultima_x[di+4], ax
						db 0x66; mov ax, word ptr ryf[si]
						db 0x66; mov word ptr ultima_y[di+4], ax }
						#endif
			      JMPR13:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr uneg
						mov dword ptr ultima_z[edi+4], eax
						add edi, 8
						#else
			      		db 0x66; mov ax, word ptr uneg
						db 0x66; mov word ptr ultima_z[di+4], ax
						add di, 8
						#endif
						jmp STOP1 }
			      else11:   asm {
			      		#ifdef WINDOWS
			      		movsx esi, pvert
						cmp byte ptr rwf[esi], 0
						#else
			      		mov si, pvert
						cmp byte ptr rwf[si], 0
						#endif
						jne vpvert1
						mov ax, nvert
						mov vvert, ax
						jmp vnvert1 }
			      vpvert1:  asm {   mov ax, pvert
						mov vvert, ax }
			      vnvert1:  asm {   shl vvert, 2
						#ifdef WINDOWS
			      		movsx esi, bx
						fld dword ptr rzf[esi]
						movsx esi, vvert
						fcomp dword ptr rzf[esi]
						#else
			      		mov si, bx
						fld dword ptr rzf[si]
						mov si, vvert
						fcomp dword ptr rzf[si]
						#endif
						fstsw ax
						sahf
						jne neq2
						jmp eq2 }
			      neq2:     asm {   fld dword ptr uneg
						fsub dword ptr rzf[MAYBE_ESI]
						fld dword ptr rzf[MAYBE_ESI]
						MOVSX_MAYBE_ESI, bx
						fsubr dword ptr rzf[MAYBE_ESI]
						fdivp
						fst zk
						fld dword ptr rxf[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fsub dword ptr rxf[MAYBE_ESI]
						fmulp
						fadd dword ptr rxf[MAYBE_ESI]
						fstp dword ptr ultima_x[MAYBE_EDI]
						fld zk
						MOVSX_MAYBE_ESI, bx
						fld dword ptr ryf[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fsub dword ptr ryf[MAYBE_ESI]
						fmulp
						fadd dword ptr ryf[MAYBE_ESI]
						fstp dword ptr ultima_y[MAYBE_EDI]
						jmp JMPR14 }
			      eq2:      asm {   MOVSX_MAYBE_ESI, bx
						#ifdef WINDOWS
						mov eax, dword ptr rxf[esi]
						mov dword ptr ultima_x[edi], eax
						mov eax, dword ptr ryf[esi]
						mov dword ptr ultima_y[edi], eax }
						#else
						db 0x66; mov ax, word ptr rxf[si]
						db 0x66; mov word ptr ultima_x[di], ax
						db 0x66; mov ax, word ptr ryf[si]
						db 0x66; mov word ptr ultima_y[di], ax }
						#endif
			      JMPR14:   asm {
			      		#ifdef WINDOWS
						mov eax, dword ptr uneg
						mov dword ptr ultima_z[edi], eax
						#else
						db 0x66; mov ax, word ptr uneg
						db 0x66; mov word ptr ultima_z[di], ax
						#endif
						add MAYBE_EDI, 4
						jmp STOP1 }
			      bypass:   asm {   shl MAYBE_ESI, 2
						#ifdef WINDOWS
						mov eax, dword ptr rxf[esi]
						mov dword ptr ultima_x[edi], eax
						mov eax, dword ptr ryf[esi]
						mov dword ptr ultima_y[edi], eax
						mov eax, dword ptr rzf[esi]
						mov dword ptr ultima_z[edi], eax
						#else
						db 0x66; mov ax, word ptr rxf[si]
						db 0x66; mov word ptr ultima_x[di], ax
						db 0x66; mov ax, word ptr ryf[si]
						db 0x66; mov word ptr ultima_y[di], ax
						db 0x66; mov ax, word ptr rzf[si]
						db 0x66; mov word ptr ultima_z[di], ax
						#endif
						add MAYBE_EDI, 4 }
			      STOP1:    asm {   inc vr
						mov ax, vr
						cmp ax, nrv
						jnb cutting_end_1
						jmp the_for_1 }

			 cutting_end_1: asm {
			 			#ifdef WINDOWS
			 			mov eax, edi
			 			shr eax, 2
			 			mov vr2, ax
			 			#else
			 			mov ax, di
						shr ax, 2
						mov vr2, ax
						#endif
						}

				if (vr2<3) {
					#ifdef WINDOWS
					asm popad
					#endif
					return;
				}

	   // Queste sono le proiezioni prospettiche da 3d a 2d.
	   // E` stato incluso in data 6.12.97 anche un piccolo esame
	   // dei minimi e massimi grafici. Questo fa sŤ che i poligoni
	   // che rientrano nei limiti del video non vengano esaminati
	   // dalle funzioni di clipping 2-d. E` pi— intelligente.
	   // Prima d'ora, il ciclo di ricerca minimi-massimi era in fondo,
	   // e veniva eseguito dopo il clipping 2d, che per• Š lungo
	   // e complicato: non Š quindi una cosa da fare sempre.

				 to_2d: asm {
				 		#ifdef WINDOWS
			 			mov eax, dword ptr lbxl
						mov ebx, dword ptr lbyl
						mov ecx, dword ptr ubxl
						mov edx, dword ptr ubyl
						#else
			 			db 0x66; mov ax, word ptr lbxl
						db 0x66; mov bx, word ptr lbyl
						db 0x66; mov cx, word ptr ubxl
						db 0x66; mov dx, word ptr ubyl
						#endif
						MOVSX_MAYBE_ESI, vr2
						dec MAYBE_ESI
						shl MAYBE_ESI, 2
						mov MAYBE_EDI, MAYBE_ESI
						add MAYBE_EDI, MAYBE_ESI
						mov _8n, MAYBE_EDI }
			     projector: asm {   fld uno
						fdiv dword ptr ultima_z[MAYBE_ESI]
						fld st(0)
						fmul dword ptr ultima_x[MAYBE_ESI]
						fadd dword ptr x_centro_f
						fst dword ptr video_x0[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI]
						#ifdef WINDOWS
						cmp dword ptr mp[edi], ecx
						#else
						db 0x66; cmp word ptr mp[di], cx
						#endif
						jnl outr_1
						#ifdef WINDOWS
						mov ecx, dword ptr mp[edi]
						#else
						db 0x66; mov cx, word ptr mp[di]
						#endif
						}
			     outr_1:	asm {
			     		#ifdef WINDOWS
			     		cmp dword ptr mp[edi], eax
			     		#else
			     		db 0x66; cmp word ptr mp[di], ax
			     		#endif
			     		
						jle outr_2
						#ifdef WINDOWS
						mov eax, dword ptr mp[edi]
						#else
						db 0x66; mov ax, word ptr mp[di]
						#endif
						}
			     outr_2:	asm {
			     		fmul dword ptr ultima_y[MAYBE_ESI]
						fadd dword ptr y_centro_f
						fst dword ptr video_y0[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI+4]
						#ifdef WINDOWS
						cmp dword ptr mp[edi+4], edx
						#else
						db 0x66; cmp word ptr mp[di+4], dx
						#endif
						jnl outr_3
						#ifdef WINDOWS
						mov edx, dword ptr mp[edi+4]
						#else
						db 0x66; mov dx, word ptr mp[di+4]
						#endif
					}
			     outr_3:	asm {
			     		#ifdef WINDOWS
						cmp dword ptr mp[edi+4], ebx
						jle outr_4
						mov ebx, dword ptr mp[edi+4]
						#else
						db 0x66; cmp word ptr mp[di+4], bx
						jle outr_4
						db 0x66; mov bx, word ptr mp[di+4]
						#endif
						}
			     outr_4:	asm {
			     		sub MAYBE_EDI, 8
						sub MAYBE_ESI, 4
						jnc projector
						mov max_x, ax
						mov max_y, bx
						mov min_x, cx
						mov min_y, dx
						xor MAYBE_ESI, MAYBE_ESI
						#ifdef WINDOWS
						cmp eax, dword ptr ubxl
						#else
						db 0x66; cmp ax, word ptr ubxl
						#endif
						jl ranged1
						inc MAYBE_ESI
						mov max_x, ubx
						}
			     ranged1:	asm {
			     		#ifdef WINDOWS
			     		cmp ebx, dword ptr ubyl
						#else
						db 0x66; cmp bx, word ptr ubyl
						#endif
						jl ranged2
						inc MAYBE_ESI
						mov max_y, uby
						}
			     ranged2:	asm {
			     		#ifdef WINDOWS
			     		cmp ecx, dword ptr lbxl
			     		#else
			     		db 0x66; cmp cx, word ptr lbxl
			     		#endif
						jnl ranged3
						inc MAYBE_ESI
						mov min_x, lbx
						}
			     ranged3:	asm {
			     		#ifdef WINDOWS
			     		cmp edx, dword ptr lbyl
			     		#else
			     		db 0x66; cmp dx, word ptr lbyl
			     		#endif
						jnl ranged4
						inc MAYBE_ESI
						mov min_y, lby
						}
			     ranged4:	asm {
			     		test MAYBE_ESI, MAYBE_ESI
						jnz yes_clip
						jmp drawb
						}

	   /* Conversione dei punti che risiedono al di fuori dell'area
	      visibile. Questi punti devono essere ridimensionati per
	      rientrare in tale area per evitare poligoni troppo grandi,
	      che oltre a rallentare notevolmente il tracciamento provocano
	      il blocco di sistema invadendo aree di memoria non-video.
	      In questa sezione i dati sui vertici del poligono da tracciare
	      vengono rimaneggiati a livello bidimensionale, aggiungendo
	      eventuali vertici per "ritagliare" solo la parte di poligono
	      visibile. */

	   // Lato superiore del video.

			      yes_clip: asm {   mov vr, 0
						xor MAYBE_EDI, MAYBE_EDI
						mov dx, vr2
						dec dx }
			      the_for_2:asm {   MOVSX_MAYBE_ESI, vr
						shl MAYBE_ESI, 2
						fld dword ptr video_y0[MAYBE_ESI]
						fcomp dword ptr lbyf
						fstsw ax
						sahf
						jb if21
						jmp else21 }
			      if21:     asm {
				      	#ifdef WINDOWS
				      	mov ebx, esi
				      	#else
				      	mov bx, si
				      	#endif
						mov ax, vr
						sub ax, 1
						jnc pvert2ok
						mov pvert, dx
						jmp pvert2no }
			      pvert2ok: asm     mov pvert, ax
			      pvert2no: asm {   mov ax, vr
						inc ax
						cmp ax, dx
						jbe nvert2ok
						mov nvert, 0
						jmp nvert2no }
			      nvert2ok: asm     mov nvert, ax
			      nvert2no: asm {   shl pvert, 2
						shl nvert, 2
						MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_y0[MAYBE_ESI]
						fcomp dword ptr lbyf
						fstsw ax
						sahf
						jae CONT2
						MOVSX_MAYBE_ESI, nvert
						fld dword ptr video_y0[MAYBE_ESI]
						fcomp dword ptr lbyf
						fstsw ax
						sahf
						jae CONT2
						jmp STOP2 }
			      CONT2:    asm {   MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_y0[MAYBE_ESI]
						fcomp dword ptr lbyf
						fstsw ax
						sahf
						jae ctrl22
						jmp else22 }
			      ctrl22:   asm {   MOVSX_MAYBE_ESI, nvert
						fld dword ptr video_y0[MAYBE_ESI]
						fcomp dword ptr lbyf
						fstsw ax
						sahf
						jae if22
						jmp else22 }
			      if22:     asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fld dword ptr video_y0[MAYBE_ESI]
						MOVSX_MAYBE_ESI, pvert
						fcomp dword ptr video_y0[MAYBE_ESI]
						fstsw ax
						sahf
						jne if23
						jmp else23 }
			      if23:     asm {   fld dword ptr lbyf
						fsub dword ptr video_y0[MAYBE_ESI]
						fld dword ptr video_y0[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fsubr dword ptr video_y0[MAYBE_ESI]
						fdivp
						fld dword ptr video_x0[MAYBE_ESI]
						MOVSX_MAYBE_ESI, pvert
						fsub dword ptr video_x0[MAYBE_ESI]
						fmulp
						fadd dword ptr video_x0[MAYBE_ESI]
						fstp dword ptr video_x1[MAYBE_EDI]
						jmp JMPR23 }
			      else23:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		mov eax, dword ptr video_x0[esi]
						mov dword ptr video_x1[edi], eax 
						#else
			      		mov si, bx
			      		db 0x66; mov ax, word ptr video_x0[si]
						db 0x66; mov word ptr video_x1[di], ax 
						#endif
						}
			      JMPR23:   asm {
			      	
			      		#ifdef WINDOWS
			      		mov eax, dword ptr lbyf
						mov dword ptr video_y1[edi], eax
						mov esi, ebx
						#else
			      		db 0x66; mov ax, word ptr lbyf
						db 0x66; mov word ptr video_y1[di], ax
						mov si, bx
						#endif
						fld dword ptr video_y0[MAYBE_ESI]
						MOVSX_MAYBE_ESI, nvert
						fcomp dword ptr video_y0[MAYBE_ESI]
						fstsw ax
						sahf
						jne if24
						jmp else24 }
			      if24:     asm {   fld dword ptr lbyf
						fsub dword ptr video_y0[MAYBE_ESI]
						fld dword ptr video_y0[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fsubr dword ptr video_y0[MAYBE_ESI]
						fdivp
						fld dword ptr video_x0[MAYBE_ESI]
						MOVSX_MAYBE_ESI, nvert
						fsub dword ptr video_x0[MAYBE_ESI]
						fmulp
						fadd dword ptr video_x0[MAYBE_ESI]
						fstp dword ptr video_x1[MAYBE_EDI+4]
						jmp JMPR22 }
			      else24:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		mov eax, dword ptr video_x0[esi]
						mov dword ptr video_x1[edi+4], eax
						#else
			      		mov si, bx
			      		db 0x66; mov ax, word ptr video_x0[si]
						db 0x66; mov word ptr video_x1[di+4], ax
						#endif
						 }
			      JMPR22:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr lbyf
						mov dword ptr video_y1[edi+4], eax
			      		#else
			      		db 0x66; mov ax, word ptr lbyf
						db 0x66; mov word ptr video_y1[di+4], ax
						#endif
						add MAYBE_EDI, 8
						jmp STOP2 }
			      else22:   asm {
			      		MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_y0[MAYBE_ESI]
						fcomp dword ptr lbyf
						fstsw ax
						sahf
						jb vnvert2
						mov ax, pvert
						mov vvert, ax
						jmp vpvert2 }
			      vnvert2:  asm {   mov ax, nvert
						mov vvert, ax }
			      vpvert2:  asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fld dword ptr video_y0[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fcomp dword ptr video_y0[MAYBE_ESI]
						fstsw ax
						sahf
						jne if25
						jmp else35 }
			      if25:     asm {   fld dword ptr lbyf
						fsub dword ptr video_y0[MAYBE_ESI]
						fld dword ptr video_y0[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fsubr dword ptr video_y0[MAYBE_ESI]
						fdivp
						fld dword ptr video_x0[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fsub dword ptr video_x0[MAYBE_ESI]
						fmulp
						fadd dword ptr video_x0[MAYBE_ESI]
						fstp dword ptr video_x1[MAYBE_EDI]
						jmp JMPR21 }
			      else25:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						#ifdef WINDOWS
			      		mov eax, dword ptr video_x0[esi]
						mov dword ptr video_x1[edi], eax
			      		#else
			      		db 0x66; mov ax, word ptr video_x0[si]
						db 0x66; mov word ptr video_x1[di], ax
						#endif
						}
			      JMPR21:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr lbyf
			      		mov dword ptr video_y1[edi], eax
			      		#else
			      		db 0x66; mov ax, word ptr lbyf
						db 0x66; mov word ptr video_y1[di], ax
						#endif
						add MAYBE_EDI, 4
						jmp STOP2 }
			      else21:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr video_y0[esi]
						mov dword ptr video_y1[edi], eax
						mov eax, dword ptr video_x0[esi]
						mov dword ptr video_x1[edi], eax
						#else
			      		db 0x66; mov ax, word ptr video_y0[si]
						db 0x66; mov word ptr video_y1[di], ax
						db 0x66; mov ax, word ptr video_x0[si]
						db 0x66; mov word ptr video_x1[di], ax
						#endif
						add MAYBE_EDI, 4 }
			      STOP2:    asm {   inc vr
						mov ax, vr
						cmp ax, vr2
						jnb cutting_end_2
						jmp the_for_2 }

			 cutting_end_2: asm {
			 			#ifdef WINDOWS
			      		mov eax, edi
			      		shr eax, 2
			      		mov vr3, ax
			      		#else
			      		mov ax, di
						shr ax, 2
						mov vr3, ax
						#endif
						}

					if (vr3<3) {
						#ifdef WINDOWS
						asm popad
						#endif
						return;
					}

	   // Lato inferiore del video.

					asm {   mov vr, 0
						xor MAYBE_EDI, MAYBE_EDI
						mov dx, vr3
						dec dx }
			      the_for_3:asm {   MOVSX_MAYBE_ESI, vr
						shl MAYBE_ESI, 2
						fld dword ptr video_y1[MAYBE_ESI]
						fcomp dword ptr ubyf
						fstsw ax
						sahf
						ja if31
						jmp else31 }
			      if31:     asm {
			      		#ifdef WINDOWS
			      		mov ebx, esi
			      		#else
			      		mov bx, si
			      		#endif
						
						mov ax, vr
						sub ax, 1
						jnc pvert3ok
						mov pvert, dx
						jmp pvert3no }
			      pvert3ok: asm     mov pvert, ax
			      pvert3no: asm {   mov ax, vr
						inc ax
						cmp ax, dx
						jbe nvert3ok
						mov nvert, 0
						jmp nvert3no }
			      nvert3ok: asm     mov nvert, ax
			      nvert3no: asm {   shl pvert, 2
						shl nvert, 2
						MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_y1[MAYBE_ESI]
						fcomp dword ptr ubyf
						fstsw ax
						sahf
						jbe CONT3
						mov si, nvert
						fld dword ptr video_y1[MAYBE_ESI]
						fcomp dword ptr ubyf
						fstsw ax
						sahf
						jbe CONT3
						jmp STOP3 }
			      CONT3:    asm {   MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_y1[MAYBE_ESI]
						fcomp dword ptr ubyf
						fstsw ax
						sahf
						jbe ctrl32
						jmp else32 }
			      ctrl32:   asm {   MOVSX_MAYBE_ESI, nvert
						fld dword ptr video_y1[MAYBE_ESI]
						fcomp dword ptr ubyf
						fstsw ax
						sahf
						jbe if32
						jmp else32 }
			      if32:     asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_y1[MAYBE_ESI]
						MOVSX_MAYBE_ESI, pvert
						fcomp dword ptr video_y1[MAYBE_ESI]
						fstsw ax
						sahf
						jne if33
						jmp else33 }
			      if33:     asm {   fld dword ptr ubyf
						fsub dword ptr video_y1[MAYBE_ESI]
						fld dword ptr video_y1[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fsubr dword ptr video_y1[MAYBE_ESI]
						fdivp
						fld dword ptr video_x1[MAYBE_ESI]
						MOVSX_MAYBE_ESI, pvert
						fsub dword ptr video_x1[MAYBE_ESI]
						fmulp
						fadd dword ptr video_x1[MAYBE_ESI]
						fstp dword ptr video_x2[MAYBE_EDI]
						jmp JMPR33 }
			      else33:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						#ifdef WINDOWS
			      		mov eax, dword ptr video_x1[esi]
						mov dword ptr video_x2[edi], eax
						#else
			      		db 0x66; mov ax, word ptr video_x1[si]
						db 0x66; mov word ptr video_x2[di], ax
						#endif
						}
			      JMPR33:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr ubyf
			      		mov dword ptr video_y2[edi], eax
			      		#else
			      		db 0x66; mov ax, word ptr ubyf
						db 0x66; mov word ptr video_y2[di], ax
						#endif
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fld dword ptr video_y1[MAYBE_ESI]
						MOVSX_MAYBE_ESI, nvert
						fcomp dword ptr video_y1[MAYBE_ESI]
						fstsw ax
						sahf
						jne if34
						jmp else34 }
			      if34:     asm {   fld dword ptr ubyf
						fsub dword ptr video_y1[MAYBE_ESI]
						fld dword ptr video_y1[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fsubr dword ptr video_y1[MAYBE_ESI]
						fdivp
						fld dword ptr video_x1[MAYBE_ESI]
						MOVSX_MAYBE_ESI, nvert
						fsub dword ptr video_x1[MAYBE_ESI]
						fmulp
						fadd dword ptr video_x1[MAYBE_ESI]
						fstp dword ptr video_x2[MAYBE_EDI+4]
						jmp JMPR32 }
			      else34:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						#ifdef WINDOWS
			      		mov eax, dword ptr video_x1[esi]
						mov dword ptr video_x2[edi+4], eax
						#else
			      		db 0x66; mov ax, word ptr video_x1[si]
						db 0x66; mov word ptr video_x2[di+4], ax
						#endif
						}
			      JMPR32:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr ubyf
						mov dword ptr video_y2[edi+4], eax
						#else
			      		db 0x66; mov ax, word ptr ubyf
						db 0x66; mov word ptr video_y2[di+4], ax
						#endif
						add MAYBE_EDI, 8
						jmp STOP3 }
			      else32:   asm {   MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_y1[MAYBE_ESI]
						fcomp dword ptr ubyf
						fstsw ax
						sahf
						ja vnvert3
						mov ax, pvert
						mov vvert, ax
						jmp vpvert3 }
			      vnvert3:  asm {   mov ax, nvert
						mov vvert, ax }
			      vpvert3:  asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_y1[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fcomp dword ptr video_y1[MAYBE_ESI]
						fstsw ax
						sahf
						jne if35
						jmp else35 }
			      if35:     asm {   fld dword ptr ubyf
						fsub dword ptr video_y1[MAYBE_ESI]
						fld dword ptr video_y1[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						fsubr dword ptr video_y1[MAYBE_ESI]
						fdivp
						fld dword ptr video_x1[MAYBE_ESI]
						mov si, vvert
						fsub dword ptr video_x1[MAYBE_ESI]
						fmulp
						fadd dword ptr video_x1[MAYBE_ESI]
						fstp dword ptr video_x2[MAYBE_EDI]
						jmp JMPR31 }
			      else35:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						#ifdef WINDOWS
			      		mov eax, dword ptr video_x1[esi]
						mov dword ptr video_x2[edi], eax
						#else
			      		db 0x66; mov ax, word ptr video_x1[si]
						db 0x66; mov word ptr video_x2[di], ax
						#endif
						}
			      JMPR31:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr ubyf
						mov dword ptr video_y2[edi], eax
						#else
			      		db 0x66; mov ax, word ptr ubyf
						db 0x66; mov word ptr video_y2[di], ax
						#endif
						add MAYBE_EDI, 4
						jmp STOP3 }
			      else31:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr video_y1[esi]
						mov dword ptr video_y2[edi], eax
						mov eax, dword ptr video_x1[esi]
						mov dword ptr video_x2[edi], eax
						#else
			      		db 0x66; mov ax, word ptr video_y1[si]
						db 0x66; mov word ptr video_y2[di], ax
						db 0x66; mov ax, word ptr video_x1[si]
						db 0x66; mov word ptr video_x2[di], ax
						#endif
						add MAYBE_EDI, 4 }
			      STOP3:    asm {   inc vr
						mov ax, vr
						cmp ax, vr3
						jnb cutting_end_3
						jmp the_for_3 }

			 cutting_end_3: asm {
			 			#ifdef WINDOWS
			 			mov eax, edi
						shr eax, 2
						#else
			 			mov ax, di
						shr ax, 2
						#endif
						mov vr4, ax
						}

					if (vr4<3) {
						#ifdef WINDOWS
						asm popad
						#endif
						return;
					}

	   // Lato sinistro del video.

					asm {   mov vr, 0
						xor MAYBE_EDI, MAYBE_EDI
						mov dx, vr4
						dec dx }
			      the_for_4:asm {
			      		MOVSX_MAYBE_ESI, vr
						shl MAYBE_ESI, 2
						fld dword ptr video_x2[MAYBE_ESI]
						fcomp dword ptr lbxf
						fstsw ax
						sahf
						jb if41
						jmp else41 }
			      if41:     asm {
			      		#ifdef WINDOWS
			      		mov ebx, esi
			      		#else
			      		mov bx, si
			      		#endif
						mov ax, vr
						sub ax, 1
						jnc pvert4ok
						mov pvert, dx
						jmp pvert4no }
			      pvert4ok: asm     mov pvert, ax
			      pvert4no: asm {   mov ax, vr
						inc ax
						cmp ax, dx
						jbe nvert4ok
						mov nvert, 0
						jmp nvert4no }
			      nvert4ok: asm     mov nvert, ax
			      nvert4no: asm {   shl pvert, 2
						shl nvert, 2
						MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_x2[MAYBE_ESI]
						fcomp dword ptr lbxf
						fstsw ax
						sahf
						jae CONT4
						MOVSX_MAYBE_ESI, nvert
						fld dword ptr video_x2[MAYBE_ESI]
						fcomp dword ptr lbxf
						fstsw ax
						sahf
						jae CONT4
						jmp STOP4 }
			      CONT4:    asm {
			      		MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_x2[MAYBE_ESI]
						fcomp dword ptr lbxf
						fstsw ax
						sahf
						jae ctrl42
						jmp else42 }
			      ctrl42:   asm {
			      		MOVSX_MAYBE_ESI, nvert
						fld dword ptr video_x2[MAYBE_ESI]
						fcomp dword ptr lbxf
						fstsw ax
						sahf
						jae if42
						jmp else42 }
			      if42:     asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_x2[MAYBE_ESI]
						MOVSX_MAYBE_ESI, pvert
						fcomp dword ptr video_x2[MAYBE_ESI]
						fstsw ax
						sahf
						jne if43
						jmp else43 }
			      if43:     asm {   fld dword ptr lbxf
						fsub dword ptr video_x2[MAYBE_ESI]
						fld dword ptr video_x2[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fsubr dword ptr video_x2[MAYBE_ESI]
						fdivp
						fld dword ptr video_y2[MAYBE_ESI]
						MOVSX_MAYBE_ESI, pvert
						fsub dword ptr video_y2[MAYBE_ESI]
						fmulp
						fadd dword ptr video_y2[MAYBE_ESI]
						fstp dword ptr video_y3[MAYBE_EDI]
						jmp JMPR43 }
			      else43:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						#ifdef WINDOWS
			      		mov eax, dword ptr video_y2[esi]
						mov dword ptr video_y3[edi], eax
						#else
			      		db 0x66; mov ax, word ptr video_y2[si]
						db 0x66; mov word ptr video_y3[di], ax
						#endif
						}
			      JMPR43:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr lbxf
						mov dword ptr video_x3[edi], eax
						#else
			      		db 0x66; mov ax, word ptr lbxf
						db 0x66; mov word ptr video_x3[di], ax
						#endif
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_x2[MAYBE_ESI]
						MOVSX_MAYBE_ESI, nvert
						fcomp dword ptr video_x2[MAYBE_ESI]
						fstsw ax
						sahf
						jne if44
						jmp else44 }
			      if44:     asm {   fld dword ptr lbxf
						fsub dword ptr video_x2[MAYBE_ESI]
						fld dword ptr video_x2[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fsubr dword ptr video_x2[MAYBE_ESI]
						fdivp
						fld dword ptr video_y2[MAYBE_ESI]
						MOVSX_MAYBE_ESI, nvert
						fsub dword ptr video_y2[MAYBE_ESI]
						fmulp
						fadd dword ptr video_y2[MAYBE_ESI]
						fstp dword ptr video_y3[MAYBE_EDI+4]
						jmp JMPR42 }
			      else44:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						#ifdef WINDOWS
			      		mov eax, dword ptr video_y2[esi]
						mov dword ptr video_y3[edi+4], eax }
			      JMPR42:   asm {   mov eax, dword ptr lbxf
						mov dword ptr video_x3[edi+4], eax
						#else
			      		db 0x66; mov ax, word ptr video_y2[si]
						db 0x66; mov word ptr video_y3[di+4], ax }
			      JMPR42:   asm {   db 0x66; mov ax, word ptr lbxf
						db 0x66; mov word ptr video_x3[di+4], ax
						#endif
						add MAYBE_EDI, 8
						jmp STOP4 }
			      else42:   asm {   MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_x2[MAYBE_ESI]
						fcomp dword ptr lbxf
						fstsw ax
						sahf
						jb vnvert4
						mov ax, pvert
						mov vvert, ax
						jmp vpvert4 }
			      vnvert4:  asm {   mov ax, nvert
						mov vvert, ax }
			      vpvert4:  asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_x2[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fcomp dword ptr video_x2[MAYBE_ESI]
						fstsw ax
						sahf
						jne if45
						jmp else45 }
			      if45:     asm {   fld dword ptr lbxf
						fsub dword ptr video_x2[MAYBE_ESI]
						fld dword ptr video_x2[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fsubr dword ptr video_x2[MAYBE_ESI]
						fdivp
						fld dword ptr video_y2[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fsub dword ptr video_y2[MAYBE_ESI]
						fmulp
						fadd dword ptr video_y2[MAYBE_ESI]
						fstp dword ptr video_y3[MAYBE_EDI]
						jmp JMPR41 }
			      else45:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						#ifdef WINDOWS
			      		mov eax, dword ptr video_y2[esi]
						mov dword ptr video_y3[edi], eax }
			      JMPR41:   asm {   mov eax, dword ptr lbxf
						mov dword ptr video_x3[edi], eax
						#else
			      		db 0x66; mov ax, word ptr video_y2[si]
						db 0x66; mov word ptr video_y3[di], ax }
			      JMPR41:   asm {   db 0x66; mov ax, word ptr lbxf
						db 0x66; mov word ptr video_x3[di], ax
						#endif
						add MAYBE_EDI, 4
						jmp STOP4 }
			      else41:   asm {
			      		#ifdef WINDOWS
			      		mov eax, dword ptr video_x2[esi]
						mov dword ptr video_x3[edi], eax
						mov eax, dword ptr video_y2[esi]
						mov dword ptr video_y3[edi], eax
						#else
			      		db 0x66; mov ax, word ptr video_x2[si]
						db 0x66; mov word ptr video_x3[di], ax
						db 0x66; mov ax, word ptr video_y2[si]
						db 0x66; mov word ptr video_y3[di], ax
						#endif
						add MAYBE_EDI, 4 }
			      STOP4:    asm {   inc vr
						mov ax, vr
						cmp ax, vr4
						jnb cutting_end_4
						jmp the_for_4 }

			 cutting_end_4: asm {
			 			#ifdef WINDOWS
			 			mov eax, edi
						shr eax, 2
						#else
			 			mov ax, di
						shr ax, 2
						#endif
						mov vr5, ax }

					if (vr5<3) {
						#ifdef WINDOWS
						asm popad
						#endif
						return;
					}

	   // Lato destro del video.

					asm {   mov vr, 0
						xor MAYBE_EDI, MAYBE_EDI // vr6 * 4
						mov dx, vr5
						dec dx } // vr5 - 1
			      the_for_5:asm {   MOVSX_MAYBE_ESI, vr
						shl MAYBE_ESI, 2
						fld dword ptr video_x3[MAYBE_ESI]
						fcomp dword ptr ubxf
						fstsw ax
						sahf
						ja if51
						jmp else51 }
			      if51:     asm {
			      		#ifdef WINDOWS
			      		mov ebx, esi
			      		#else
			      		mov bx, si // costante vr * 4
						#endif
						mov ax, vr
						sub ax, 1
						jnc pvert5ok
						mov pvert, dx
						jmp pvert5no }
			      pvert5ok: asm     mov pvert, ax
			      pvert5no: asm {   mov ax, vr
						inc ax
						cmp ax, dx
						jbe nvert5ok
						mov nvert, 0
						jmp nvert5no }
			      nvert5ok: asm     mov nvert, ax
			      nvert5no: asm {   shl pvert, 2
						shl nvert, 2
						MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_x3[MAYBE_ESI]
						fcomp dword ptr ubxf
						fstsw ax
						sahf
						jbe CONT5
						MOVSX_MAYBE_ESI, nvert
						fld dword ptr video_x3[MAYBE_ESI]
						fcomp dword ptr ubxf
						fstsw ax
						sahf
						jbe CONT5
						jmp STOP5 }
			      CONT5:    asm {   MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_x3[MAYBE_ESI]
						fcomp dword ptr ubxf
						fstsw ax
						sahf
						jbe ctrl52
						jmp else52 }
			      ctrl52:   asm {   MOVSX_MAYBE_ESI, nvert
						fld dword ptr video_x3[MAYBE_ESI]
						fcomp dword ptr ubxf
						fstsw ax
						sahf
						jbe if52
						jmp else52 }
			      if52:     asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_x3[MAYBE_ESI]
						MOVSX_MAYBE_ESI, pvert
						fcomp dword ptr video_x3[MAYBE_ESI]
						fstsw ax
						sahf
						jne if53
						jmp else53 }
			      if53:     asm {   fld dword ptr ubxf
						fsub dword ptr video_x3[MAYBE_ESI]
						fld dword ptr video_x3[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fsubr dword ptr video_x3[MAYBE_ESI]
						fdivp
						fld dword ptr video_y3[MAYBE_ESI]
						MOVSX_MAYBE_ESI, pvert
						fsub dword ptr video_y3[MAYBE_ESI]
						fmulp
						fadd dword ptr video_y3[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI+4]
						jmp JMPR53 }
			      else53:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_y3[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI+4] }
			      JMPR53:   asm {   mov word ptr mp[MAYBE_EDI], ubx
						mov word ptr mp[MAYBE_EDI+2], 0
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_x3[MAYBE_ESI]
						MOVSX_MAYBE_ESI, nvert
						fcomp dword ptr video_x3[MAYBE_ESI]
						fstsw ax
						sahf
						jne if54
						jmp else54 }
			      if54:     asm {   fld dword ptr ubxf
						fsub dword ptr video_x3[MAYBE_ESI]
						fld dword ptr video_x3[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fsubr dword ptr video_x3[MAYBE_ESI]
						fdivp
						fld dword ptr video_y3[MAYBE_ESI]
						MOVSX_MAYBE_ESI, nvert
						fsub dword ptr video_y3[MAYBE_ESI]
						fmulp
						fadd dword ptr video_y3[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI+12]
						jmp JMPR52 }
			      else54:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_y3[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI+12] }
			      JMPR52:   asm {   mov word ptr mp[MAYBE_EDI+8], ubx
						mov word ptr mp[MAYBE_EDI+10], 0
						add MAYBE_EDI, 16
						jmp STOP5 }
			      else52:   asm {   MOVSX_MAYBE_ESI, pvert
						fld dword ptr video_x3[MAYBE_ESI]
						fcomp dword ptr ubxf
						fstsw ax
						sahf
						ja vnvert5
						mov ax, pvert
						mov vvert, ax
						jmp vpvert5 }
			      vnvert5:  asm {   mov ax, nvert
						mov vvert, ax }
			      vpvert5:  asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_x3[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fcomp dword ptr video_x3[MAYBE_ESI]
						fstsw ax
						sahf
						jne if55
						jmp else55 }
			      if55:     asm {   fld dword ptr ubxf
						fsub dword ptr video_x3[MAYBE_ESI]
						fld dword ptr video_x3[MAYBE_ESI]
						#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fsubr dword ptr video_x3[MAYBE_ESI]
						fdivp
						fld dword ptr video_y3[MAYBE_ESI]
						MOVSX_MAYBE_ESI, vvert
						fsub dword ptr video_y3[MAYBE_ESI]
						fmulp
						fadd dword ptr video_y3[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI+4]
						jmp JMPR51 }
			      else55:   asm {
			      		#ifdef WINDOWS
			      		mov esi, ebx
			      		#else
			      		mov si, bx
			      		#endif
						
						fld dword ptr video_y3[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI+4] }
			      JMPR51:   asm {   mov word ptr mp[MAYBE_EDI], ubx
						mov word ptr mp[MAYBE_EDI+2], 0
						add MAYBE_EDI, 8
						jmp STOP5 }
			      else51:   asm {   fld dword ptr video_x3[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI]
						fld dword ptr video_y3[MAYBE_ESI]
						fistp dword ptr mp[MAYBE_EDI+4]
						add MAYBE_EDI, 8 }
			      STOP5:    asm {   inc vr
						mov ax, vr
						cmp ax, vr5
						jnb cutting_end_5
						jmp the_for_5 }

			 cutting_end_5: asm {   mov _8n, MAYBE_EDI
						sub _8n, 8
						shr MAYBE_EDI, 3
						mov vr6, di }

					if (vr6<3) {
						#ifdef WINDOWS
						asm popad
						#endif
						return;
					}

	/* Riempimento del poligono risultante. */

	// Tracciamento rapido (nr. 3 balletti & via, per i poligoni piccoli)

drawb:	
		#ifdef WINDOWS
		asm popad
		#endif
		
		if (!flares) {
			if (min_y==max_y) {
				if (min_x==max_x)
					adapted[min_x + riga[min_y]] = colore;
				else {
					ptr = max_x + riga[min_y];
					while (max_x>=min_x) {
						adapted[ptr] = colore;
						max_x--;
						ptr--;
					}
				}
				return;
			}
		}

	// Tracciamento complesso.

	// Disegna i bordi del poligono, con la funzione Segmento.

	asm {
		#ifdef WINDOWS
		pushad
		#endif
		xor MAYBE_ESI, MAYBE_ESI
	}
bordo:  asm {
		#ifdef WINDOWS
		mov eax, dword ptr mp[esi]
		mov dword ptr xp, eax
		mov eax, dword ptr mp[esi+4]
		mov dword ptr yp, eax
		mov eax, dword ptr mp[esi+8]
		mov dword ptr xa, eax
		mov eax, dword ptr mp[esi+12]
		mov dword ptr ya, eax
		#else
		db 0x66; mov ax, word ptr mp[si]
		db 0x66; mov word ptr xp, ax
		db 0x66; mov ax, word ptr mp[si+4]
		db 0x66; mov word ptr yp, ax
		db 0x66; mov ax, word ptr mp[si+8]
		db 0x66; mov word ptr xa, ax
		db 0x66; mov ax, word ptr mp[si+12]
		db 0x66; mov word ptr ya, ax
		#endif
		push MAYBE_ESI
		}
		Segmento ();
	asm {   pop MAYBE_ESI
		add MAYBE_ESI, 8
		cmp MAYBE_ESI, _8n
		jb bordo
		#ifdef WINDOWS
		mov eax, dword ptr mp[esi]
		mov dword ptr xp, eax
		mov eax, dword ptr mp[esi+4]
		mov dword ptr yp, eax
		mov eax, dword ptr mp[0]
		mov dword ptr xa, eax
		mov eax, dword ptr mp[4]
		mov dword ptr ya, eax }
		#else
		db 0x66; mov ax, word ptr mp[si]
		db 0x66; mov word ptr xp, ax
		db 0x66; mov ax, word ptr mp[si+4]
		db 0x66; mov word ptr yp, ax
		db 0x66; mov ax, word ptr mp[0]
		db 0x66; mov word ptr xa, ax
		db 0x66; mov ax, word ptr mp[4]
		db 0x66; mov word ptr ya, ax }
		#endif
		Segmento ();
		#ifdef WINDOWS
		asm popad
		#endif
	// Pixel di Partenza.

	#ifdef WINDOWS
	Udword segmptr;
	#else
	Uword segmptr; //= riga[min_y] + min_x;
	#endif
	
	// Pixel d'Arrivo.

	#ifdef WINDOWS
	Udword lim_y; // = riga[max_y] + min_x;
	Udword lim_x; // = segmptr + max_x - min_x;
	Udword bytes; // = lim_x - segmptr + 2;
	Udword min_xDW = min_x;
	Udword max_xDW = max_x;
	Udword min_yDW = min_y;
	Udword max_yDW = max_y;
	#else
	Uword lim_y; // = riga[max_y] + min_x;
	Uword lim_x; // = segmptr + max_x - min_x;
	Uword bytes; // = lim_x - segmptr + 2;
	#endif
	
	asm {
		#ifdef WINDOWS
		pushad
		mov esi, min_yDW
		mov eax, min_xDW
		#else
		mov si, min_y
		mov ax, min_x
		#endif
		add MAYBE_ESI, MAYBE_ESI
		#ifdef WINDOWS
		mov edi, max_yDW
		add eax, dword ptr riga[esi*2]
		mov ebx, min_xDW
		#else
		mov di, max_y
		add ax, word ptr riga[si]
		mov bx, min_x
		#endif
		add MAYBE_EDI, MAYBE_EDI
		#ifdef WINDOWS
		mov segmptr, eax
		add ebx, dword ptr riga[edi*2]
		mov lim_y, ebx
		add eax, max_xDW
		sub eax, min_xDW
		mov lim_x, eax
		sub eax, segmptr
		add eax, 2			//REMOVE4: Maybe remove this line...
		mov bytes, eax
		popad
		#else
		mov segmptr, ax
		add bx, word ptr riga[di]
		mov lim_y, bx
		add ax, max_x
		sub ax, min_x
		mov lim_x, ax
		sub ax, segmptr
		add ax, 2
		mov bytes, ax
		#endif
		}

	// Riempimento (direction flag dev'essere 0)
	asm cld;

	switch (flares) {
		case 0:
			asm {
				#ifdef WINDOWS
				pushad
				mov edi, [adapted]
				#else
				pusha
				les di, dword ptr adapted
				#endif
				add lim_y, MAYBE_EDI
				add MAYBE_EDI, segmptr
				mov al, colore
				mov ah, colore
				SHL_EAX_16
				mov ah, colore }
		linea:  asm {   push MAYBE_EDI
				#ifdef WINDOWS
				mov ecx, bytes
				#else
				mov cx, bytes
				#endif
				mov al, 255
			  repne scasb
				jne pross
				mov MAYBE_ESI, MAYBE_EDI
			   repe scasb
				mov MAYBE_EBX, MAYBE_EDI
			  repne scasb
				jne fb1
			   repe scasb
				dec MAYBE_EDI
				dec MAYBE_ESI
				mov al, colore
				#ifdef WINDOWS
				mov edx, edi
				sub edx, esi
				mov edi, esi
				mov ecx, edx
				shr ecx, 2
				#else
				mov dx, di
				sub dx, si
				mov di, si
				mov cx, dx
				shr cx, 2
				#endif
				jz no_store }
	store_stringdw: asm {
				#ifdef WINDOWS
				mov [edi], eax
				#else
				db 0x26, 0x66, 0x89, 0x05 // mov es:[di], eax
				#endif
				add MAYBE_EDI, 4
				#ifdef WINDOWS
				dec ecx
				#else
				dec cx
				#endif
				jnz store_stringdw }
	   no_store:    asm {   mov cl, dl
				and cl, 3
			    rep stosb
				jmp pross }
		fb1:    asm {   dec MAYBE_ESI
				#ifdef WINDOWS
				dec ebx
				mov ecx, ebx
				mov al, colore
				sub ecx, MAYBE_ESI
				#else
				dec bx
				mov cx, bx
				mov al, colore
				sub MAYBE_ECX, MAYBE_ESI
				#endif
				mov MAYBE_EDI, MAYBE_ESI
			    rep stosb }
		pross:  asm {   pop MAYBE_EDI
				add MAYBE_EDI, 320
				cmp MAYBE_EDI, lim_y
				jbe linea
				#ifdef WINDOWS
				popad	
				#else
				popa
				#endif
				}
			break;
		case 1:
			asm {
				#ifdef WINDOWS
				pushad
				mov edi, [adapted]
				add lim_y, edi
				add edi, segmptr
				#else
				les di, dword ptr adapted
				add lim_y, di
				add di, segmptr
				#endif
				mov al, colore
				and al, 0x3F
				mov colore, al }
		l2:     asm {
				push MAYBE_EDI
				mov MAYBE_ECX, bytes
				mov al, 255
			  repne scasb
				jne pross2
				mov MAYBE_ESI, MAYBE_EDI
			   repe scasb
				mov MAYBE_EBX, MAYBE_EDI
			  repne scasb
				jne fb2
			   repe scasb
				dec MAYBE_EDI
				dec MAYBE_ESI
				mov MAYBE_ECX, MAYBE_EDI
				sub MAYBE_ECX, MAYBE_ESI
				mov MAYBE_EDI, MAYBE_ESI }
		fill2:  asm {
				#ifdef WINDOWS
				mov al, [edi-1]
				#else
				mov al, es:[di-1]
				#endif
				and al, 0x3F
				add al, colore
				cmp al, 62
				jb flow
				mov al, 62 }
		flow:   asm {
				#ifdef WINDOWS
				mov [edi], al
				#else
				mov es:[di], al
				#endif
				inc MAYBE_EDI
				dec MAYBE_ECX
				jnz fill2
				jmp pross2 }
		fb2:    asm {   dec MAYBE_ESI
				dec MAYBE_EBX
				mov MAYBE_ECX, MAYBE_EBX
				sub MAYBE_ECX, MAYBE_ESI
				mov MAYBE_EDI, MAYBE_ESI
				mov dl, colore
				shr dl, 1 }
		fb2a:   asm {
				#ifdef WINDOWS
				mov al, [edi-1]
				#else
				mov al, es:[di-1]
				#endif
				and al, 0x3F
				add al, dl
				cmp al, 62
				jb flow4
				mov al, 62 }
		flow4:  asm {
				#ifdef WINDOWS
				mov [edi], al
				#else
				mov es:[di], al
				#endif
				inc MAYBE_EDI
				dec MAYBE_ECX
				jnz fb2a }
		pross2: asm {
				pop MAYBE_EDI
				add MAYBE_EDI, 320
				cmp MAYBE_EDI, lim_y
				jbe l2
				#ifdef WINDOWS
				popad
				#endif
			}
			break;
		case 2:
			asm {
				#ifdef WINDOWS
				pushad
				mov eax, [adapted]
				mov edi, [adapted]
				#else
				push ds
				les ax, dword ptr adapted
				lds di, dword ptr adapted
				#endif
				add lim_y, MAYBE_EDI
				add MAYBE_EDI, segmptr }
		l3:	asm {	mov al, 0xFF
				push MAYBE_EDI
				mov MAYBE_ECX, bytes
			  repne scasb
				jne pross3
				mov MAYBE_ESI, MAYBE_EDI
			   repe scasb
				mov MAYBE_EBX, MAYBE_EDI
			  repne scasb
				jne fb3
			   repe scasb
				dec MAYBE_EDI
				dec MAYBE_ESI
				mov MAYBE_ECX, MAYBE_EDI
				sub MAYBE_ECX, MAYBE_ESI
				mov MAYBE_EDI, MAYBE_ESI }
		fill3:  asm {   cmp byte ptr [MAYBE_EDI], 0xFF
				jne tsnob
				xor MAYBE_EAX, MAYBE_EAX
				mov ah, [MAYBE_EDI-321]
				and ah, 0x3F
				or ah, 0x40
				mov [MAYBE_EDI], ah
				jmp under }
		tsnob:  asm {   mov al, [MAYBE_EDI]
				and ax, 0x3F
				or  al, 0x40
				add MAYBE_EAX, MAYBE_ECX
				cmp MAYBE_EAX, 128
				jb dnorm
				mov al, 127 }
		dnorm:  asm	mov [MAYBE_EDI], al
		under:  asm {   inc MAYBE_EDI
				dec MAYBE_ECX
				jnz fill3
				jmp pross3 }
		fb3:    asm {   dec MAYBE_ESI
				dec MAYBE_EBX
				mov MAYBE_ECX, MAYBE_EBX
				sub MAYBE_ECX, MAYBE_ESI
				mov MAYBE_EDI, MAYBE_ESI }
		fb3a:   asm {   mov ah, [MAYBE_EDI-321]
				cmp ah, 0xFF
				jne tsnoby
				mov ah, [MAYBE_EDI-642] }
		tsnoby: asm {   and ah, 0x3F
				or ah, 0x40
				mov [MAYBE_EDI], ah
				inc MAYBE_EDI
				dec MAYBE_ECX
				jnz fb3a }
		pross3: asm {   pop MAYBE_EDI
				add MAYBE_EDI, 320
				cmp MAYBE_EDI, lim_y
				ja l3end
				jmp l3 }
		l3end:	
				#ifdef WINDOWS
				asm popad
				#else
				asm	pop ds
				#endif
			break;
		// effetto flares = 3 spostato a "polymap"
		case 4:
			asm {
				#ifdef WINDOWS
				pushad
				mov edi, [adapted]
				#else
				pusha
				les di, dword ptr adapted
				#endif
				add lim_y, MAYBE_EDI
				add MAYBE_EDI, segmptr }
		 fil4a: asm {	mov al, colore
				mov ah, colore
				SHL_EAX_16
				mov ah, colore
				push MAYBE_EDI
				mov MAYBE_ECX, bytes
				mov al, 255
			  repne scasb
				jne fil4d
				mov MAYBE_ESI, MAYBE_EDI
			   repe scasb
				mov MAYBE_EBX, MAYBE_EDI
			  repne scasb
				jne fil4e
			   repe scasb
				dec MAYBE_EDI
				dec MAYBE_ESI
				mov al, colore
				mov MAYBE_EDX, MAYBE_EDI
				sub MAYBE_EDX, MAYBE_ESI
				mov MAYBE_EDI, MAYBE_ESI
				mov MAYBE_ECX, MAYBE_EDX
				shr MAYBE_ECX, 2
				jz fil4c }
		 fil4b: asm {
		 		#ifdef WINDOWS
		 		mov [edi], eax
		 		#else
		 		db 0x26, 0x66, 0x89, 0x05 // mov es:[di], eax
		 		#endif
				add MAYBE_EDI, 4	//REMOVE4: Maybe?
				dec MAYBE_ECX
				jnz fil4b }
		 fil4c: asm {   mov cl, dl
				and cl, 3
			    rep stosb
				jmp fil4d }
		 fil4e: asm {   dec MAYBE_ESI
				dec MAYBE_EBX
				mov MAYBE_ECX, MAYBE_EBX
				mov al, colore
				sub MAYBE_ECX, MAYBE_ESI
				mov MAYBE_EDI, MAYBE_ESI
			    rep stosb }
		 fil4d: asm {   mov al, colore
				mov ah, colore
				and al, 0x3F
				and ah, 0xC0
				add al, ent
				cmp al, 0x3F
				jbe fil4f
				mov al, 0x3F
				test ent, 0x80
				jz  fil4f
				xor al, al }
		 fil4f: asm {   or  al, ah
				mov colore, al
				pop MAYBE_EDI
				add MAYBE_EDI, 320
				cmp MAYBE_EDI, lim_y
				jbe fil4a
				#ifdef WINDOWS
			 	popad
			 	#else
			 	popa
			 	#endif
			 	}
	}
}
#endif

/*

	Sezione per il texture mapping.

*/

#define OK					   1 // Ritorno positivo.
#define NOT_OK					   0 // Ritorno negativo.

Uchar maybehuge *txtr; /* Area della texture (FLS a livelli di intensit…,
			     64 livelli per pixel, senza header).*/

char init_texture_mapping ()
{
	_control87 (MCW_EM, MCW_EM); // disattiva i Floating Point Errors.

	txtr = (Uchar huge *)
	       FARMALLOC ((Dword)TEXTURE_YSIZE * 256 + 16, "init_texture_mapping's txtr");

	if (txtr)
		return (OK);
	else
		return (NOT_OK);
}

char load_texture (char *fname, Dword offset)
				/* Carica una bitmap:
				   formato FLS a livelli di luminanza,
				   64 livelli per pixel, senza header. */
{
	FILEPTR fh;
	Word sl;
	Udword p;

	fh = OPENFILE (fname, OPEN_RB);

	if (fh ISFILEVALID) {
		if (offset>=0)
			FILESEEK (fh, offset, SEEK_SET);
		else
			FILESEEK (fh, offset, SEEK_END);
		sl = 0;
		p  = 12;
		while (sl<TEXTURE_YSIZE && ! FEOF(fh)) {
			READFILE (fh, &txtr[p], TEXTURE_XSIZE);
			p += 256;
			sl++;
		}
		CLOSEFILE (fh);
		if (sl==TEXTURE_YSIZE)
			return (OK);
		else
			return (NOT_OK);
	}
	else
		return (NOT_OK);
}

char fast_load_texture (char *fname) /* Solo per bitmaps 256 x 256. */
{
	FILEPTR fh;
	Udword p;

	fh = OPENFILE (fname, OPEN_RB);

	if (fh ISFILEVALID) {
		p  = 12;
		READFILE (fh, &txtr[p], 32768);
		p += 32768;
		READFILE (fh, &txtr[p], 32768);
		CLOSEFILE (fh);
		return (OK);
	}
	else
		return (NOT_OK);
}

/* Variabili e funzioni per i procedimenti di shading.
   Possono essere cambiate per conferire un aspetto diverso
   ad ogni poligono.

char    shade = 0;        // in che modo i poligoni intercettano la luce

#define NORMAL	     0x00 // luminosit… non curata
*/
			  /* sezione spotlight */
#define SPOTLIGHT    0x10 // torcia elettrica o faro, con centro su <xl, yl>
Word 	xl = x_centro;    // coordinate video del centro di luce
Word	yl = y_centro;	  // coordinata y
Word     aspect = 8;       // aspetto d. proiezione: + alto = + schiacciato
Word     fallout = 20;     // evidenza della zona centrale: + alto = + diffuso
Word     lt_range = 30;    // ampiezza zona illumin.: 0 = infinita
Word     absorption = 45;  // assorbimento della superficie, da 0 a 63

			  /* sezione radiosity semplificata */
#define RADIOSITY    0x20 // luminosit… regolabile orizzontalmente o vertic.
char	shadymask = 1;
Word	shady_aux = 0;

Word 	xsh, ysh, ksh; // variabili di lavoro che devono rientrare in DS.

float 	pnx, pny, pnz; // valori di ritorno della funzione successiva. */

void pnorm (float *x, float *y, float *z)
	// Calcola i coefficenti x/y/z della normale ad un poligono.
	// Valori calcolati in pnx, pny, pnz.
	// Richiesti almeno tre vertici.
	// N.B. I vertici sono scanditi in senso orario,
	//      il vettore risultante rispetta la regola della mano destra.
{
	float x1, y1, z1;
	float x2, y2, z2;
	float xr, yr, zr;

	float ln;

	x1 = x[0] - x[2];
	y1 = y[0] - y[2];
	z1 = z[0] - z[2];
	x2 = x[1] - x[2];
	y2 = y[1] - y[2];
	z2 = z[1] - z[2];

	xr = y1 * z2 - y2 * z1;
	yr = z1 * x2 - z2 * x1;
	zr = x1 * y2 - x2 * y1;

	ln = SQRT (xr * xr + yr * yr + zr * zr);
	if (ln>0) {
		ln  =  1.0 / ln;
		pnx = xr * ln;
		pny = yr * ln;
		pnz = zr * ln;
	}
	else {
		pnx = 0;
		pny = 0;
		pnz = 0;
	}
}

/* Se si desidera una texture sui poligoni, invocare quest'altra funzione.
   Il parametro "tinta" permette di specificare il colore meno luminoso
   di una sequenza di sue copie pi— intense: il numero di queste
   gradazioni non Š importante per polymap.

   E` leggermente pi— lenta nel riempimento, ma non Š grave.
   N.B. Il poligono deve avere sempre 4 vertici, anche se specificare il
	numero di vertici effettivi con il parametro "nv" aggiusta la
	texture in modo che i bordi coincidano.

   P.S. Sulla pagina nascosta, bisogna prevedere un byte in pi— (64001),
	perch‚ vi viene conservato il numero del primo colore della texture,
	dato che i parametri sullo stack non sono raggiungibili nel ciclo
	di tracciamento principale, per ragioni di ottimizzazione. */

float	_0 = 0.0;
float	_16 = 16.0;

float	x_antialias = 1.125;
float	y_antialias = 1.125;
float	z_antialias = 1.125;

char	culling_needed = 0;  // flag: traccia due punti per volta.
char	halfscan_needed = 0; // flag: traccia due linee per volta.

Uchar escrescenze = 0xE0; // primo colore dei bumps (escrescenze)
Word   fpart[MPIY];
Word   ipart[MPIY];

#ifdef OPOLYMAP
#include "opolymap.h"
#elif defined(NPOLYMAP)
#include "npolymap.h"
#else
void polymap (float *x, float *y, float *z, char nv, Uchar tinta)
{
	if (nv==0) return;
	float tempXsize = XSIZE;
	float tempYsize = YSIZE;

	char  _flares = flares;
	float _uno = 1;

	char  culling = culling_needed;
	char  halfscan = halfscan_needed;

	Word   vr22;
	Dword  bndx;

	Word   i, sections;

	Dword  i_low_lim = -10000;
	Dword  i_hig_lim = +10000;

	Dword  u, v, min_y, max_y;
	Dword  x1, y1, x2, y2, ity, jty;

	float k1, k2, k3, k4;
	float hx, vx, ox, hy, vy, oy, hz, vz, oz, _x, _y, _z;
	float kx, rx, ry, rz, mx, my, mz, nx, ny, nz, xx, yy, zz;

	float midx, midy, midz;
	float trxf[4], tryf[4], trzf[4];

	#ifdef WINDOWS
	Dword min_xDW = min_x;
	Dword max_xDW = max_x;
	#endif
	
	// Polymap ha routines fatte per 4 vertici.
	// Se sono 3, l'ultimo va duplicato.

	if (nv==3) {
		x[3] = x[2];
		y[3] = y[2];
		z[3] = z[2];
	}

	// Rototraslazione dei vertici; i dati rimangono ancora 3d.
	
	asm	{
			#ifdef WINDOWS
			pushad
			#endif
			mov doflag, 0
			// if (gamma)
			MOV_EAX_DWORD_PTR _0
			CMP_EAX_DWORD_PTR gamma
			jne t_axis
			jmp no_t_axis }							//	Note: Something in this comments here is seemingly incorrect, but I don't know what. Now that I have this code working, attempting to translate it to C++ is no longer necessary, so I don't need to bother trying to figure out what was mistranslated here. (SL)
	t_axis: asm {   xor MAYBE_EDI, MAYBE_EDI		//	di=0; si=0;
			xor MAYBE_ESI, MAYBE_ESI }
       _vertex: asm {								//	do {		//Or for (di=0, si=0; di!=4; si+=4, di++) {
       		L_DWORD_PTR(es, MAYBE_EBX, z)
		   	fld dword ptr SEGVAR(es, MAYBE_EBX+MAYBE_ESI)
		    fsub cam_z								//		FPa -= cam_z
			fst zz									//		zz = FPa
			fmul opt_tsinbeta						//		FPa *= opt_tsinbeta
			L_DWORD_PTR(es, MAYBE_EBX, x)
		   	fld dword ptr SEGVAR(es, MAYBE_EBX+MAYBE_ESI)
			fsub cam_x								//		FPb -= cam_x
			fst xx									//		xx = FPb
			fmul opt_tcosbeta						//		FPb *= opt_tcosbeta
			faddp									//		FBb += FPa				//FPb is now ST(0) and FPa no longer exists.
			fstp dword ptr rxf[MAYBE_ESI]					//		rxf[si/4] = FPb			//The FP stack is now empty, FPb no longer exists.
			fld zz									//		FPc = zz					//FPc is now ST(0)
			fmul opt_tcosbeta						//		FPc *= opt_tcosbeta
			fld xx									//		FPd = xx					//FPc is now ST(1) and FPb is now ST(0)
			fmul opt_tsinbeta						//		FPd *= opt_tsinbeta
			fsubp									//		FPc -= FPd					//FPc is now ST(0) and FPd no longer exists.
			fst z2									//		z2 = FPc
			fmul opt_tcosalfa						//		FPc *= opt_tcosalfa
			L_DWORD_PTR(es, MAYBE_EBX, y)
		    fld dword ptr SEGVAR(es, MAYBE_EBX+MAYBE_ESI)				//		FPe = (Dword) y[si/4]		//FPe is now ST(0) and FPc is now FP(1)
			fsub cam_y								//		FPe -= cam_y
			fst yy									//		yy = FPe
			fmul opt_tsinalfa						//		FPe *= opt_tsinalfa
			faddp									//		FPc += FPe					//FPc is now ST(0) and FPe no longer exists.
			fst dword ptr rzf[MAYBE_ESI]					//		((Dword[])rzf)[si/4] = FPc
			fcomp uneg								//		lessThanUneg = (FPc<uneg);		//fcomp compares, fstsw stores status word in ax, and sahf later loads it into eflags, so a jb can be done.	//This also pops FPc off the PF stack, leaving it empty
			fstsw ax								
			fld yy									//		FPf = yy						//FPf is ST(0) now
			fmul opt_tcosalfa						//		FPf *= opt_tcosalfa
			fld z2									//		FPg = z2						//FPf is now ST(1), FPg is ST(0)
			fmul opt_tsinalfa						//		FPg *= opt_tsinalfa
			fsubp									//		FPf -= FPg						//FPf is now ST(0), FPg no longer exists.
			fst my									//		my = FPf
			fmul opt_tcosgamma						//		FPf *= opt_tcosgamma
			fld dword ptr rxf[MAYBE_ESI]					//		FPh = ((Dword[])rxf)[si/4]		//FPh is now ST(0), FPf is now ST(1)
			fmul opt_tsingamma						//		FPh *= opt_tsingamma
			fsubp									//		FPf -= FPh						//FPf is now ST(0), FPh no longer exists.
			fstp dword ptr ryf[MAYBE_ESI]					//		((Dword[])ryf)[si/4] = FPf		//FPf no longer exists
			fld my									//		FPi = my
			fmul opt_tsingamma						//		FPi *= opt_tsingamma
			fld dword ptr rxf[MAYBE_ESI]					//		FPj = ((Dword[])rxf)[si/4]		//FPj is now ST(0), FPi is now ST(1)
			fmul opt_tcosgamma						//		FPj *= opt_tcosgamma
			faddp									//		FPi += FPj						//FPi is now ST(0), FPj no longer exists
			fstp dword ptr rxf[MAYBE_ESI]					//		rxf[si/4] = FPi					//FPi no longer exists, stack is empty.
			sahf
			jb _rzf_min_uneg						//		if (!lessThanUneg) {
			inc doflag								//			doflag++;
			mov byte ptr rwf[MAYBE_EDI], 1			//			((byte[])rwf)[di] = 1
			jmp _convert }							//		} else {
 _rzf_min_uneg: asm     mov byte ptr rwf[MAYBE_EDI], 0	//		((byte[])rwf)[di] = 0
      _convert: asm {   add MAYBE_ESI, 4			//		}
			inc MAYBE_EDI							//		si+=4; di++;
			cmp MAYBE_EDI, 4						//	}
			je _end_convert
			jmp _vertex }
  _end_convert: asm	jmp end_convert
	no_t_axis: asm {   
			xor MAYBE_EDI, MAYBE_EDI
			xor MAYBE_ESI, MAYBE_ESI }
	vertex: asm {
			L_DWORD_PTR(es, MAYBE_EBX, z)
			fld dword ptr SEGVAR(es, MAYBE_EBX+MAYBE_ESI)
			fsub cam_z
			fst zz
			fmul opt_tsinbeta
			L_DWORD_PTR(es, MAYBE_EBX, x)
			fld dword ptr SEGVAR(es, MAYBE_EBX+MAYBE_ESI)
			fsub cam_x
			fst xx
			fmul opt_tcosbeta
			faddp
			fstp dword ptr rxf[MAYBE_ESI]
			fld zz
			fmul opt_tcosbeta
			fld xx
			fmul opt_tsinbeta
			fsubp
			fst z2
			fmul opt_tcosalfa
			L_DWORD_PTR(es, MAYBE_EBX, y)
			fld dword ptr SEGVAR(es, MAYBE_EBX+MAYBE_ESI)
			fsub cam_y
			fst yy
			fmul opt_tsinalfa
			faddp
			fst dword ptr rzf[MAYBE_ESI]
			fcomp uneg
			fstsw ax
			fld yy
			fmul opt_tcosalfa
			fld z2
			fmul opt_tsinalfa
			fsubp
			fstp dword ptr ryf[MAYBE_ESI]
			sahf
			jb rzf_min_uneg
			inc doflag
			mov byte ptr rwf[MAYBE_EDI], 1
			jmp convert }
  rzf_min_uneg: asm     mov byte ptr rwf[MAYBE_EDI], 0
       convert: asm {   add MAYBE_ESI, 4
			inc MAYBE_EDI
			cmp MAYBE_EDI, 4
			je end_convert
			jmp vertex }

   end_convert: asm {// if (!doflag) return;
			cmp doflag, 0
			jne vectors
		#ifdef WINDOWS
	   	popad
	   	#endif
	   }

		return;
	// Calcolo dei vettori di tracciamento del texture mapping.
	#ifdef WINDOWS
	int num;
	#endif
       vectors:
	   	#ifdef WINDOWS
		asm popad
	   	Dword esiTmp = 0;
		#endif
		if (nv == 3) {
			midx = (rxf[0] + rxf[1] + rxf[2]) * 0.3333333;
			midy = (ryf[0] + ryf[1] + ryf[2]) * 0.3333333;
			midz = (rzf[0] + rzf[1] + rzf[2]) * 0.3333333;
			for (vr = 0; vr < 3; vr++) {
				trxf[vr] = (rxf[vr] - midx) * x_antialias + midx;
				tryf[vr] = (ryf[vr] - midy) * y_antialias + midy;
				trzf[vr] = (rzf[vr] - midz) * z_antialias + midz;
			}
			#ifdef WINDOWS
			num = 2;
			asm pushad
			esiTmp = 8;	//_ESI = 8;
			#else
			_SI = 8;
			#endif
		}
		else {
			midx = (rxf[0] + rxf[1] + rxf[2] + rxf[3]) * 0.25;
			midy = (ryf[0] + ryf[1] + ryf[2] + ryf[3]) * 0.25;
			midz = (rzf[0] + rzf[1] + rzf[2] + rzf[3]) * 0.25;
			for (vr = 0; vr < 4; vr++) {
				trxf[vr] = (rxf[vr] - midx) * x_antialias + midx;
				tryf[vr] = (ryf[vr] - midy) * y_antialias + midy;
				trzf[vr] = (rzf[vr] - midz) * z_antialias + midz;
			}
			#ifdef WINDOWS
			num = 3;
			asm pushad
			esiTmp = 12;	//_ESI = 12;
			#else
			_SI = 12;
			#endif
		}
		/*#ifdef WINDOWS
		rx = trxf[0];
		mx = trxf[1]-rx;
		nx = rx - trxf[num];
		ry = tryf[0];
		my = tryf[1] - ry;
		ny = ry - tryf[num];
		rz = trzf[0];
		mz = trzf[1] - rz;
		nz = rz - trzf[num];
		#else*/
		asm {
			#ifdef WINDOWS
			mov esi, esiTmp
			#endif
			// rx = rxf[0];
			fld dword ptr trxf[0]
			fstp rx
		     //	mx = rxf[1] - rx;
			fld dword ptr trxf[4]
			fsub rx
			fstp mx
		     //	nx = rx - rxf[3];
			fld rx
			fsub dword ptr trxf[LOCALVAR MAYBE_ESI]	//[ebp+MAYBE_ESI] assembles to the result we want, but that's due to the bug which makes [MAYBE_ESI] assemble wrong...
			fstp nx
		     //	ry = ryf[0];
			fld dword ptr tryf[0]
			fstp ry
		     //	my = ryf[1] - ry;
			fld dword ptr tryf[4]
			fsub ry
			fstp my
		     //	ny = ry - ryf[3];
			fld ry
			fsub dword ptr tryf[LOCALVAR MAYBE_ESI]
			fstp ny
		     //	rz = rzf[0];
			fld dword ptr trzf[0]
			fstp rz
		     //	mz = rzf[1] - rz;
			fld dword ptr trzf[4]
			fsub rz
			fstp mz
		     //	nz = rz - rzf[3];
			fld rz
			fsub dword ptr trzf[LOCALVAR MAYBE_ESI]
			fstp nz }
		//#endif
		asm {// hx = (rx * mz - rz * mx) * YCOEFF;
			fld rx
			fmul mz
			fld rz
			fmul mx
			fsubp
			fmul YCOEFF
			fstp hx
		     // hy = (rx * nz - rz * nx) * YCOEFF;
			fld rx
			fmul nz
			fld rz
			fmul nx
			fsubp
			fmul YCOEFF
			fstp hy
		     // hz = (nx * mz - nz * mx) / dpp;
			fld nx
			fmul mz
			fld nz
			fmul mx
			fsubp
			fmul inv_dpp
			fstp hz
		     //	vx = (rz * my - ry * mz) * XCOEFF;
			fld rz
			fmul my
			fld ry
			fmul mz
			fsubp
			fmul XCOEFF
			fstp vx
		     //	vy = (rz * ny - ry * nz) * XCOEFF;
			fld rz
			fmul ny
			fld ry
			fmul nz
			fsubp
			fmul XCOEFF
			fstp vy
		     //	vz = (nz * my - ny * mz) / dpp;
			fld nz
			fmul my
			fld ny
			fmul mz
			fsubp
			fmul inv_dpp
			fstp vz
		     //	ox = (ry * mx - rx * my) * EMU_K;
			fld ry
			fmul mx
			fld rx
			fmul my
			fsubp
			fmul EMU_K
			fstp ox
		     //	oy = (ry * nx - rx * ny) * EMU_K;
			fld ry
			fmul nx
			fld rx
			fmul ny
			fsubp
			fmul EMU_K
			fstp oy
		     //	oz =  ny * mx - nx * my;
			fld ny
			fmul mx
			fld nx
			fmul my
			fsubp
			fstp oz }

	// Fast-load per poligoni completamente visibili.

		asm {// if (doflag==4) {
			cmp doflag, 4
			jne z_clipping
			xor MAYBE_ESI, MAYBE_ESI
			mov MAYBE_ECX, 4
			mov vr2, 4
			mov vr22, 8 }
	load:   asm {
			MOV_EAX_DWORD_PTR rxf[MAYBE_ESI]
			MOV_EBX_DWORD_PTR ryf[MAYBE_ESI]
			MOV_EDX_DWORD_PTR rzf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_x[MAYBE_ESI], MAYBE_EAX
			MOV_DWORD_PTR ultima_y[MAYBE_ESI], MAYBE_EBX
			MOV_DWORD_PTR ultima_z[MAYBE_ESI], MAYBE_EDX
			
			add MAYBE_ESI, 4
			dec MAYBE_ECX
			jnz load
			jmp to_2d }

	/* Conversione punti alle spalle dell'osservatore
	   rispetto al piano dello schermo. */

    z_clipping: asm {   mov vr, 0
			xor MAYBE_EDI, MAYBE_EDI
			mov dx, 4
			dec dx }
     the_for_1: asm {   MOVSX_MAYBE_ESI, vr
			cmp byte ptr rwf[MAYBE_ESI], 0
			je CONT1
			jmp bypass }
      CONT1:    asm {   mov ax, vr
			sub ax, 1
			jnc pvert1ok
			mov pvert, dx
			jmp pvert1no }
      pvert1ok: asm     mov pvert, ax
      pvert1no: asm {   mov ax, vr
			inc ax
			cmp ax, dx
			jbe nvert1ok
			mov nvert, 0
			jmp nvert1no }
      nvert1ok: asm     mov nvert, ax
      nvert1no: asm {   MOVSX_MAYBE_ESI, pvert
			cmp byte ptr rwf[MAYBE_ESI], 0
			je ctrl1
			jmp JMPR11 }
      ctrl1:    asm {   MOVSX_MAYBE_ESI, nvert
			cmp byte ptr rwf[MAYBE_ESI], 0
			jne JMPR11
			jmp STOP1 }
      JMPR11:   asm {   mov bx, vr
			shl bx, 2
			MOVSX_MAYBE_ESI, pvert
			mov al, byte ptr rwf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, nvert
			add al, byte ptr rwf[MAYBE_ESI]
			cmp al, 2
			je if11
			jmp else11 }
      if11:     asm {   shl pvert, 2
			shl nvert, 2
			MOVSX_MAYBE_ESI, bx
			fld dword ptr rzf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, pvert
			fcomp dword ptr rzf[MAYBE_ESI]
			fstsw ax
			sahf
			jne if12
			jmp else12 }
      if12:     asm {   fld dword ptr uneg
			fsub dword ptr rzf[MAYBE_ESI]
			fld dword ptr rzf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, bx
			fsubr dword ptr rzf[MAYBE_ESI]
			fdivp
			fst zk
			fld dword ptr rxf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, pvert
			fsub dword ptr rxf[MAYBE_ESI]
			fmulp
			fadd dword ptr rxf[MAYBE_ESI]
			fstp dword ptr ultima_x[MAYBE_EDI]
			fld zk
			MOVSX_MAYBE_ESI, bx
			fld dword ptr ryf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, pvert
			fsub dword ptr ryf[MAYBE_ESI]
			fmulp
			fadd dword ptr ryf[MAYBE_ESI]
			fstp dword ptr ultima_y[MAYBE_EDI]
			jmp JMPR12 }
      else12:   asm {   MOVSX_MAYBE_ESI, bx
			MOV_EAX_DWORD_PTR rxf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_x[MAYBE_EDI], MAYBE_EAX
			MOV_EAX_DWORD_PTR ryf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_y[MAYBE_EDI], MAYBE_EAX
			}
      JMPR12:   asm {
      		MOV_EAX_DWORD_PTR uneg
			MOV_DWORD_PTR ultima_z[MAYBE_EDI], MAYBE_EAX
			MOVSX_MAYBE_ESI, bx
			fld dword ptr rzf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, nvert
			fcomp dword ptr rzf[MAYBE_ESI]
			fstsw ax
			sahf
			jne neq1
			jmp eq1 }
      neq1:     asm {   fld dword ptr uneg
			fsub dword ptr rzf[MAYBE_ESI]
			fld dword ptr rzf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, bx
			fsubr dword ptr rzf[MAYBE_ESI]
			fdivp
			fst zk
			fld dword ptr rxf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, nvert
			fsub dword ptr rxf[MAYBE_ESI]
			fmulp
			fadd dword ptr rxf[MAYBE_ESI]
			fstp dword ptr ultima_x[MAYBE_EDI+4]
			fld zk
			MOVSX_MAYBE_ESI, bx
			fld dword ptr ryf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, nvert
			fsub dword ptr ryf[MAYBE_ESI]
			fmulp
			fadd dword ptr ryf[MAYBE_ESI]
			fstp dword ptr ultima_y[MAYBE_EDI+4]
			jmp JMPR13 }
      eq1:      asm {   MOVSX_MAYBE_ESI, bx
			MOV_EAX_DWORD_PTR rxf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_x[MAYBE_EDI+4], MAYBE_EAX
			MOV_EAX_DWORD_PTR ryf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_y[MAYBE_EDI+4], MAYBE_EAX }
      JMPR13:   asm {   MOV_EAX_DWORD_PTR uneg
			MOV_DWORD_PTR ultima_z[MAYBE_EDI+4], MAYBE_EAX
			add MAYBE_EDI, 8
			jmp STOP1 }
      else11:   asm {   MOVSX_MAYBE_ESI, pvert
			cmp byte ptr rwf[MAYBE_ESI], 0
			jne vpvert1
			mov ax, nvert
			mov vvert, ax
			jmp vnvert1 }
      vpvert1:  asm {   mov ax, pvert
			mov vvert, ax }
      vnvert1:  asm {   shl vvert, 2
			MOVSX_MAYBE_ESI, bx
			fld dword ptr rzf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, vvert
			fcomp dword ptr rzf[MAYBE_ESI]
			fstsw ax
			sahf
			jne neq2
			jmp eq2 }
      neq2:     asm {   fld dword ptr uneg
			fsub dword ptr rzf[MAYBE_ESI]
			fld dword ptr rzf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, bx
			fsubr dword ptr rzf[MAYBE_ESI]
			fdivp
			fst zk
			fld dword ptr rxf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, vvert
			fsub dword ptr rxf[MAYBE_ESI]
			fmulp
			fadd dword ptr rxf[MAYBE_ESI]
			fstp dword ptr ultima_x[MAYBE_EDI]
			fld zk
			MOVSX_MAYBE_ESI, bx
			fld dword ptr ryf[MAYBE_ESI]
			MOVSX_MAYBE_ESI, vvert
			fsub dword ptr ryf[MAYBE_ESI]
			fmulp
			fadd dword ptr ryf[MAYBE_ESI]
			fstp dword ptr ultima_y[MAYBE_EDI]
			jmp JMPR14 }
      eq2:      asm {   MOVSX_MAYBE_ESI, bx
			MOV_EAX_DWORD_PTR rxf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_x[MAYBE_EDI], MAYBE_EAX
			MOV_EAX_DWORD_PTR ryf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_y[MAYBE_EDI], MAYBE_EAX }
      JMPR14:   asm {   MOV_EAX_DWORD_PTR uneg
			MOV_DWORD_PTR ultima_z[MAYBE_EDI], MAYBE_EAX
			add MAYBE_EDI, 4
			jmp STOP1 }
      bypass:   asm {   shl MAYBE_ESI, 2
			MOV_EAX_DWORD_PTR rxf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_x[MAYBE_EDI], MAYBE_EAX
			MOV_EAX_DWORD_PTR ryf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_y[MAYBE_EDI], MAYBE_EAX
			MOV_EAX_DWORD_PTR rzf[MAYBE_ESI]
			MOV_DWORD_PTR ultima_z[MAYBE_EDI], MAYBE_EAX
		  	add MAYBE_EDI, 4 }
      STOP1:    asm {   inc vr
			mov ax, vr
			cmp ax, 4
			jnb cutting_end_1
			jmp the_for_1 }

 cutting_end_1: asm {   mov MAYBE_EAX, MAYBE_EDI
			shr MAYBE_EAX, 1
			mov vr22, ax
			shr MAYBE_EAX, 1
			mov vr2, ax }

			if (vr2<3) {
				#ifdef WINDOWS
				asm popad
				#endif
				return;
			}

	   // Queste sono le proiezioni prospettiche da 3d a 2d.
	   // Contemporaneamente, il ciclo ricerca il minimo ed il massimo
	   // verticale dell'estensione del poligono sullo schermo.

	 to_2d: asm {   
		 	MOV_EDX_DWORD_PTR ubyl
			MOV_EBX_DWORD_PTR lbyl
			MOVSX_MAYBE_ESI, vr2
			dec MAYBE_ESI
			shl MAYBE_ESI, 2
			mov MAYBE_EDI, MAYBE_ESI
			add MAYBE_EDI, MAYBE_ESI }
     projector: asm {   fld dpp
			fdiv dword ptr ultima_z[MAYBE_ESI]
			fld st(0)
			fmul dword ptr ultima_x[MAYBE_ESI]
			fadd dword ptr x_centro_f
			fistp dword ptr mp[MAYBE_EDI]
			fmul dword ptr ultima_y[MAYBE_ESI]
			fadd dword ptr y_centro_f
			fistp dword ptr mp[MAYBE_EDI+4]
			CMP_DWORD_PTR mp[MAYBE_EDI+4], MAYBE_EDX
			jnl outr_3
			MOV_EDX_DWORD_PTR mp[MAYBE_EDI+4] }
     outr_3:	asm {	CMP_DWORD_PTR mp[MAYBE_EDI+4], MAYBE_EBX
			jle outr_4
			MOV_EBX_DWORD_PTR mp[MAYBE_EDI+4] }
			
     outr_4:	asm {	sub MAYBE_EDI, 8
			sub MAYBE_ESI, 4
			jnc projector
			MOV_DWORD_PTR max_y, MAYBE_EBX
			MOV_DWORD_PTR min_y, MAYBE_EDX
			}
			
	// Eventuale esclusione di poligoni non visibili.

	asm {// if (min_y>uby) return;
       	MOV_EAX_DWORD_PTR min_y
       	CMP_EAX_DWORD_PTR ubyl
		jle ct1ok
	     // if (max_y<lby) return;
       	MOV_EAX_DWORD_PTR max_y
       	CMP_EAX_DWORD_PTR lbyl
		jnl ct1ok }

       	#ifdef WINDOWS
		asm popad
		#endif
		return;

	// Normalizzazione dei limiti.

ct1ok:	asm {// if (min_y<lby) min_y = lby;
       	MOV_EAX_DWORD_PTR min_y
       	CMP_EAX_DWORD_PTR lbyl
		jnl step_1
       	MOV_EAX_DWORD_PTR lbyl
       	MOV_DWORD_PTR min_y, MAYBE_EAX }

step_1:	asm {// if (max_y>uby) max_y = uby;
      	MOV_EAX_DWORD_PTR max_y
      	CMP_EAX_DWORD_PTR ubyl
		jle step_2
		MOV_EAX_DWORD_PTR ubyl
      	MOV_DWORD_PTR max_y, MAYBE_EAX }

step_2:	asm {// if (min_y>max_y) return;
       	MOV_EAX_DWORD_PTR min_y
       	CMP_EAX_DWORD_PTR max_y
		jle ct2ok }

	#ifdef WINDOWS
	asm popad
	#endif
	return;

	// Inizializzazione costanti di ottimizzazione.

ct2ok:	asm {// k1 = vx * 16;
		fld  vx
		fmul _16
		fstp k1
	     //	k2 = vy * 16;
		fld  vy
		fmul _16
		fstp k2
	     //	k3 = vz * 16;
		fld  vz
		fmul _16
		fstp k3 }

	if (culling) {
		k1 *= 2;
		k2 *= 2;
		k3 *= 2;
	}

	// Inizializzazione delle matrici dei confini orizzontali.

	
	asm {// for (i=min_y; i<=max_y; i++)
		MOV_EDI_DWORD_PTR min_y	//Previously: mov di, word ptr min_y
		MOV_ECX_DWORD_PTR max_y	//Previously: mov cx, word ptr max_y
		
		MOV_EAX_DWORD_PTR lbxl
		MOV_EBX_DWORD_PTR ubxl
		sub MAYBE_ECX, MAYBE_EDI
		shl MAYBE_EDI, 1
		inc MAYBE_ECX
		 }
ol_init:asm {//	fpart[i] = lbxl;
		mov word ptr fpart[MAYBE_EDI], ax
	     // ipart[i] = ubxl;
		mov word ptr ipart[MAYBE_EDI], bx
		add MAYBE_EDI, 2
		dec MAYBE_ECX
		jnz ol_init }
		/*sub MAYBE_ECX, MAYBE_EDI
		shl MAYBE_EDI, 1
		inc MAYBE_ECX }
ol_init:asm {//	fpart[i] = lbxl;
		mov word ptr fpart[MAYBE_EDI], ax
	     // ipart[i] = ubxl;
		mov word ptr ipart[MAYBE_EDI], bx
		add MAYBE_EDI, 2
		dec MAYBE_ECX
		jnz ol_init }
		*/

	// Calcolo confini orizzontali.

	asm {//	mp[vr22]   = mp[0];
	     // mp[vr22+1] = mp[1];
		MOVSX_MAYBE_EDI, vr22
		shl MAYBE_EDI, 2
       	MOV_EAX_DWORD_PTR mp[0]
	  	MOV_EBX_DWORD_PTR mp[4]
	   	MOV_DWORD_PTR mp[MAYBE_EDI], MAYBE_EAX
	   	MOV_DWORD_PTR mp[MAYBE_EDI+4], MAYBE_EBX
		 // for (i = 0; i < vr22; i += 2)
		xor MAYBE_ESI, MAYBE_ESI
		shr vr22, 1 }
extfor: asm {//	y1 = mp[i+1];
	     //	y2 = mp[i+3];
	     //	x1 = mp[i];
	     //	x2 = mp[i+2];
       	MOV_EBX_DWORD_PTR mp[MAYBE_ESI+4]
	  	MOV_EDX_DWORD_PTR mp[MAYBE_ESI+12]
       	MOV_EAX_DWORD_PTR  mp[MAYBE_ESI]
       	MOV_ECX_DWORD_PTR  mp[MAYBE_ESI+8]
	     //	if (y2<y1)
       	CMP MAYBE_EDX, MAYBE_EBX
		jnl noex
       	MOV_DWORD_PTR x1, MAYBE_ECX
      	MOV_DWORD_PTR y1, MAYBE_EDX
      	MOV_DWORD_PTR x2, MAYBE_EAX
       	MOV_DWORD_PTR y2, MAYBE_EBX
		jmp exch }
  noex: asm {// niente scambio
       	MOV_DWORD_PTR x1, MAYBE_EAX
       	MOV_DWORD_PTR y1, MAYBE_EBX
       	MOV_DWORD_PTR x2, MAYBE_ECX
       	MOV_DWORD_PTR y2, MAYBE_EDX
	   }
  exch: asm {// scambio effettuato
	     // if (y2!=y1) [nessuno ha alterato i flags]
		jne ol
		jmp nool } // niente calcolo del bordo: il segmento non si sviluppa in altezza
    ol: asm {// kx = (float)(x2 - x1) / (float)(y2 - y1);
		fild x2
		fisub x1
		fild y2
		fisub y1
		fdivp
		fstp kx
	     // if (y1<lbyl)
       	MOV_EAX_DWORD_PTR y1
       	CMP_EAX_DWORD_PTR lbyl
		jnl nocr
	     // ity = lbyl;
       	MOV_EAX_DWORD_PTR lbyl
       	MOV_DWORD_PTR ity, MAYBE_EAX
		 // x1 += (float)(lbyl-y1) * kx;
		fild x1
		fild lbyl
		fisub y1
		fmul kx
		faddp
		fistp x1
		jmp crct }
  nocr: asm {// ity = y1;
      	MOV_EAX_DWORD_PTR y1
       	MOV_DWORD_PTR ity, MAYBE_EAX }
  crct: asm {// if (y2>ubyl)
       	MOV_EAX_DWORD_PTR y2
       	CMP_EAX_DWORD_PTR ubyl
		jng _nocr
	     // jty = ubyl;
       	MOV_EAX_DWORD_PTR ubyl
       	MOV_DWORD_PTR jty, MAYBE_EAX
		jmp _crct }
 _nocr: asm {// jty = y2;
       	MOV_EAX_DWORD_PTR y2
       	MOV_DWORD_PTR jty, MAYBE_EAX }
 _crct: asm {// bndx = x1;
		fild x1
	     // for (h=ity; h<=jty; h++)
       	MOV_EDI_DWORD_PTR ity
       	MOV_ECX_DWORD_PTR jty
       	CMP MAYBE_EDI, MAYBE_ECX
		jnl noifor
       	SUB MAYBE_ECX, MAYBE_EDI
		shl MAYBE_EDI, 1
		inc MAYBE_ECX }
intfor: asm {// _EAX = bndx;
		fist bndx
		MOV_EAX_DWORD_PTR bndx
		CMP_EAX_DWORD_PTR i_low_lim
		jnl ct01
		MOV_EAX_DWORD_PTR i_low_lim }
ct01:	asm {	CMP_EAX_DWORD_PTR i_hig_lim
		jng ct02
		MOV_EAX_DWORD_PTR i_hig_lim
		}
ct02:	asm {// if (bndx > fpart[h])
		cmp ax, word ptr fpart[MAYBE_EDI]
		jng ct1n
	     //	if (bndx < ubx)
		cmp ax, word ptr ubxl
		jnl ct2n
	     //	fpart[h] = bndx;
		mov word ptr fpart[MAYBE_EDI], ax
		jmp ct1n }
  ct2n: asm {// fpart[h] = ubx;
		mov dx, word ptr ubxl
		mov word ptr fpart[MAYBE_EDI], dx }
  ct1n: asm {// if (bndx < ipart[h])
		cmp ax, word ptr ipart[MAYBE_EDI]
		jnl ct3n
	     //	if (bndx > lbx)
		cmp ax, word ptr lbxl
		jng ct4n
	     //	ipart[h] = bndx;
		mov word ptr ipart[MAYBE_EDI], ax
		jmp ct3n }
  ct4n: asm {//	ipart[h] = lbx;
		mov dx, word ptr lbxl
		mov word ptr ipart[MAYBE_EDI], dx }
  ct3n: asm {// bndx += kx;
		fadd kx
		add MAYBE_EDI, 2
		dec MAYBE_ECX
		jnz intfor }
noifor:	
		FSTP_ST
  nool: asm {   add MAYBE_ESI, 8
		dec vr22
		jz  ol_end
		jmp extfor }

	// Pre-assegnamenti di lavoro.

ol_end:
	/*#ifdef WINDOWS
		//fs is txtr
		//es is adapted
		asm {
			mov esi, [adapted]
			mov al, tinta
			mov byte ptr [esi+0xFA00], al
			mov al, escrescenze
			mov byte ptr [esi+0xFA01], al
		}
	#else*/
	asm {
		L_DWORD_PTR(es, MAYBE_EDX, txtr)
	#ifndef WINDOWS
		mov ax, es			// .
		shr dx, 4			// .
		add ax, dx			// .
		db 0x8e, 0xe0		// mov fs, ax
	#endif
	
		L_DWORD_PTR(es, MAYBE_EAX, adapted)	// caricamento indirizzo area video
		#ifdef WINDOWS
		mov esi, [adapted]
		#endif
		mov al, tinta		// caricamento del primo colore
		mov WONLY_BYTE_PTR RAWSEGVAR(es, esi, 0xFA00), al
		//asm mov es:[0xFA00], al		// .
		mov al, escrescenze		// caricamento primo colore bumps
		mov WONLY_BYTE_PTR RAWSEGVAR(es, esi, 0xFA01), al
		//asm mov es:[0xFA01], al		// .
		
		// Ciclo di tracciamento.
	
				 // for (i=min_y; i<=max_y; i++)
			
		mov ax, word ptr min_y
		mov i, ax
	}
	 trace: asm {//	_z = oz + (hz * (i - y_centro)) + (vz * (ipart[i] - x_centro + 1));
			MOVSX_MAYBE_ESI, i
			shl MAYBE_ESI, 1
			fild word ptr ipart[MAYBE_ESI]
			fsub x_centro_f
			fadd uno
			fld st(0) // duplica (ipart[i] - x_centro + 1)
			fld st(0) // due volte, Š lo stesso per tre calcoli
			fmul vz
			fild i
			fsub y_centro_f
			fmul hz
			faddp
			fadd oz
			fst _z
		     //	k4 = 1 / _z;
			fdivr uno
			fstp k4
		     // _x = ox + (hx * (i - y_centro)) + (vx * (ipart[i] - x_centro + 1));
			fmul vx
			fild i
			fsub y_centro_f
			fmul hx
			faddp
			fadd ox
			fstp _x
		     // _y = oy + (hy * (i - y_centro)) + (vy * (ipart[i] - x_centro + 1));
			fmul vy
			fild i
			fsub y_centro_f
			fmul hy
			faddp
			fadd oy
			fstp _y
		     // u  = (_x * tempXsize) * k4; // Seq. stabile
		     //	v  = (_y * tempYsize) * k4; // Ma usare _control87
			fld _y
			fmul tempYsize
			fmul k4
			fld _x
			fmul tempXsize
			fmul k4
			fxch
			fistp v
			fistp u
		     //	sections = fpart[i] - ipart[i];	// Sequenza stabile.
		     //	_DI = i * 320 + ipart[i];       // Moltiplicazione per 320 in tabella.
		     // SI Š gi… caricato con I * 2.
			MOVSX_MAYBE_EDX, word ptr ipart[MAYBE_ESI]
			MOVSX_MAYBE_EAX, word ptr fpart[MAYBE_ESI]
			mov MAYBE_EDI, RIGA(MAYBE_ESI)
			sub MAYBE_EAX, MAYBE_EDX
			add MAYBE_EDI, MAYBE_EDX
			mov sections, ax
			#ifndef WINDOWS
			push ds
			push es
			pop  ds
//adapted is now ds too.
			#endif
			test culling, 1
			jz row
			jmp c_row }
	 // tracciamento di una scanline: versione ad alto dettaglio
	   row: asm {   cmp sections, 0
			jg  again
			jmp row_end }
	 again:	asm {	cmp sections, 16
			jg  complete
			mov ax, sections
			mov cl, al
			jmp unfinished }
      complete: asm 	mov cl, 16
    unfinished: asm {	sub sections, 16
			cmp cl, 0
			je  row
		     // x += k1;               // Sequenza stabile.
		     // y += k2;	       // Traduzione ASM ok.
		     // z += k3;               // Nessun ritardo grazie a FXCH.
		     // if (z) {               // !! Sequenza instabile.
		     //	k4 = 1 / z;	       // correzione da parte di "_control87"
		     //	u2 = (x * XSIZE) * k4; // Problema: le FISTP possono provocare
		     //	v2 = (y * YSIZE) * k4; // errori di dominio in virgola mobile.
			fld   _z	       // 1 cycle   stack: z
			fadd  k3               // 1 cycle   stack: z+k3
			fld   _x	       // 1 cycle   stack: x, z+k3
			fadd  k1               // 1 cycle   stack: x+k1, z+k3
			fxch                   // no time   stack: z+k3, x+k1
			fst   _z               // 2 cycles  stack: z+k3, x+k1
			fxch                   // no time   stack: x+k1, z+k3
			fst   _x               // 2 cycles  stack: x+k1, z+k3
			fxch                   // no time   stack: z+k3, x+k1
			fdivr _uno             // 39 cycles stack: k4, x+k1
			MOV_EAX_DWORD_PTR u     // while FPU is working,
			MOV_EDX_DWORD_PTR v     // this group takes 0 cycles.
			mov ch, _flares	       //
			DB_0x66; push MAYBE_EBP         //This was just push bp before - but since we manipulate ebp later, we had better push the whole thing
			fxch                   // no time   stack: x+k1, k4
			fmul  tempXsize        // 1 cycle   stack: x..., k4
			fld   _y               // 1 cycle   stack: y, x..., k4
			fadd  k2	       // 1 cycle   stack: y+k2, x..., k4
			fst   _y               // 3 cycles  stack: y+k2, x..., k4
			fmul  tempYsize        // 1 cycle   stack: y..., x..., k4
			fxch                   // no time   stack: x..., y..., k4
			fmul  st, st(2)        // 1 cycle   stack: u, y..., k4
			fxch                   // no time   stack: y..., u, k4
			fmul  st, st(2)        // 1 cycle   stack: v, u, k4
			fxch                   // no time   stack: u, v, k4
			fistp u                // 6 cycles  stack: v, k4
			fistp v                // 6 cycles  stack: k4
			FSTP_ST
	       	MOV_ESI_DWORD_PTR v
			MOV_EBP_DWORD_PTR u
			SUB MAYBE_ESI, MAYBE_EDX
			SUB MAYBE_EBP, MAYBE_EAX
			SAR MAYBE_ESI, 4
			SAR MAYBE_EBP, 4
			test ch, 15		// NORMALE = 0
			jz internal
			test ch, 1		// LUCIDO = 1
			jnz transp
			test ch, 2		// BRILLANTE = 2
			jnz bright
			test ch, 4		// TRASLUCIDO = 4
			jnz merger
			jmp bumper }		// BUMP MAPPING = 8
      internal:	asm {
		  	xor MAYBE_EBX, MAYBE_EBX
		  	mov bh, dh		// 1 (riempimento normale)
			inc MAYBE_EDI			// *
			mov bl, ah		// 1
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	#endif
		  	mov ch, RAWSEGVAR(ds, esi, 0xFA00)	// *
			#ifdef WINDOWS
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]
			pop esi
		  	#else
		  	db 0x64, 0x02, 0x2F 	// 1+PFX+AGI (add ch, fs:[bx])
			#endif
		  	add MAYBE_EAX, MAYBE_EBP		// *
			#ifdef WINDOWS
		  	mov byte ptr [esi+edi-1], ch		// 1	//mov byte ptr [esi+edi+3], ch		//REMOVE4?
		  	#else
		  	mov [MAYBE_EDI+3], ch		// 1
			#endif
		  	#ifdef WINDOWS
			pop esi
			#endif
		  	add MAYBE_EDX, MAYBE_ESI		// *
			dec cl			// 1
			jnz internal  		// 7 cicli.
			jmp common }
      transp:  	asm {
		  	xor MAYBE_EBX, MAYBE_EBX
		  	mov bh, dh		// 1 (riempimento lucido)
			inc MAYBE_EDI			// *
			mov bl, ah		// 1
			#ifdef WINDOWS
		  	push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+edi-1]		// *	//mov ch, byte ptr [esi+edi+3]	//REMOVE4?
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
		  	
		  	add eax, ebp		// *
			mov byte ptr [esi+edi-1], ch		// 1	//mov byte ptr [esi+edi+3], ch		//REMOVE4?
			pop esi
		  	#else
		  	mov ch, [di+3]		// *
			db 0x64, 0x02, 0x2F 	// 1+PFX+AGI (add ch, fs:[bx])
		  	add ax, bp		// *
			mov [di+3], ch		// 1
			#endif
			add MAYBE_EDX, MAYBE_ESI		// *
			dec cl			// 1
			jnz transp		// 7 cicli.
			jmp common }
      bright:  	asm {
		  	#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+edi]	//REMOVED4: Was mov ch, byte ptr [esi+edi+4]
		  	pop esi
		  	#else
		  	mov ch, [di+4]		// 1 (riempimento brillante)
			#endif
		  	mov bh, dh		// *
			inc MAYBE_EDI			// 1
			mov bl, ah		// *
			and ch, 0x3F		// 1
			add MAYBE_EAX, MAYBE_EBP		// *
			#ifdef WINDOWS
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			#else
		  	db 0x64, 0x02, 0x2F 	// 1+PFX (add ch, fs:[bx])
			#endif
		  	add MAYBE_EDX, MAYBE_ESI		// *
			cmp ch, 0x3E		// 1
			jbe antibloom		// * (antiblooming)
			mov ch, 0x3E }		// 1
      antibloom:asm {
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	and byte ptr [esi+edi-1], 0xC0	//and byte ptr [esi+edi+3], 0xC0		//REMOVED4
		  	or byte ptr [esi+edi-1], ch		//or byte ptr [esi+edi+3], ch		//REMOVED4
		  	pop esi
		  	#else
		  	and byte ptr [di+3],0xC0// 1
			or  [di+3], ch		// 1
			#endif
		  	dec cl			// *
			jnz bright		// 1/0 (9-10 cicli.)
			jmp common }
      merger:  	asm {
		  	#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+edi]	//mov ch, byte ptr [esi+edi+4]		//REMOVED4
		  	pop esi
		  	and ebx, 0xffff
		  	#else
		  	mov ch, [di+4]		// 1 (traslucido)
			#endif
		  	mov bh, dh		// *
			inc MAYBE_EDI			// 1
			mov bl, ah		// *
			and ch, 0x3F		// 1
			add MAYBE_EAX, MAYBE_EBP		// *
			#ifdef WINDOWS
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
		  	push esi
		  	mov esi, [adapted]
		  	add ch, byte ptr [esi+0xFA00]
		  	pop esi
		  	#else
		  	db 0x64, 0x02, 0x2F 	// 1+PFX (add ch, fs:[bx])
			add ch, ds:[0xFA00]
			#endif
		  	add MAYBE_EDX, MAYBE_ESI		// *
			shr ch, 1		// 1
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	and byte ptr [esi+edi-1], 0xC0	//REMOVED4, was +3
		  	or byte ptr [esi+edi-1], ch		//REMOVED4, was +3
			pop esi
			#else
		  	and byte ptr [di+3],0xC0// 1
			or  [di+3], ch		// 1
			#endif
			dec cl			// *
			jnz merger		// 1 (9 cicli.)
			jmp common }
      bumper:  	asm {
		  	xor MAYBE_EBX, MAYBE_EBX
		  	mov bh, dh		// 1 (bump mapping)
			inc MAYBE_EDI			// *
			mov bl, ah		// 1
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+0xFA00]
			pop esi
		  	push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			#else
			mov ch, ds:[0xFA00]	// *
			db 0x64, 0x02, 0x2F 	// 1+PFX+AGI (add ch, fs:[bx])
			#endif
			add MAYBE_EAX, MAYBE_EBP		// *
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov byte ptr [esi+edi-1], ch		// 1			//REMOVED4, was +3
			pop esi
		  	#else
			mov [di+3], ch
			#endif
			push MAYBE_EDI
			push cx
			and ch, 0x7
		}
		bmpm320:
		asm {
			sub MAYBE_EDI, 320
			dec ch
			jns bmpm320
			pop cx
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	sub ch, byte ptr [esi+0xFA00]
			add ch, byte ptr [esi+0xFA01]
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			mov byte ptr [esi+edi+640-1], ch	//REMOVED4, was +3
			pop esi
			#else
			sub ch, ds:[0xFA00]
			add ch, ds:[0xFA01]	// *
			db 0x64, 0x02, 0x2F 	// 1+PFX+AGI (add ch, fs:[bx])
			mov byte ptr [di+640+3], ch
			#endif
			pop MAYBE_EDI
			add MAYBE_EDX, MAYBE_ESI		// *
			dec cl			// 1
			jnz bumper } 		// ? cicli.
	common:	asm {
			DB_0x66; pop MAYBE_EBP
			jmp row }
	 // tracciamento di una scanline: versione a basso dettaglio
	 c_row: asm {   cmp sections, 0
			jg  c_again
			jmp row_end }
       c_again:	asm {	cmp sections, 32
			jg  c_complete
			mov ax, sections
			add ax, 2
			mov cl, al
			jmp c_unfinished }
    c_complete: asm  	mov cl, 32
  c_unfinished: asm {	sub sections, 32
			cmp cl, 2
			jl  c_row
			fld   _z	       // 1 cycle   stack: z
			fadd  k3               // 1 cycle   stack: z+k3
			fld   _x	       // 1 cycle   stack: x, z+k3
			fadd  k1               // 1 cycle   stack: x+k1, z+k3
			fxch                   // no time   stack: z+k3, x+k1
			fst   _z               // 2 cycles  stack: z+k3, x+k1
			fxch                   // no time   stack: x+k1, z+k3
			fst   _x               // 2 cycles  stack: x+k1, z+k3
			fxch                   // no time   stack: z+k3, x+k1
			fdivr _uno             // 39 cycles stack: k4, x+k1
	       	MOV_EAX_DWORD_PTR u 	// while FPU is working,
	  		MOV_EDX_DWORD_PTR v     // this group takes 0 cycles.
			shr cl, 1	       //
			DB_0x66; push MAYBE_EBP         //This was just push bp before - but since we manipulate ebp later, we had better push the whole thing
			
			mov ch, _flares	       //
			push MAYBE_EDI		       //
			fxch                   // no time   stack: x+k1, k4
			fmul  tempXsize        // 1 cycle   stack: x..., k4
			fld   _y               // 1 cycle   stack: y, x..., k4
			fadd  k2	       // 1 cycle   stack: y+k2, x..., k4
			fst   _y               // 3 cycles  stack: y+k2, x..., k4
			fmul  tempYsize        // 1 cycle   stack: y..., x..., k4
			fxch                   // no time   stack: x..., y..., k4
			fmul  st, st(2)        // 1 cycle   stack: u, y..., k4
			fxch                   // no time   stack: y..., u, k4
			fmul  st, st(2)        // 1 cycle   stack: v, u, k4
			fxch                   // no time   stack: u, v, k4
			fistp u                // 6 cycles  stack: v, k4
			fistp v                // 6 cycles  stack: k4
			FSTP_ST
			MOV_ESI_DWORD_PTR v
	       	MOV_EBP_DWORD_PTR u
	       	SUB MAYBE_ESI, MAYBE_EDX
	       	SUB MAYBE_EBP, MAYBE_EAX
	       	SAR MAYBE_ESI, 4
	       	SAR MAYBE_EBP, 4
	       	test ch, 15 		// NORMALE = 0
			jz c_internal
			test ch, 1		// LUCIDO = 1
			jnz c_transp
			test ch, 2		// BRILLANTE = 2
			jnz c_bright
			test ch, 4		// TRASLUCIDO = 4
			jnz c_merger
			jmp c_bumper }		// BUMP MAPPING = 8
    c_internal:	asm {
			xor MAYBE_EBX, MAYBE_EBX
			mov bh, dh		// 1 (riempimento normale)
			add MAYBE_EDI, 2		// *
			mov bl, ah		// 1
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+0xFA00]
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			pop esi
			#else
			mov ch, ds:[0xFA00]	// *
			db 0x64, 0x02, 0x2F 	// 1+PFX+AGI (add ch, fs:[bx])
			#endif
			add MAYBE_EAX, MAYBE_EBP		// *
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov [esi+edi-2], ch	//REMOVED4, was +2
			mov [esi+edi-1], ch	//REMOVED4, was +3
			pop esi
			#else
			mov [di+2], ch		// 1
			mov [di+3], ch		// *
			#endif
			add MAYBE_EDX, MAYBE_ESI		// 1
			dec cl   		// *
			jnz c_internal  	// 1 (8 cicli).
			jmp c_common }
    c_transp:  	asm {
			xor MAYBE_EBX, MAYBE_EBX
			mov bh, dh		// 1 (riempimento lucido)
			add MAYBE_EDI, 2		// *
			mov bl, ah		// 1
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+edi-1]	//REMOVED4, was +3
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			pop esi
			#else
			mov ch, [di+3]		// *
			db 0x64, 0x02, 0x2F 	// 1+PFX+AGI (add ch, fs:[bx])
			#endif
			add MAYBE_EAX, MAYBE_EBP		// *
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov byte ptr [esi+edi-2], ch	//REMOVED4, was +2
			mov byte ptr [esi+edi-1], ch	//REMOVED4, was +3
			pop esi
			#else
			mov [di+2], ch		// 1
			mov [di+3], ch		// *
			#endif
			add MAYBE_EDX, MAYBE_ESI		// 1
			dec cl   		// *
			jnz c_transp		// 1 (8 cicli).
			jmp c_common }
    c_bright:  	asm {
    		#ifdef WINDOWS
    		push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+edi]	//REMOVED4, was +4
    		pop esi
			#else
    		mov ch, [di+4]		// 1 (riempimento brillante)
    		#endif
			xor MAYBE_EBX, MAYBE_EBX
			mov bh, dh		// *
			add MAYBE_EDI, 2		// 1
			mov bl, ah		// *
			and ch, 0x3F		// 1
			add MAYBE_EAX, MAYBE_EBP		// *
			#ifdef WINDOWS
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			#else
			db 0x64, 0x02, 0x2F 	// 1+PFX (add ch, fs:[bx])
			#endif
			add MAYBE_EDX, MAYBE_ESI		// *
			cmp ch, 0x3E		// 1
			jbe c_antibloom		// * (antiblooming)
			mov ch, 0x3E }		// 1
    c_antibloom:asm {
//ds and es are still adapted, fs is still txtr
    		#ifdef WINDOWS
    		push esi
		  	mov esi, [adapted]
		  	and byte ptr [esi+edi-2], 0xC0	//REMOVED4, was +2
    		or ch, byte ptr [esi+edi-2]	//REMOVED4, was +2
    		dec cl
    		mov byte ptr [esi+edi-2], ch	//REMOVED4, was +2
    		mov byte ptr [esi+edi-1], ch	//REMOVED4, was +3
    		pop esi
			#else
    		and byte ptr [di+2],0xC0// 1
			or  ch, [di+2]		// 1
			dec cl    		// 1
			mov [di+2], ch		// *
			mov [di+3], ch		// 1
			#endif
			jnz c_bright		// 0 (11 cicli.)
			jmp c_common }
    c_merger:  	asm {
    		#ifdef WINDOWS
    		push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+edi]	//REMOVED4, was +4
			pop esi
    		#else
    		mov ch, [di+4]		// 1 (traslucido)
			#endif
			xor MAYBE_EBX, MAYBE_EBX
			mov bh, dh		// *
			add MAYBE_EDI, 2		// 1
			mov bl, ah		// *
			and ch, 0x3F		// 1
			add MAYBE_EAX, MAYBE_EBP		// *
			#ifdef WINDOWS
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			push esi
		  	mov esi, [adapted]
		  	add ch, [esi+0xFA00]
			pop esi
			#else
			db 0x64, 0x02, 0x2F 	// 1+PFX (add ch, fs:[bx])
			add ch, ds:[0xFA00]
			#endif
			add MAYBE_EDX, MAYBE_ESI		// *
			shr ch, 1		// 1
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	and byte ptr [esi+edi-2],0xC0// *	//REMOVED4, was +2
			or  ch, byte ptr [esi+edi-2]		// 1	//REMOVED4, was +2
			dec cl   		// *
			mov byte ptr [esi+edi-2], ch		// 1	//REMOVED4, was +2
			mov byte ptr [esi+edi-1], ch		// *	//REMOVED4, was +3
			pop esi
			#else
			and byte ptr [di+2],0xC0// *
			or  ch, [di+2]		// 1
			dec cl   		// *
			mov [di+2], ch		// 1
			mov [di+3], ch		// *
			#endif
			jnz c_merger		// 1 (9 cicli.)
			jmp c_common }
      c_bumper: asm {
      		xor MAYBE_EBX, MAYBE_EBX
      		mov bh, dh		// 1 (bump mapping)
			add MAYBE_EDI, 2		// *
			mov bl, ah		// 1
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	mov ch, byte ptr [esi+0xFA00]	// *
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			add eax, ebp		// *
			mov byte ptr [esi+edi-2], ch		// 1	//REMOVED4, was +2
			mov byte ptr [esi+edi-1], ch		// 1	//REMOVED4, was +3
			pop esi
		  	push edi
			#else
			mov ch, ds:[0xFA00]	// *
			db 0x64, 0x02, 0x2F 	// 1+PFX+AGI (add ch, fs:[bx])
			add ax, bp		// *
			
			mov [di+2], ch		// 1
			mov [di+3], ch		// 1
			push di
			#endif
			push cx
			and ch, 0x7 }
      c_bmpm320:asm {
      		sub MAYBE_EDI, 320
			dec ch
			jns c_bmpm320
			pop cx
			#ifdef WINDOWS
			push esi
		  	mov esi, [adapted]
		  	sub ch, byte ptr [esi+0xFA00]
			add ch, byte ptr [esi+0xFA01]
			push esi
		  	mov esi, [txtr]
		  	add ch, byte ptr [esi+ebx-4]	//add ch, byte ptr txtr[ebx]
			pop esi
			mov byte ptr [esi+edi+640-2], ch	//REMOVED4, was +2
		  	mov byte ptr [esi+edi+640-1], ch	//REMOVED4, was +3
			pop esi
		  	pop edi
			#else
			sub ch, ds:[0xFA00]
			add ch, ds:[0xFA01]	// *
			db 0x64, 0x02, 0x2F 	// 1+PFX+AGI (add ch, fs:[bx])
			mov byte ptr [di+640+2], ch
			mov byte ptr [di+640+3], ch
			pop di
			#endif
			add MAYBE_EDX, MAYBE_ESI		// *
			dec cl			// 1
			jnz c_bumper } 		// ? cicli.
      c_common:	asm {
      		pop MAYBE_EDI
			DB_0x66; pop MAYBE_EBP         //This was just push bp before - but since we manipulate ebp later, we had better push the whole thing
			add MAYBE_EDI, 32
			jmp c_row }
	// codice inter-scanline: fra una scanline e la successiva...
       row_end: asm {	test halfscan, 1
			jz do_singlescan
			inc i
			mov ax, word ptr max_y
			cmp ax, i
			#ifndef WINDOWS
			pop ds
			#endif
			jb trace_end
			MOVSX_MAYBE_ESI, i
			shl MAYBE_ESI, 1
			mov dx, word ptr ipart[MAYBE_ESI-2]
			mov ax, word ptr fpart[MAYBE_ESI-2]
			#ifdef WINDOWS
			mov edi, dword ptr riga[MAYBE_ESI*2]
			#else
			mov di, word ptr riga[MAYBE_ESI]
			push ds
			push es
			pop  ds
			#endif
			//and now ds is adapted again
			sub MAYBE_EAX, MAYBE_EDX
			jc do_singlescan
			jz do_singlescan
			add MAYBE_EDI, MAYBE_EDX }
     duplicate: asm {
     		#ifdef WINDOWS
     		push esi
		  	mov esi, [adapted]
		  	mov dl, byte ptr [esi+edi-320]	//REMOVED4, was -316
			mov byte ptr [esi+edi], dl	//REMOVED4, was +4
			mov byte ptr [esi+edi+320], dl	//REMOVED4, was +324
			pop esi
		 	#else
     		mov dl, [di-316]
			mov [di+4], dl
			mov [di+324], dl
			#endif
			inc MAYBE_EDI
			dec MAYBE_EAX
			jnz duplicate }
 do_singlescan:	asm {	inc i
			xor MAYBE_EAX, MAYBE_EAX
			mov ax, word ptr max_y
			cmp ax, i
			#ifndef WINDOWS
			pop ds
			#endif
			jb trace_end
			jmp trace }
     trace_end:      // Fine tracciamento.
			#ifdef WINDOWS
			asm popad
			#endif
	//error("polymap finished");
}
#endif

void Forward (float delta) /* Provoca l'avanzamento dell'osservatore
			      nella direzione di volo di <delta>
			      unit… virtuali. */
{
	cam_x -= delta * opt_tsinbeta * opt_tcosalfa;
	cam_z += delta * opt_tcosbeta * opt_tcosalfa;
	cam_y += delta * opt_tsinalfa;
}

Dword _x_, _y_;

char getcoords (float x, float y, float z)
{ // calcola le coordinate sullo schermo di un punto nello spazio,
  // usando lo stesso nucleo di calcolo di poly3d e di polymap,
  // se il punto rientra nello schermo ritorna 1, altrimenti ritorna 0.
  // le coordinate sono poi trasferite nelle variabili _x_ e _y_.
  // il punto non andrebbe tracciato se non Š visibile, perch‚
  // le coordinate risulterebbero, in tal caso, indeterminabili.

	float rx, ry, rz, my;

		asm {// if (gamma != 0) goto t_axis;
			#ifdef WINDOWS
	       	pushad
			#endif
			MOV_EAX_DWORD_PTR _0
	       	CMP_EAX_DWORD_PTR gamma
		jne t_axis
			jmp no_t_axis }
	t_axis: asm {	fld z
			fsub cam_z
			fst zz
			fmul opt_tsinbeta
			fld x
			fsub cam_x
			fst xx
			fmul opt_tcosbeta
			faddp
			fstp rx
			fld zz
			fmul opt_tcosbeta
			fld xx
			fmul opt_tsinbeta
			fsubp
			fst z2
			fmul opt_tcosalfa
			fld y
			fsub cam_y
			fst yy
			fmul opt_tsinalfa
			faddp
			fst rz
			fcomp uneg
			fstsw ax
			fld yy
			fmul opt_tcosalfa
			fld z2
			fmul opt_tsinalfa
			fsubp
			fst my
			fmul opt_tcosgamma
			fld rx
			fmul opt_tsingamma
			fsubp
			fstp ry
			fld my
			fmul opt_tsingamma
			fld rx
			fmul opt_tcosgamma
			faddp
			fstp rx
			sahf
			jb _rzf_min_uneg
			jmp convert }
 _rzf_min_uneg: 	
				#ifdef WINDOWS
				asm popad
				#endif
				return (0);

     no_t_axis: asm {   fld z
			fsub cam_z
			fst zz
			fmul opt_tsinbeta
			fld x
			fsub cam_x
			fst xx
			fmul opt_tcosbeta
			faddp
			fstp rx
			fld zz
			fmul opt_tcosbeta
			fld xx
			fmul opt_tsinbeta
			fsubp
			fst z2
			fmul opt_tcosalfa
			fld y
			fsub cam_y
			fst yy
			fmul opt_tsinalfa
			faddp
			fst rz
			fcomp uneg
			fstsw ax
			fld yy
			fmul opt_tcosalfa
			fld z2
			fmul opt_tsinalfa
			fsubp
			fstp ry
			sahf
			jb rzf_min_uneg
			jmp convert }
  rzf_min_uneg: 	
				#ifdef WINDOWS
				asm popad
				#endif
				return (0);

       convert: //my  = dpp / rz;
		//_x_ = my * rx + x_centro_f;
		//_y_ = my * ry + y_centro_f;

		asm {
			fld dpp
			fdiv rz
			fld st(0)
			fmul rx
			fadd x_centro_f
			fistp _x_
			fmul ry
			fadd y_centro_f
			fistp _y_
		}
		#ifdef WINDOWS
		asm popad
		#endif
				
		if (_x_ > lbxl && _x_ < ubxl && _y_ > lbyl && _y_ < ubyl) {
			return (1);
		} else {
			return (0);
		}
}

char facing (float *x, float *y, float *z)
{ /* Controlla se un poligono a una sola faccia Š visibile o meno.
     Certo che come procedimento non Š poi tanto semplice: va calcolata,
     anche approssimativamente, la normale alla superficie; comunque,
     sempre meglio che calcolare tutto il poligono... */
	float x1, y1, z1, x2, y2, z2, xr, yr, zr;
	char retval;
	asm {
		
		#ifdef WINDOWS
		pushad
		mov ebx, [x]
		mov esi, [y]
		mov edi, [z]
		fld   dword ptr [ebx]
		fsub  dword ptr [ebx+8]
		fstp  x1
		fld   dword ptr [esi]
		fsub  dword ptr [esi+8]
		fstp  y1
		fld   dword ptr [edi]
		fsub  dword ptr [edi+8]
		fstp  z1
		fld   dword ptr [ebx+4]
		fsub  dword ptr [ebx+8]
		fstp  x2
		fld   dword ptr [esi+4]
		fsub  dword ptr [esi+8]
		fstp  y2
		fld   dword ptr [edi+4]
		fsub  dword ptr [edi+8]
		
		#else
		les   bx, dword ptr x
		mov   si, word ptr  y
		mov   di, word ptr  z
		fld   dword ptr es:[bx]
		fsub  dword ptr es:[bx+8]
		fstp  x1
		fld   dword ptr es:[si]
		fsub  dword ptr es:[si+8]
		fstp  y1
		fld   dword ptr es:[di]
		fsub  dword ptr es:[di+8]
		fstp  z1
		fld   dword ptr es:[bx+4]
		fsub  dword ptr es:[bx+8]
		fstp  x2
		fld   dword ptr es:[si+4]
		fsub  dword ptr es:[si+8]
		fstp  y2
		fld   dword ptr es:[di+4]
		fsub  dword ptr es:[di+8]
		#endif
		fst   z2
		fmul  y1
		fld   y2
		fmul  z1
		fsubp
		fstp  xr
		fld   z1
		fmul  x2
		fld   z2
		fmul  x1
		fsubp
		fstp  yr
		fld   x1
		fmul  y2
		fld   x2
		fmul  y1
		fsubp
		fstp  zr
		fld   cam_x
		#ifdef WINDOWS
		fsub dword ptr [ebx+8]
		#else
		fsub  dword ptr es:[bx+8]
		#endif
		fmul  xr
		fld   cam_y
		#ifdef WINDOWS
		fsub dword ptr [esi+8]
		#else
		fsub  dword ptr es:[si+8]
		#endif
		fmul  yr
		faddp
		fld   cam_z
		#ifdef WINDOWS
		fsub dword ptr [edi+8]
		#else
		fsub  dword ptr es:[di+8]
		#endif
		fmul  zr
		faddp
		ftst
		fstsw ax
		ffree st(0)
		fincstp
		xor dl, dl
		sahf
		jb _zero
		not dl
		mov retval, dl
	}
_zero:		
	#ifdef WINDOWS
	asm popad
	#endif
				
	return (retval);
}
