code:
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.

static long dmval;

#pragma aux sqr =\
	"imul eax, eax",\
	parm nomemory [eax]\
	modify exact [eax]\
	value [eax]

#pragma aux scale =\
	"imul edx",\
	"idiv ecx",\
	parm nomemory [eax][edx][ecx]\
	modify exact [eax edx]\

#pragma aux mulscale =\
	"imul edx",\
	"shrd eax, edx, cl",\
	parm nomemory [eax][edx][ecx]\
	modify exact [eax edx]\

#pragma aux mulscale1 =\
	"imul edx",\
	"shrd eax, edx, 1",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale2 =\
	"imul edx",\
	"shrd eax, edx, 2",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale3 =\
	"imul edx",\
	"shrd eax, edx, 3",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale4 =\
	"imul edx",\
	"shrd eax, edx, 4",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale5 =\
	"imul edx",\
	"shrd eax, edx, 5",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale6 =\
	"imul edx",\
	"shrd eax, edx, 6",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale7 =\
	"imul edx",\
	"shrd eax, edx, 7",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale8 =\
	"imul edx",\
	"shrd eax, edx, 8",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale9 =\
	"imul edx",\
	"shrd eax, edx, 9",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale10 =\
	"imul edx",\
	"shrd eax, edx, 10",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale11 =\
	"imul edx",\
	"shrd eax, edx, 11",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale12 =\
	"imul edx",\
	"shrd eax, edx, 12",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale13 =\
	"imul edx",\
	"shrd eax, edx, 13",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale14 =\
	"imul edx",\
	"shrd eax, edx, 14",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale15 =\
	"imul edx",\
	"shrd eax, edx, 15",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale16 =\
	"imul edx",\
	"shrd eax, edx, 16",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale17 =\
	"imul edx",\
	"shrd eax, edx, 17",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale18 =\
	"imul edx",\
	"shrd eax, edx, 18",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale19 =\
	"imul edx",\
	"shrd eax, edx, 19",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale20 =\
	"imul edx",\
	"shrd eax, edx, 20",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale21 =\
	"imul edx",\
	"shrd eax, edx, 21",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale22 =\
	"imul edx",\
	"shrd eax, edx, 22",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale23 =\
	"imul edx",\
	"shrd eax, edx, 23",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale24 =\
	"imul edx",\
	"shrd eax, edx, 24",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale25 =\
	"imul edx",\
	"shrd eax, edx, 25",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale26 =\
	"imul edx",\
	"shrd eax, edx, 26",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale27 =\
	"imul edx",\
	"shrd eax, edx, 27",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale28 =\
	"imul edx",\
	"shrd eax, edx, 28",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale29 =\
	"imul edx",\
	"shrd eax, edx, 29",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale30 =\
	"imul edx",\
	"shrd eax, edx, 30",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale31 =\
	"imul edx",\
	"shrd eax, edx, 31",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\

#pragma aux mulscale32 =\
	"imul edx",\
	parm nomemory [eax][edx]\
	modify exact [eax edx]\
	value [edx]\

#pragma aux dmulscale =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, cl",\
	parm nomemory [eax][edx][esi][edi][ecx]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale1 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 1",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale2 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 2",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale3 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 3",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale4 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 4",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale5 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 5",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale6 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 6",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale7 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 7",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale8 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 8",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale9 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 9",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale10 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 10",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale11 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 11",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale12 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 12",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale13 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 13",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale14 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 14",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale15 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 15",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale16 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 16",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale17 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 17",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale18 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 18",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale19 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 19",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale20 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 20",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale21 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 21",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale22 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 22",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale23 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 23",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale24 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 24",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale25 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 25",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale26 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 26",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale27 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 27",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale28 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 28",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale29 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 29",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale30 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 30",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale31 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	"shrd eax, edx, 31",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\

#pragma aux dmulscale32 =\
	"imul edx",\
	"mov ebx, eax",\
	"mov eax, esi",\
	"mov esi, edx",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, esi",\
	parm nomemory [eax][edx][esi][edi]\
	modify exact [eax ebx edx esi]\
	value [edx]\

#pragma aux tmulscale1 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 1",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale2 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 2",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale3 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 3",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale4 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 4",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale5 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 5",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale6 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 6",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale7 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 7",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale8 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 8",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale9 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 9",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale10 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 10",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale11 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 11",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale12 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 12",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale13 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 13",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale14 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 14",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale15 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 15",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale16 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 16",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale17 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 17",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale18 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 18",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale19 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 19",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale20 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 20",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale21 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 21",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale22 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 22",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale23 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 23",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale24 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 24",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale25 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 25",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale26 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 26",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale27 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 27",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale28 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 28",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale29 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 29",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale30 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 30",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale31 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	"shrd eax, edx, 31",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux tmulscale32 =\
	"imul edx",\
	"xchg eax, ebx",\
	"xchg edx, ecx",\
	"imul edx",\
	"add ebx, eax",\
	"adc ecx, edx",\
	"mov eax, esi",\
	"imul edi",\
	"add eax, ebx",\
	"adc edx, ecx",\
	parm nomemory [eax][edx][ebx][ecx][esi][edi]\
	modify exact [eax ebx ecx edx]\
	value [edx]\

#pragma aux boundmulscale =\
	"imul ebx",\
	"mov ebx, edx",\
	"shrd eax, edx, cl",\
	"sar edx, cl",\
	"xor edx, eax",\
	"js checkit",\
	"xor edx, eax",\
	"jz skipboundit",\
	"cmp edx, 0xffffffff",\
	"je skipboundit",\
	"checkit:",\
	"mov eax, ebx",\
	"sar eax, 31",\
	"xor eax, 0x7fffffff",\
	"skipboundit:",\
	parm nomemory [eax][ebx][ecx]\
	modify exact [eax ebx edx]\

#pragma aux divscale =\
	"mov edx, eax",\
	"shl eax, cl",\
	"neg cl",\
	"sar edx, cl",\
	"idiv ebx",\
	parm nomemory [eax][ebx][ecx]\
	modify exact [eax ecx edx]\

#pragma aux divscale1 =\
	"add eax, eax",\
	"sbb edx, edx",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale2 =\
	"mov edx, eax",\
	"sar edx, 30",\
	"lea eax, [eax*4]",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale3 =\
	"mov edx, eax",\
	"sar edx, 29",\
	"lea eax, [eax*8]",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale4 =\
	"mov edx, eax",\
	"sar edx, 28",\
	"shl eax, 4",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale5 =\
	"mov edx, eax",\
	"sar edx, 27",\
	"shl eax, 5",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale6 =\
	"mov edx, eax",\
	"sar edx, 26",\
	"shl eax, 6",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale7 =\
	"mov edx, eax",\
	"sar edx, 25",\
	"shl eax, 7",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale8 =\
	"mov edx, eax",\
	"sar edx, 24",\
	"shl eax, 8",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale9 =\
	"mov edx, eax",\
	"sar edx, 23",\
	"shl eax, 9",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale10 =\
	"mov edx, eax",\
	"sar edx, 22",\
	"shl eax, 10",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale11 =\
	"mov edx, eax",\
	"sar edx, 21",\
	"shl eax, 11",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale12 =\
	"mov edx, eax",\
	"sar edx, 20",\
	"shl eax, 12",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale13 =\
	"mov edx, eax",\
	"sar edx, 19",\
	"shl eax, 13",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale14 =\
	"mov edx, eax",\
	"sar edx, 18",\
	"shl eax, 14",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale15 =\
	"mov edx, eax",\
	"sar edx, 17",\
	"shl eax, 15",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale16 =\
	"mov edx, eax",\
	"sar edx, 16",\
	"shl eax, 16",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale17 =\
	"mov edx, eax",\
	"sar edx, 15",\
	"shl eax, 17",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale18 =\
	"mov edx, eax",\
	"sar edx, 14",\
	"shl eax, 18",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale19 =\
	"mov edx, eax",\
	"sar edx, 13",\
	"shl eax, 19",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale20 =\
	"mov edx, eax",\
	"sar edx, 12",\
	"shl eax, 20",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale21 =\
	"mov edx, eax",\
	"sar edx, 11",\
	"shl eax, 21",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale22 =\
	"mov edx, eax",\
	"sar edx, 10",\
	"shl eax, 22",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale23 =\
	"mov edx, eax",\
	"sar edx, 9",\
	"shl eax, 23",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale24 =\
	"mov edx, eax",\
	"sar edx, 8",\
	"shl eax, 24",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale25 =\
	"mov edx, eax",\
	"sar edx, 7",\
	"shl eax, 25",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale26 =\
	"mov edx, eax",\
	"sar edx, 6",\
	"shl eax, 26",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale27 =\
	"mov edx, eax",\
	"sar edx, 5",\
	"shl eax, 27",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale28 =\
	"mov edx, eax",\
	"sar edx, 4",\
	"shl eax, 28",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale29 =\
	"mov edx, eax",\
	"sar edx, 3",\
	"shl eax, 29",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale30 =\
	"mov edx, eax",\
	"sar edx, 2",\
	"shl eax, 30",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale31 =\
	"mov edx, eax",\
	"sar edx, 1",\
	"shl eax, 31",\
	"idiv ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax edx]\

#pragma aux divscale32 =\
	"xor eax, eax",\
	"idiv ebx",\
	parm nomemory [edx][ebx]\
	modify exact [eax edx]\

#pragma aux int5 =\
	"int 0x5",\

#pragma aux setvmode =\
	"int 0x10",\
	parm [eax]\

#pragma aux setupmouse =\
	"mov ax, 0",\
	"int 33h",\
	"and eax, 0x0000ffff",\
	modify exact [eax]\

#pragma aux readmousexy =\
	"mov ax, 11d",\
	"int 33h",\
	"mov [esi], cx",\
	"mov [edi], dx",\
	parm [esi][edi]\
	modify exact [eax ebx ecx edx]\

#pragma aux readmousebstatus =\
	"mov ax, 5d",\
	"int 33h",\
	"mov [esi], ax",\
	parm [esi]\
	modify exact [eax ebx ecx edx]\

#pragma aux readpixel =\
	"mov al, byte ptr [edi]",\
	parm nomemory [edi]\
	modify exact [eax]\

#pragma aux drawpixel =\
	"mov byte ptr [edi], al",\
	parm [edi][eax]\
	modify exact \

#pragma aux drawpixels =\
	"mov word ptr [edi], ax",\
	parm [edi][eax]\
	modify exact \

#pragma aux drawpixelses =\
	"mov dword ptr [edi], eax",\
	parm [edi][eax]\
	modify exact \

#pragma aux clearbuf =\
	"rep stosd",\
	parm [edi][ecx][eax]\
	modify exact [edi ecx]\

#pragma aux clearbufbyte =\
	"cmp ecx, 4",\
	"jae longcopy",\
	"test cl, 1",\
	"jz preskip",\
	"stosb",\
	"preskip: shr ecx, 1",\
	"rep stosw",\
	"jmp endit",\
	"longcopy: test edi, 1",\
	"jz skip1",\
	"stosb",\
	"dec ecx",\
	"skip1: test edi, 2",\
	"jz skip2",\
	"stosw",\
	"sub ecx, 2",\
	"skip2: mov ebx, ecx",\
	"shr ecx, 2",\
	"rep stosd",\
	"test bl, 2",\
	"jz skip3",\
	"stosw",\
	"skip3: test bl, 1",\
	"jz endit",\
	"stosb",\
	"endit:",\
	parm [edi][ecx][eax]\
	modify [ebx]\

#pragma aux copybuf =\
	"rep movsd",\
	parm [esi][edi][ecx]\
	modify exact [ecx esi edi]\

#pragma aux copybufbyte =\
	"cmp ecx, 4",\
	"jae longcopy",\
	"test cl, 1",\
	"jz preskip",\
	"movsb",\
	"preskip: shr ecx, 1",\
	"rep movsw",\
	"jmp endit",\
	"longcopy: test edi, 1",\
	"jz skip1",\
	"movsb",\
	"dec ecx",\
	"skip1: test edi, 2",\
	"jz skip2",\
	"movsw",\
	"sub ecx, 2",\
	"skip2: mov ebx, ecx",\
	"shr ecx, 2",\
	"rep movsd",\
	"test bl, 2",\
	"jz skip3",\
	"movsw",\
	"skip3: test bl, 1",\
	"jz endit",\
	"movsb",\
	"endit:",\
	parm [esi][edi][ecx]\
	modify [ebx]\

#pragma aux copybufreverse =\
	"shr ecx, 1",\
	"jnc skipit1",\
	"mov al, byte ptr [esi]",\
	"dec esi",\
	"mov byte ptr [edi], al",\
	"inc edi",\
	"skipit1: shr ecx, 1",\
	"jnc skipit2",\
	"mov ax, word ptr [esi-1]",\
	"sub esi, 2",\
	"ror ax, 8",\
	"mov word ptr [edi], ax",\
	"add edi, 2",\
	"skipit2: test ecx, ecx",\
	"jz endloop",\
	"begloop: mov eax, dword ptr [esi-3]",\
	"sub esi, 4",\
	"bswap eax",\
	"mov dword ptr [edi], eax",\
	"add edi, 4",\
	"dec ecx",\
	"jnz begloop",\
	"endloop:",\
	parm [esi][edi][ecx]\

#pragma aux qinterpolatedown16 =\
	"mov ebx, ecx",\
	"shr ecx, 1",\
	"jz skipbegcalc",\
	"begqcalc: lea edi, [edx+esi]",\
	"sar edx, 16",\
	"mov dword ptr [eax], edx",\
	"lea edx, [edi+esi]",\
	"sar edi, 16",\
	"mov dword ptr [eax+4], edi",\
	"add eax, 8",\
	"dec ecx",\
	"jnz begqcalc",\
	"test ebx, 1",\
	"jz skipbegqcalc2",\
	"skipbegcalc: sar edx, 16",\
	"mov dword ptr [eax], edx",\
	"skipbegqcalc2:",\
	parm [eax][ecx][edx][esi]\
	modify exact [eax ebx ecx edx edi]\

#pragma aux qinterpolatedown16short =\
	"test ecx, ecx",\
	"jz endit",\
	"test al, 2",\
	"jz skipalignit",\
	"mov ebx, edx",\
	"sar ebx, 16",\
	"mov word ptr [eax], bx",\
	"add edx, esi",\
	"add eax, 2",\
	"dec ecx",\
	"jz endit",\
	"skipalignit: sub ecx, 2",\
	"jc finishit",\
	"begqcalc: mov ebx, edx",\
	"add edx, esi",\
	"sar ebx, 16",\
	"mov edi, edx",\
	"and edi, 0ffff0000h",\
	"add edx, esi",\
	"add ebx, edi",\
	"mov dword ptr [eax], ebx",\
	"add eax, 4",\
	"sub ecx, 2",\
	"jnc begqcalc",\
	"test cl, 1",\
	"jz endit",\
	"finishit: mov ebx, edx",\
	"sar ebx, 16",\
	"mov word ptr [eax], bx",\
	"endit:",\
	parm [eax][ecx][edx][esi]\
	modify exact [eax ebx ecx edx edi]\

#pragma aux setcolor16 =\
	"mov dx, 0x3ce",\
	"shl ax, 8",\
	"out dx, ax",\
	parm [eax]\
	modify exact [eax edx]\

#pragma aux vlin16first =\
	"mov al, byte ptr [edi]",\
	"mov eax, ecx",\
	"shr ecx, 2",\
	"begvlin16firsta: mov byte ptr [edi], al",\
	"mov byte ptr [edi+80], al",\
	"mov byte ptr [edi+160], al",\
	"mov byte ptr [edi+240], al",\
	"add edi, 320",\
	"dec ecx",\
	"jnz begvlin16firsta",\
	"mov ecx, eax",\
	"and ecx, 3",\
	"jz skipfirst",\
	"begvlin16firstb: mov byte ptr [edi], al",\
	"add edi, 80",\
	"dec ecx",\
	"jnz begvlin16firstb",\
	"skipfirst:",\
	parm [edi][ecx]\
	modify exact [eax ecx edi]\

#pragma aux vlin16 =\
	"mov esi, edi",\
	"begvlin16: movsb",\
	"add edi, 79",\
	"add esi, 79",\
	"dec ecx",\
	"jnz begvlin16",\
	parm [edi][ecx]\
	modify exact [ecx esi edi]\

#pragma aux drawpixel16 =\
	"mov ecx, edi",\
	"mov eax, 0x00008008",\
	"mov dx, 0x3ce",\
	"ror ah, cl",\
	"shr edi, 3",\
	"out dx, ax",\
	"mov cl, byte ptr [edi+0xa0000]",\
	"mov byte ptr [edi+0xa0000], al",\
	parm [edi]\
	modify exact [eax ecx edx edi]\

#pragma aux fillscreen16 =\
	"mov dx, 0x3ce",\
	"shl ax, 8",\
	"out dx, ax",\
	"mov ax, 0xff08",\
	"out dx, ax",\
	"shr ecx, 5",\
	"add edi, 0xa0000",\
	"rep stosd",\
	parm [edi][eax][ecx]\
	modify exact [eax ecx edx edi]\

#pragma aux koutp =\
	"out dx, al",\
	parm [edx][eax]\
	modify exact \

#pragma aux koutpw =\
	"out dx, ax",\
	parm [edx][eax]\
	modify exact \

#pragma aux kinp =\
	"in al, dx",\
	parm nomemory [edx]\
	modify exact [eax]\

#pragma aux mul3 =\
	"lea eax, [eax+eax*2]",\
	parm nomemory [eax]\

#pragma aux mul5 =\
	"lea eax, [eax+eax*4]",\
	parm nomemory [eax]\

#pragma aux mul9 =\
	"lea eax, [eax+eax*8]",\
	parm nomemory [eax]\

	//returns eax/ebx, dmval = eax%edx;
#pragma aux divmod =\
	"xor edx, edx",\
	"div ebx",\
	"mov dmval, edx",\
	parm [eax][ebx]\
	modify exact [eax edx]\
	value [eax]

	//returns eax%ebx, dmval = eax/edx;
#pragma aux moddiv =\
	"xor edx, edx",\
	"div ebx",\
	"mov dmval, eax",\
	parm [eax][ebx]\
	modify exact [eax edx]\
	value [edx]

#pragma aux klabs =\
	"test eax, eax",\
	"jns skipnegate",\
	"neg eax",\
	"skipnegate:",\
	parm nomemory [eax]\

#pragma aux ksgn =\
	"add ebx, ebx",\
	"sbb eax, eax",\
	"cmp eax, ebx",\
	"adc al, 0",\
	parm nomemory [ebx]\
	modify exact [eax ebx]\

	//eax = (unsigned min)umin(eax,ebx)
#pragma aux umin =\
	"sub eax, ebx",\
	"sbb ecx, ecx",\
	"and eax, ecx",\
	"add eax, ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax ecx]\

	//eax = (unsigned max)umax(eax,ebx)
#pragma aux umax =\
	"sub eax, ebx",\
	"sbb ecx, ecx",\
	"xor ecx, 0xffffffff",\
	"and eax, ecx",\
	"add eax, ebx",\
	parm nomemory [eax][ebx]\
	modify exact [eax ecx]\

#pragma aux kmin =\
	"cmp eax, ebx",\
	"jl skipit",\
	"mov eax, ebx",\
	"skipit:",\
	parm nomemory [eax][ebx]\
	modify exact [eax]\

#pragma aux kmax =\
	"cmp eax, ebx",\
	"jg skipit",\
	"mov eax, ebx",\
	"skipit:",\
	parm nomemory [eax][ebx]\
	modify exact [eax]\

#pragma aux limitrate =\
	"mov dx, 0x3da",\
	"wait1: in al, dx",\
	"test al, 8",\
	"jnz wait1",\
	"wait2: in al, dx",\
	"test al, 8",\
	"jz wait2",\
	modify exact [eax edx]\

#pragma aux readtimer =\
	"mov al, 0xd2",\
	"out 0x43, al",\
	"in al, 0x40",\
	"shl eax, 24",\
	"in al, 0x40",\
	"rol eax, 8",\
	modify [eax]\

#pragma aux redblueblit = \
	"xor ecx, ecx",\
	"begblit: mov eax, dword ptr [edx+ecx]",\
	"shl eax, 4",\
	"add eax, dword ptr [ebx+ecx]",\
	"mov dword ptr [ecx+0xa0000], eax",\
	"add ecx, 4",\
	"cmp ecx, esi",\
	"jb begblit",\
	parm [ebx][edx][esi]\
	modify exact [eax ecx]\

#pragma aux chainblit =\
	"shr ecx, 1",\
	"jnc prebeg",\
	"mov al, byte ptr [esi+8]",\
	"mov ah, byte ptr [esi+12]",\
	"shl eax, 16",\
	"mov al, byte ptr [esi]",\
	"mov ah, byte ptr [esi+4]",\
	"mov dword ptr [edi], eax",\
	"add esi, 16",\
	"add edi, 4",\
	"test ecx, ecx",\
	"prebeg: jz endit",\
	"beg: mov al, byte ptr [esi+8]",\
	"mov bl, byte ptr [esi+24]",\
	"mov ah, byte ptr [esi+12]",\
	"mov bh, byte ptr [esi+28]",\
	"shl eax, 16",\
	"add edi, 8",\
	"shl ebx, 16",\
	"mov al, byte ptr [esi]",\
	"mov bl, byte ptr [esi+16]",\
	"mov ah, byte ptr [esi+4]",\
	"mov bh, byte ptr [esi+20]",\
	"add esi, 32",\
	"mov dword ptr [edi-8], eax",\
	"dec ecx",\
	"mov dword ptr [edi-4], ebx",\
	"jnz beg",\
	"endit:",\
	parm [esi][edi][ecx]\
	modify exact [eax ebx ecx esi edi]\

#pragma aux swapchar =\
	"mov cl, [eax]",\
	"mov ch, [ebx]",\
	"mov [ebx], cl",\
	"mov [eax], ch",\
	parm [eax][ebx]\
	modify exact [ecx]\

#pragma aux swapshort =\
	"mov cx, [eax]",\
	"mov dx, [ebx]",\
	"mov [ebx], cx",\
	"mov [eax], dx",\
	parm [eax][ebx]\
	modify exact [ecx edx]\

#pragma aux swaplong =\
	"mov ecx, [eax]",\
	"mov edx, [ebx]",\
	"mov [ebx], ecx",\
	"mov [eax], edx",\
	parm [eax][ebx]\
	modify exact [ecx edx]\

#pragma aux swapbuf4 =\
	"begswap:",\
	"mov esi, [eax]",\
	"mov edi, [ebx]",\
	"mov [ebx], esi",\
	"mov [eax], edi",\
	"add eax, 4",\
	"add ebx, 4",\
	"dec ecx",\
	"jnz short begswap",\
	parm [eax][ebx][ecx]\
	modify exact [eax ebx ecx esi edi]\

#pragma aux swap64bit =\
	"mov ecx, [eax]",\
	"mov edx, [ebx]",\
	"mov [ebx], ecx",\
	"mov ecx, [eax+4]",\
	"mov [eax], edx",\
	"mov edx, [ebx+4]",\
	"mov [ebx+4], ecx",\
	"mov [eax+4], edx",\
	parm [eax][ebx]\
	modify exact [ecx edx]\

	//swapchar2(ptr1,ptr2,xsiz); is the same as:
	//swapchar(ptr1,ptr2); swapchar(ptr1+1,ptr2+xsiz);
#pragma aux swapchar2 =\
	"add esi, ebx",\
	"mov cx, [eax]",\
	"mov dl, [ebx]",\
	"mov [ebx], cl",\
	"mov dh, [esi]",\
	"mov [esi], ch",\
	"mov [eax], dx",\
	parm [eax][ebx][esi]\
	modify exact [ecx edx esi]\

static long timeroffs1mhz;
	//accutimeroffs = -8-(t1-t0);
#pragma aux inittimer1mhz =\
	"xor ebx, ebx",\
	"xor ecx, ecx",\
	"in al, 0x61",\
	"or al, 1",\
	"out 0x61, al",\
	"mov al, 0x34",\
	"out 0x43, al",\
	"xor al, al",\
	"out 0x40, al",\
	"mov al, 0xb4",\
	"out 0x43, al",\
	"mov al, 240",\
	"out 0x42, al",\
	"xor al, al",\
	"cli",\
	"out 0x40, al",\
	"dec al",\
	"out 0x42, al",\
	"mov al, 0x04",\
	"out 0x43, al",\
	"in al, 0x40",\
	"mov bl, al",\
	"in al, 0x40",\
	"mov bh, al",\
	"mov al, 0x84",\
	"out 0x43, al",\
	"in al, 0x42",\
	"mov cl, al",\
	"in al, 0x42",\
	"sti",\
	"mov ch, al",\
	"sub ebx, ecx",\
	"sub ebx, 8",\
	"mov timeroffs1mhz, ebx",\
	modify exact [eax ebx ecx]\

#pragma aux uninittimer1mhz =\
	"in al, 0x61",\
	"and al, 252",\
	"out 0x61, al",\
	modify exact [eax]\

	//t = ((ecx-ebx+timeroffs1mhz)&0xfff0)*4095 + ecx;
#pragma aux gettime1mhz =\
	"mov ebx, timeroffs1mhz",\
	"xor ecx, ecx",\
	"mov al, 0x04",\
	"cli",\
	"out 0x43, al",\
	"in al, 0x40",\
	"sub bl, al",\
	"in al, 0x40",\
	"sbb bh, al",\
	"mov al, 0x84",\
	"out 0x43, al",\
	"in al, 0x42",\
	"mov cl, al",\
	"in al, 0x42",\
	"sti",\
	"mov ch, al",\
	"add ebx, ecx",\
	"and ebx, 0x0000fff0",\
	"sub ecx, ebx",\
	"shl ebx, 12",\
	"add ebx, ecx",\
	modify exact [eax ebx ecx]\
	value [ebx]\

	//eax = eax-ebx; if (eax < 0) eax += (1<<28) - (1<<16);
#pragma aux deltatime1mhz =\
	"sub eax, ebx",\
	"jnc skipit",\
	"add eax, 0x0fff0000",\
	"skipit:",\
	parm [ebx][eax]\


code:
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.

All of my Build Engine code is designed specifically for the Watcom C/C++ 11.0
compiler. You're on your own if you attempt to use any other compiler.

To best view my source, set your "Tab Stops" to 3!

---------------  Engine files required to compile a Build game  ---------------

ENGINE.C: All the major C code is in here
   Graphics functions:
      Function to draw everything in the 3D view
      Function to draw the 2D texturized map view
      Function to draw status bar pieces
      Function to change screen size (+, -, Field of view (shrunk mode))
      Line drawing for both 2D and 3D modes
      Simple 8*8 and 3*5 font routines (mostly used in BUILD editor)
      Screen capture PCX code
      Functions to load palette
      Functions to set video modes
      Function to flip screen pages
      Function to generate palette lookup tables
      Function to set gamma correction
      Functions to help with mirrors (they weren't fully built in to the engine)
      Stereoscopic modes (red blue glasses, Crystal Eyes, Nuvision)
   Movement functions:
      Function to detect if 2 points can see each other
      Function to find where an instant weapon (pistol, shotgun, chaingun) hits
      Function to determine if you're near a tagged object
      Collision detection for all sprites (with smooth sliding)
      Collision detection to keep you away from moving objects
   Boring functions:
      Functions to load/save MAP files
      Function to load ART file
      Disk caching system
      Functions to manipulate sprite linked lists
   Helper functions:
      A couple of line intersection functions
      A couple of math routines like faster atan2, sqrt, 2D rotation
      Functions to help with animation of certain doors & tiles
      Function to move vertices connected to many walls
      A function that returns what sector something is in
      Some Build editor functions also used in games

CACHE1D.C:
   Contains a unique LRU-style caching system
   Group file code to handle all file loading transparently
   Compression & Decompression routines used in .DMO files

A.ASM: (pure assembly routines)
   8 routines for horizontal texture mapping, special cases for
        masked mapping, translucent masked mapping, and # pixels at a time
   11 routines for vertical texture mapping, special cases for
        masked mapping, translucent masked mapping, # pixels at a time,
        slopes, voxels

   NOTE: This assembly code is designed for WASM (the assembler that ships
      with Watcom C/C++ 11.0) In order to make it work under MASM, you will
      have to make some simple modifications:

      1. At the top of the file, change ".586P" to ".386P"

      2. If the assembler complains that a jump is out of range, go to the
         line of the error and remove the word "short" from the line. For
         example, change: "jnc short mylabel" to just: "jnc mylabel"

      3. If you get an error message like: "Symbol not defined: XE9", you
         need to convert the value to a hex format that the assembler
         understands. For example, change "mov al, 0xe9" to: "mov al, 0e9h"
         (You need an extra 0 in front if the left-most digit is a letter)

BUILD.H:
   Sector, Wall, Sprite structures, defines and other documented shared
   variables.  While I designed the format of the structures, the "game"
   developers were very involved with what went into them.

PRAGMAS.H:
   Tons of Watcom in-line assembly pragmas, such as 64-bit multiply and
   divide routines, memory clear & move, and a lot of cute ones for doing
   math, etc.

VES2.H:
   VESA 2.0 routines used by the Build engine. This code unfortunately is
   somewhat integrated with ENGINE.C

MMULTI.C:
   Contains mid-level network routines.  This file arbitrated between
   COMMIT and the game code.  I had to write error correction in this
   module because COMMIT didn't have it.

   NOTE: By default, my Build test uses MULTI.C instead of MMULTI.C. My game
      is the only Build game that does this; all commercial Build games use
      MMULTI.C.

   You can use the COMMIT driver with my test game. You will probably find
   that there are more problems in general - this is not because MMULTI.C
   or COMMIT are bad; it's because I always used MULTI.C by default with
   my Build game. (I used my 2DRAW engine to test the MMULTI.C code.)
   Follow these instructions exactly if you want to use MMULTI.C:

      1. In the makefile, replace all occurrences of "multi" with "mmulti"

      2. In GAME.C, on line 448, Remove the comment in front of the call to
         waitforeverybody(). This needs to be done because my MMULTI.C code
         doesn't have a "sendlogon" function. You will get severe lag if you
         forget to do this.

      3. To run the game, you must first setup BOTH setup programs (on ALL
         computers)

         A) First edit the parameters inside COMMIT.DAT to match your desired
            multiplayer configuration.

         B) Then go into my Build setup program. Under the communications
            menu, set the NUMBER OF PLAYERS. For a COMMIT game, the specific
            ports, etc. have no effect and don't really matter. Press ENTER
            a few times to get through the rest of the menus. I know this
            seems silly, but at the time, it seemed like the simplest way to
            get my GAME.C code to work with both MULTI.C and MMULTI.C.

--------  Additional source required to compile Ken's Build test game  --------

GAME.C:
   Sample code for a complete game.  Well it's not really complete unless
      you loved Ken's Labyrinth.  This code wasn't actually used in the
      distributed games, but it was an important code base for the developers
      to look at when they had questions.  Some of their routines were lifted
      straight from this code.

NAMES.H: EDITART updates this file every time you type in a name. This .H
   file is just a convenient way to access textures inside the game code.

MULTI.C: Before I added support for COMMIT, I had my own COM/network routines.
   This file is almost identical to MMULTI.C.  You will have to change a few
   minor things like function parameters if you want to update my game to use
   MMULTI.C & COMMIT instead.

KDMENG.C: KDM (Ken's Digital Music) sound playback engine, C code
K.ASM: KDM (Ken's Digital Music) sound playback engine, Assembly code

-----------  Additional source required to compile the Build editor  ----------

BUILD.C:
   Combine this code with the engine and you get the Build editor. You will
   find all of the editing functions from the Build editor in here (2D and 3D)

BSTUB.C:
   Game teams were able to customize certain things in the Build editor with
   this module.

---------------------------------  Make file  ---------------------------------

   You can use my makefile if you wish - it shows you my compile options:
MAKEFILE.: A very simple make file.
   Type: "wmake" or "wmake game.exe" to compile my build test game
   Type: "wmake build.exe" to compile my build editor

-------------------------------  Documentation  -------------------------------

   This is the documentation I wrote for the game programmers. Please keep in
   mind that I never gave out the source to my engine (ENGINE.C, CACHE1D.C,
   VES2.H, A.ASM) I gave them only OBJ's and my GAME.C code to play with.
   These text files mainly tell how to USE my engine, not how to write one.

BUILDINF.TXT: This text file has the most up-to-date function descriptions.
   You should look in here first before searching through the old stuff in
   BUILD.TXT and BUILD2.TXT.

BUILD.TXT: This is my original documentation that I sent along with the
   all my library updates to my Build engine. A lot of the information in
   here is redundant with BUILDINF.TXT, but I decided to include it anyway
   because the history section has a lot of interesting things in it that
   reveal how and why I designed things the way I did.

   PLEASE NOTE: The documentation at the top of BUILD.TXT is NOT up to date.
   Many of the function parameters are missing or out of order. Use
   BUILDINF.TXT (or my website :) for the latest function descriptions.

BUILD2.TXT: When BUILD.TXT didn't fit in the memory of my old text editor,
   I started this new file.

-------------------------------------------------------------------------------
-Ken S. (web page: http://www.advsys.net/ken)

repo_name: orochi/nblood

license: mit


code:
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman
// Ken Silverman's official web site: "http://www.advsys.net/ken"
// See the included license file "BUILDLIC.TXT" for license info.
// This file has been modified from Ken Silverman's original release

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <dos.h>

#pragma pack(push,1);

typedef struct
{
	char VESASignature[4];
	short VESAVersion;
	long OemStringPtr, Capabilities, VideoModePtr;
	short TotalMemory, OemSoftwareRev;
	long OemVendorNamePtr, OemProductNamePtr, OemProductRevPtr;
	char reserved[222], OemDATA[256];
} VBE_vgaInfo;

typedef struct
{
	short ModeAttributes;
	char WinAAtributes, WinBAttributes;
	short WinGranularity, WinSize, WinASegment, WinBSegment;
	long WinFuncPtr;
	short BytesPerScanLine, XResolution, YResolution;
	char XCharSize, YCharSize, NumberOfPlanes, BitsPerPixel;
	char NumberOfBanks, MemoryModel, BankSize, NumberOfImagePages;
	char res1;
	char RedMaskSize, RedFieldPosition;
	char GreenMaskSize, GreenFieldPosition;
	char BlueMaskSize, BlueFieldPosition;
	char RsvdMaskSize, RsvdFieldPosition, DirectColorModeInfo;
	long PhysBasePtr, OffScreenMemOffset;
	short OffScreenMemSize;
	char res2[206];
} VBE_modeInfo;

struct _RMWORDREGS { unsigned short ax, bx, cx, dx, si, di, cflag; };
struct _RMBYTEREGS { unsigned char al, ah, bl, bh, cl, ch, dl, dh; };
typedef union { struct _RMWORDREGS x; struct _RMBYTEREGS h; } RMREGS;
typedef struct { unsigned short es, cs, ss, ds; } RMSREGS;

typedef struct
{
	long edi, esi, ebp, reserved, ebx, edx, ecx, eax;
	short flags, es, ds, fs, gs, ip, cs, sp, ss;
} _RMREGS;

#pragma pack(pop);

long VESABuf_len = 1024, VESABuf_sel = 0, VESABuf_rseg;
short modelist[256];
static char *screen = NULL, vesachecked = 0;
long xres, yres, bytesperline, frameplace, imageSize, maxpages;
long buffermode, origbuffermode, linearmode;
long setactiveentry = 0, setvisualentry = 0, setpaletteentry = 0;
char permanentupdate = 0, vgacompatible;
short visualpagelookup[64][2];
long activepagelookup[64];
static long ves2lastx[MAXYDIM];
static long davesapageshift;
static VBE_vgaInfo vgaInfo;
long globlinplace;

#pragma aux qlimitrate =\
	"mov dx, 0x3da",\
	"wait1: in al, dx",\
	"test al, 1",\
	"jnz wait1",\
	modify exact [eax edx]\

short ods, oes, oss;
#pragma aux backupsegs =\
	"mov ods, ds",\
	"mov oes, es",\
	"mov oss, ss",\
	modify [eax]\

#pragma aux restoresegs =\
	"mov ds, ods",\
	"mov es, oes",\
	"mov ss, oss",\
	modify [eax]\

#pragma aux setvmode =\
	"int 0x10",\
	parm [eax]\

#pragma aux copybufbyte =\
	"cmp ecx, 4",\
	"jae longcopy",\
	"test cl, 1",\
	"jz preskip",\
	"movsb",\
	"preskip: shr ecx, 1",\
	"rep movsw",\
	"jmp endit",\
	"longcopy: test edi, 1",\
	"jz skip1",\
	"movsb",\
	"dec ecx",\
	"skip1: test edi, 2",\
	"jz skip2",\
	"movsw",\
	"sub ecx, 2",\
	"skip2: mov ebx, ecx",\
	"shr ecx, 2",\
	"rep movsd",\
	"test bl, 2",\
	"jz skip3",\
	"movsw",\
	"skip3: test bl, 1",\
	"jz endit",\
	"movsb",\
	"endit:",\
	parm [esi][edi][ecx]\
	modify [ebx]\

/*   //64-bit copybufbyte
#pragma aux copybufbyte =\
	"cmp ecx, 8",\
	"jae longcopy",\
	"test cl, 1",\
	"jz shortskip1",\
	"movsb",\
	"shortskip1: shr ecx, 2",\
	"jnc shortskip2",\
	"movsw",\
	"shortskip2: rep movsd",\
	"jmp endit",\
	"longcopy: test edi, 1",\
	"jz skip1",\
	"movsb",\
	"dec ecx",\
	"skip1: test edi, 2",\
	"jz skip2",\
	"movsw",\
	"sub ecx, 2",\
	"skip2: test edi, 4",\
	"jz skip3",\
	"movsd",\
	"sub ecx, 4",\
	"skip3: mov ebx, ecx",\
	"shr ecx, 3",\
	"jz skip4",\
	"begloop: fld qword ptr [esi]",\
	"fstp qword ptr [edi]",\
	"add esi, 8",\
	"add edi, 8",\
	"dec ecx",\
	"jnz begloop",\
	"skip4: test bl, 4",\
	"jz skip5",\
	"movsd",\
	"skip5: test bl, 2",\
	"jz skip6",\
	"movsw",\
	"skip6: test bl, 1",\
	"jz endit",\
	"movsb",\
	"endit:",\
	parm [esi][edi][ecx]\
	modify [ebx]\
*/

#pragma aux vesasetactive =\
	"call dword ptr [setactiveentry]",\
	parm [eax][ebx][ecx][edx]\

#pragma aux vesasetvisual =\
	"call dword ptr [setvisualentry]",\
	parm [eax][ebx][ecx][edx]\

#pragma aux vesasetpalette =\
	"call dword ptr [setpaletteentry]",\
	parm [eax][ebx][ecx][edx][esi][edi]\

long DPMI_int86(long intno, RMREGS *in, RMREGS *out)
{
	_RMREGS rmregs;
	union REGS r;
	struct SREGS sr;

	memset(&rmregs,0,sizeof(rmregs));
	rmregs.eax = in->x.ax; rmregs.ebx = in->x.bx;
	rmregs.ecx = in->x.cx; rmregs.edx = in->x.dx;
	rmregs.esi = in->x.si; rmregs.edi = in->x.di;

	segread(&sr);
	r.w.ax = 0x300; r.h.bl = intno; r.h.bh = 0; r.w.cx = 0; sr.es = sr.ds;
	r.x.edi = (unsigned)&rmregs;
	backupsegs(); int386x(0x31,&r,&r,&sr); restoresegs();

	out->x.ax = rmregs.eax; out->x.bx = rmregs.ebx;
	out->x.cx = rmregs.ecx; out->x.dx = rmregs.edx;
	out->x.si = rmregs.esi; out->x.di = rmregs.edi;
	out->x.cflag = rmregs.flags&1;
	return(out->x.ax);
}

long DPMI_int86x(long intno, RMREGS *in, RMREGS *out, RMSREGS *sregs)
{
	_RMREGS rmregs;
	union REGS r;
	struct SREGS sr;

	memset(&rmregs, 0, sizeof(rmregs));
	rmregs.eax = in->x.ax; rmregs.ebx = in->x.bx;
	rmregs.ecx = in->x.cx; rmregs.edx = in->x.dx;
	rmregs.esi = in->x.si; rmregs.edi = in->x.di;
	rmregs.es = sregs->es;
	rmregs.ds = sregs->ds;

	segread(&sr);
	r.w.ax = 0x300; r.h.bl = intno; r.h.bh = 0; r.w.cx = 0; sr.es = sr.ds;
	r.x.edi = (unsigned)&rmregs;
	backupsegs(); int386x(0x31,&r,&r,&sr); restoresegs();

	out->x.ax = rmregs.eax; out->x.bx = rmregs.ebx;
	out->x.cx = rmregs.ecx; out->x.dx = rmregs.edx;
	out->x.si = rmregs.esi; out->x.di = rmregs.edi;
	sregs->es = rmregs.es; sregs->cs = rmregs.cs;
	sregs->ss = rmregs.ss; sregs->ds = rmregs.ds;
	out->x.cflag = rmregs.flags&1;
	return(out->x.ax);
}

static void ExitVBEBuf(void)
{
	union REGS r;
	r.w.ax = 0x101; r.w.dx = VESABuf_sel; //DPMI free real seg
	backupsegs(); int386(0x31,&r,&r); restoresegs();
}

void VBE_callESDI(RMREGS *regs, void *buffer, long size)
{
	RMSREGS sregs;
	union REGS r;

	if (!VESABuf_sel)  //Init Real mode buffer
	{
		r.w.ax = 0x100; r.w.bx = (VESABuf_len+15)>>4;
		backupsegs(); int386(0x31,&r,&r); restoresegs();
		if (r.w.cflag) { printf("DPMI_allocRealSeg failed!\n"); exit(0); }
		VESABuf_sel = r.w.dx;
		VESABuf_rseg = r.w.ax;
		atexit(ExitVBEBuf);
	}
	sregs.es = VESABuf_rseg;
	regs->x.di = 0;
	_fmemcpy(MK_FP(VESABuf_sel,0),buffer,size);
	DPMI_int86x(0x10,regs,regs,&sregs);
	_fmemcpy(buffer,MK_FP(VESABuf_sel,0),size);
}

long VBE_getModeInfo(long mode, VBE_modeInfo *modeInfo)
{
	RMREGS regs;

	regs.x.ax = 0x4f01;
	regs.x.cx = mode;
	VBE_callESDI(&regs, modeInfo, sizeof(VBE_modeInfo));
	if (regs.x.ax != 0x004f) return(0);
	if ((modeInfo->ModeAttributes&1) == 0) return(0); //1 is vbeMdAvailable
	return(1);
}

GetPtrToLFB(long physAddr)
{
	#define LIMIT (4096*1024)-1
	long sel;
	union REGS r;

	r.w.ax = 0; r.w.cx = 1;
	backupsegs(); int386(0x31,&r,&r); restoresegs();
	if (r.x.cflag) { printf("DPMI_allocSelector() failed!\n"); exit(0); }
	sel = r.w.ax;
	r.w.ax = 9; r.w.bx = sel; r.w.cx = 0x8092;
	backupsegs(); int386(0x31,&r,&r); restoresegs();

	r.w.ax = 0x800; r.w.bx = physAddr >> 16; r.w.cx = physAddr & 0xffff;
	r.w.si = LIMIT>>16; r.w.di = LIMIT&0xffff;
	backupsegs(); int386(0x31,&r,&r); restoresegs();
	if (r.x.cflag) { printf("DPMI_mapPhysicalToLinear() failed!\n"); exit(0); }
	globlinplace = ((long)r.w.bx<<16)+r.w.cx;

	r.w.ax = 7; r.w.bx = sel;
	r.w.cx = globlinplace>>16; r.w.dx = globlinplace&0xffff;
	backupsegs(); int386(0x31,&r,&r); restoresegs();
	if (r.x.cflag) { printf("DPMI_setSelectorBase() failed!\n"); exit(0); }

	r.w.ax = 8; r.w.bx = sel;
	r.w.cx = LIMIT>>16; r.w.dx = LIMIT&0xffff;
	backupsegs(); int386(0x31,&r,&r); restoresegs();
	if (r.x.cflag) { printf("DPMI_setSelectorLimit() failed!\n"); exit(0); }
}

getvalidvesamodes()
{
	long i, j, k;
	short *p, *p2;
	VBE_modeInfo modeInfo;
	RMREGS regs;

	if (vesachecked) return;
	vesachecked = 1;

	validmodecnt = 0;
	modelist[0] = -1;

	strncpy(vgaInfo.VESASignature,"VBE2",4);
	regs.x.ax = 0x4f00;
	VBE_callESDI(&regs,&vgaInfo,sizeof(VBE_vgaInfo));
	if ((regs.x.ax != 0x004f) || (strncmp(vgaInfo.VESASignature,"VESA",4)))
		return;

	//if (vgaInfo.VESAVersion < 0x200) return;

		//LfbMapRealPointer
	p = (short *)(((vgaInfo.VideoModePtr&0xffff0000)>>12)+((vgaInfo.VideoModePtr)&0xffff));
	p2 = modelist;
	while (*p != -1) *p2++ = *p++;
	*p2 = -1;

	for(p=modelist;*p!=-1;p++)
	{
		regs.x.ax = 0x4f01; regs.x.cx = *p;
		VBE_callESDI(&regs,&modeInfo,sizeof(VBE_modeInfo));
		if (regs.x.ax != 0x004f) continue;
		if (!(modeInfo.ModeAttributes&1)) continue; //1 is vbeMdAvailable
		if (modeInfo.MemoryModel != 4) continue;    //4 is vbeMemPK
		if (modeInfo.BitsPerPixel != 8) continue;
		if (modeInfo.NumberOfPlanes != 1) continue;

		validmode[validmodecnt] = *p;
		validmodexdim[validmodecnt] = modeInfo.XResolution;
		validmodeydim[validmodecnt] = modeInfo.YResolution;
		validmodecnt++;
	}

	for(i=1;i<validmodecnt;i++)
		for(j=0;j<i;j++)
			if (validmodeydim[i] < validmodeydim[j])
			{
				k = validmode[i]; validmode[i] = validmode[j]; validmode[j] = k;
				k = validmodexdim[i]; validmodexdim[i] = validmodexdim[j]; validmodexdim[j] = k;
				k = validmodeydim[i]; validmodeydim[i] = validmodeydim[j]; validmodeydim[j] = k;
			}

	for(i=1;i<validmodecnt;i++)
		for(j=0;j<i;j++)
			if (validmodexdim[i] < validmodexdim[j])
			{
				k = validmode[i]; validmode[i] = validmode[j]; validmode[j] = k;
				k = validmodexdim[i]; validmodexdim[i] = validmodexdim[j]; validmodexdim[j] = k;
				k = validmodeydim[i]; validmodeydim[i] = validmodeydim[j]; validmodeydim[j] = k;
			}
}

setvesa(long x, long y)
{
	div_t dived;
	long i, j, k;
	short *p, *p1, *p2;
	VBE_modeInfo modeInfo;
	RMREGS regs;
	RMSREGS sregs;

	getvalidvesamodes();

	xres = x; yres = y;
	for(k=0;k<validmodecnt;k++)
	{
		regs.x.ax = 0x4f01; regs.x.cx = validmode[k];
		VBE_callESDI(&regs,&modeInfo,sizeof(VBE_modeInfo));
		if (regs.x.ax != 0x004f) continue;
		if (!(modeInfo.ModeAttributes&1)) continue; //1 is vbeMdAvailable

		if (modeInfo.MemoryModel != 4) continue;    //4 is vbeMemPK
		if (modeInfo.BitsPerPixel != 8) continue;
		if (modeInfo.NumberOfPlanes != 1) continue;
		if (modeInfo.XResolution != x) continue;
		if (modeInfo.YResolution != y) continue;

		bytesperline = modeInfo.BytesPerScanLine;
		maxpages = min(modeInfo.NumberOfImagePages+1,64);

		regs.x.ax = 0x4f02;
		regs.x.bx = validmode[k] | ((modeInfo.ModeAttributes&128)<<7);
		DPMI_int86(0x10,&regs,&regs);

		if (modeInfo.ModeAttributes&32) vgacompatible = 0;
											else vgacompatible = 1;

		regs.x.ax = 0x4f0a; regs.x.bx = 0;
		DPMI_int86x(0x10,&regs,&regs,&sregs);
		if (regs.x.ax == 0x004f)   //cx is length of protected mode code
		{
			i = (((long)sregs.es)<<4)+((long)regs.x.di);
			p1 = (short *)i;
			setactiveentry = ((long)p1[0]) + i;
			setvisualentry = ((long)p1[1]) + i;
			setpaletteentry = ((long)p1[2]) + i;
				//p1[2] is useless palette function - see vesprot.asm for code
		}

			//Linear mode
		if (modeInfo.ModeAttributes&128) //128 is vbeMdLinear
		{
			GetPtrToLFB(modeInfo.PhysBasePtr);

			linearmode = 1;
			buffermode = (maxpages<=1);
			imageSize = bytesperline*yres;
			frameplace = globlinplace;
			j = 0;
			for(i=0;i<maxpages;i++)
			{
				activepagelookup[i] = globlinplace+j;
				j += imageSize;
			}
		}
		else  //Banked mode
		{
				//Get granularity
			switch(modeInfo.WinGranularity)
			{
				case 64: davesapageshift = 0; break;
				case 32: davesapageshift = 1; break;
				case 16: davesapageshift = 2; break;
				case 8: davesapageshift = 3; break;
				case 4: davesapageshift = 4; break;
				case 2: davesapageshift = 5; break;
				case 1: davesapageshift = 6; break;
			}

			linearmode = 0;
			if ((x == 320) && (y == 200) && (maxpages >= 2))
			{
				buffermode = 0;
				imageSize = 65536;
				frameplace = 0xa0000;
			}
			else
			{
				buffermode = 1;
				imageSize = bytesperline*yres;
				frameplace = FP_OFF(screen);
				maxpages = 1;
			}
		}

		origbuffermode = buffermode;

		j = 0;
		for(i=0;i<maxpages;i++)
		{
			dived = div(j,bytesperline);
			visualpagelookup[i][0] = (short)dived.rem;
			visualpagelookup[i][1] = (short)dived.quot;
			j += imageSize;
		}
		return(0);
	}
	return(-1);
}

setdacbits(long newdacbits)
{
	RMREGS regs;

	if ((vgaInfo.Capabilities&1) == 0) return(6L);
	regs.x.ax = 0x4f08;
	regs.x.bx = (((long)newdacbits)<<8);
	DPMI_int86(0x10,&regs,&regs);
	return((long)regs.h.bh);
}

#define setvesapage(i)                                      \
{                                                           \
	if (setactiveentry)                                      \
		vesasetactive(0x4f05,0L,0L,i);                        \
	else                                                     \
	{                                                        \
		regs.x.ax = 0x4f05; regs.x.bx = 0; regs.x.dx = i;     \
		DPMI_int86(0x10,&regs,&regs);                         \
	}                                                        \
}

void setactivepage(long dapagenum)
{
	RMREGS regs;

	if ((origbuffermode == 0) && (linearmode == 0))
	{
		frameplace = 0xa0000;
		setvesapage(dapagenum<<davesapageshift);
	}
	if (buffermode != 0) { frameplace = FP_OFF(screen); return; }
	if (linearmode != 0) { frameplace = activepagelookup[dapagenum]; return; }
}

static long curpag = 0;
void setvisualpage(long dapagenum)
{
	RMREGS regs;
	long i, j, p, dx, cx1, cy1, cx2, cy2, delta, x, y, y1, y2, ny1, ny2;

	if (buffermode != 0)
	{
		cx1 = windowx1; cy1 = windowy1; cx2 = windowx2; cy2 = windowy2;
		if (permanentupdate) { cx1 = 0; cy1 = 0; cx2 = xdim-1; cy2 = ydim-1; }
		dx = cx2-cx1+1;
		if (linearmode)
		{
			p = FP_OFF(screen);
			delta = activepagelookup[dapagenum&0x7fffffff]-FP_OFF(screen);
			if (permanentupdate == 0)
			{
				y1 = startumost[cx1]; y2 = y1;
				for(x=cx1;x<=cx2;x++)
				{
					ny1 = startumost[x]-1; ny2 = startdmost[x];
					if (ny1 < ny2-1)
					{
						if (ny1 >= y2)
						{
							while (y1 < y2-1)
							{
								y1++; if ((y1&31) == 0) faketimerhandler();
									//x,y1
								i = p+ylookup[y1]+ves2lastx[y1];
								copybufbyte(i,i+delta,x-ves2lastx[y1]);
							}
							y1 = ny1;
						}
						else
						{
							while (y1 < ny1)
							{
								y1++; if ((y1&31) == 0) faketimerhandler();
									//x-1,y1
								i = p+ylookup[y1]+ves2lastx[y1];
								copybufbyte(i,i+delta,x-ves2lastx[y1]);
							}
							while (y1 > ny1) ves2lastx[y1--] = x;
						}
						while (y2 > ny2)
						{
							y2--; if ((y2&31) == 0) faketimerhandler();
								//x-1,y2
							i = p+ylookup[y2]+ves2lastx[y2];
							copybufbyte(i,i+delta,x-ves2lastx[y2]);
						}
						while (y2 < ny2) ves2lastx[y2++] = x;
					}
					else
					{
						while (y1 < y2-1)
						{
							y1++; if ((y1&31) == 0) faketimerhandler();
								//x-1,y1
							i = p+ylookup[y1]+ves2lastx[y1];
							copybufbyte(i,i+delta,x-ves2lastx[y1]);
						}
						if (x == cx2) break;
						y1 = startumost[x+1]; y2 = y1;
					}
				}
				while (y1 < y2-1)
				{
					y1++; if ((y1&31) == 0) faketimerhandler();
						//cx2+1,y1
					i = p+ylookup[y1]+ves2lastx[y1];
					copybufbyte(i,i+delta,cx2+1-ves2lastx[y1]);
				}
			}
			else
			{
				p += ylookup[cy1]+cx1;
				delta = activepagelookup[dapagenum&0x7fffffff]-FP_OFF(screen);
				for(y=cy1;y<=cy2;y++)
				{
					copybufbyte(p,p+delta,dx);
					p += ylookup[1];
					if ((y&31) == 0) faketimerhandler();
				}
			}
		}
		else
		{
			p = ylookup[cy1]+cx1;
			for(y=cy1;y<=cy2;y++)
			{
				if ((p>>16) != curpag)
				{
					curpag = (p>>16);

					setvesapage(curpag<<davesapageshift);
					faketimerhandler();
				}

				i = (p&65535)+dx-65536;
				if (i <= 0)
					copybufbyte(p+FP_OFF(screen),(p&65535)+0xa0000,dx);
				else
				{
					copybufbyte(p+FP_OFF(screen),0xb0000-(dx-i),dx-i);

					curpag = ((p+dx-1)>>16);
					setvesapage(curpag<<davesapageshift);
					faketimerhandler();

					copybufbyte(p+(dx-i)+FP_OFF(screen),0xa0000,i);
				}
				p += ylookup[1];
			}
		}
		permanentupdate = 0;
	}
	if (origbuffermode == 0)
	{
		if (setvisualentry)
		{
			i = imageSize*(dapagenum&0x7fffffff);
			if (vgacompatible)
			{
				if (dapagenum >= 0) qlimitrate();
				vesasetvisual(0x4f07,0L,i>>2,i>>18);
			}
			else
				{ vesasetvisual(0x4f07,0x80,i>>2,i>>18); }

		}
		else
		{
			regs.x.ax = 0x4f07;
			regs.x.cx = visualpagelookup[dapagenum&0x7fffffff][0]; //X-coordinate
			regs.x.dx = visualpagelookup[dapagenum&0x7fffffff][1]; //Y-coordinate
			if (vgacompatible)
			{
				regs.x.bx = 0;
				if (dapagenum >= 0) qlimitrate();
				DPMI_int86(0x10,&regs,&regs);
			}
			else
				{ regs.x.bx = 0x80; DPMI_int86(0x10,&regs,&regs); }
		}
		if (dapagenum >= 0) faketimerhandler();
	}
}

uninitvesa()
{
	VESABuf_len = 1024;
	VESABuf_sel = 0;
	vesachecked = 0;
}

#pragma aux setpalettequick =\
	"mov edx, 0x3c8",\
	"out dx, al",\
	"inc edx",\
	"lea ecx, [ecx+ecx*2]",\
	"cld",\
	"rep outsb",\
	parm [eax][ecx][esi]\
	modify exact [ecx edx esi]\

VBE_setPalette(long start, long num, char *dapal)
{
	RMREGS regs;
	long i, j, k;
	char palquick[768];

	if (stereomode == 1)
	{
		if ((unsigned)((blackband&255)-start) < (unsigned)num)
		{
			dapal[(((blackband&255)-start)<<2)+0] = 0;
			dapal[(((blackband&255)-start)<<2)+1] = 0;
			dapal[(((blackband&255)-start)<<2)+2] = 0;
		}
		if ((unsigned)((whiteband&255)-start) < (unsigned)num)
		{
			dapal[(((whiteband&255)-start)<<2)+0] = 255;
			dapal[(((whiteband&255)-start)<<2)+1] = 255;
			dapal[(((whiteband&255)-start)<<2)+2] = 255;
		}
	}
	if ((vgacompatible) || (vgaInfo.VESAVersion < 0x200) || (vidoption != 1))
	{
		j = 0; k = (start<<2);
		for(i=0;i<num;i++)
		{
			palquick[j] = dapal[k+2];
			palquick[j+1] = dapal[k+1];
			palquick[j+2] = dapal[k];
			j += 3; k += 4;
		}
		//setpalettequick(start,num,palquick);
		koutp(0x3c8,start);
		for(i=(num>>1);i>0;i--)
		{
			koutp(0x3c9,dapal[2]);
			while (kinp(0x3da)&1); while (!(kinp(0x3da)&1));
										  koutp(0x3c9,dapal[1]); koutp(0x3c9,dapal[0]);
			koutp(0x3c9,dapal[6]); koutp(0x3c9,dapal[5]); koutp(0x3c9,dapal[4]);
			dapal += 8;
		}
		if (num&1)
		{
			koutp(0x3c9,dapal[2]);
			while (kinp(0x3da)&1); while (!(kinp(0x3da)&1));
										  koutp(0x3c9,dapal[1]); koutp(0x3c9,dapal[0]);
		}
		return(1);
	}

	if (setpaletteentry)
	{
		i = (vesasetpalette(0x4f09,(vgaInfo.Capabilities&4)<<5,
								  num,start,0L,dapal)&65535);
	}
	else
	{
		regs.x.ax = 0x4f09; regs.h.bl = ((vgaInfo.Capabilities&4)<<5);
		regs.x.cx = num; regs.x.dx = start;
		VBE_callESDI(&regs,dapal,sizeof(dapal)*num);
		i = regs.x.ax;
	}
	if (i != 0x004f) return(0);
	return(1);
}

VBE_getPalette(long start, long num, char *dapal)
{
	RMREGS regs;
	long i;

	if ((vgacompatible) || (vgaInfo.VESAVersion < 0x200) || (vidoption != 1))
	{
		koutp(0x3c7,start);
		for(i=num;i>0;i--)
		{
			dapal[2] = kinp(0x3c9);
			dapal[1] = kinp(0x3c9);
			dapal[0] = kinp(0x3c9);
			dapal += 4;
		}
		return(1);
	}

	regs.x.ax = 0x4f09; regs.h.bl = 1;
	regs.x.cx = num; regs.x.dx = start;
	VBE_callESDI(&regs,dapal,sizeof(dapal)*num);
	i = regs.x.ax;
	if (i != 0x004f) return(0);
	return(1);
}