1. New Niel2.e

I've just downloaded and tried niel2.e

Below is a couple is a few line routines that can be easily modified to
run with niel2.e or any other graphics lib by changing the call to EU's
pixel() with the pixel routine fron the desired library ie; niel2.e.

I also found a problem with the machine code to map the linear frame
buffer that was also in the origional niel.e.
(Unless it was deliberatly coded that way for EU compatablity reasons).

First here are the line routines:

-- Bressenham algorithm with no restrictions on input variables.
-- You need to supply your own abs() function.
global procedure Line(atom Color, sequence xy1, sequence xy2)
    atom d, ax, ay, sx, sy, dx, dy
    atom x1, x2, y1, y2

    x1 = xy1[1] y1 = xy1[2] x2 = xy2[1] y2 = xy2[2]
    dx = x2 - x1 ax = abs(dx) * 2 if dx < 0 then sx = -1 else sx = 1 end if
    dy = y2 - y1 ay = abs(dy) * 2 if dy < 0 then sy = -1 else sy = 1 end if

    pixel(Color, {x1, y1})

    if ax > ay then
        d = ay - (ax * 2)
        while x1 != x2 do
            if d >= 0 then y1 += sy d -= ax end if
            x1 += sx
            d += ay
            pixel(Color, {x1, y1})
        end while

    else
        d = ax - (ay * 2)
        while y1 != y2 do
            if d >= 0 then x1 += sx d -= ay end if
            y1 += sy
            d += ax
            pixel(Color, {x1, y1})
        end while
    end if

end procedure

global procedure Cubic_Bezier_Curve(atom Color,
                    sequence xy1, sequence xy2, sequence xy3, sequence xy4)

    atom x1, y1, x2, y2, x3, y3, x4, y4
    atom tx1, tx2, tx3, ty1, ty2, ty3, mu1, mu2, mu3, muDelta
    integer xStart, yStart, xEnd, yEnd

        x1 = xy1[1] y1 = xy1[2]
        x2 = xy2[1] y2 = xy2[2]
        x3 = xy3[1] y3 = xy3[2]
        x4 = xy4[1] y4 = xy4[2]

        tx1 = -x1 + 3 * x2 - 3 * x3 + x4    ty1 = -y1 + 3 * y2 - 3 * y3 + y4
        tx2 = 3 * x1 - 6 * x2 + 3 * x3      ty2 = 3 * y1 - 6 * y2 + 3 * y3
        tx3 = -3 * x1 + 3 * x2              ty3 = -3 * y1 + 3 * y2

        xStart = 1 yStart = 1
        muDelta = 1 / 128 mu1 = muDelta

        for n = 1 to 128 do
            mu2 = mu1 * mu1 mu3 = mu2 * mu1
            xEnd = floor(mu3 * tx1 + mu2 * tx2 + mu1 * tx3 + x1)
            yEnd = floor(mu3 * ty1 + mu2 * ty2 + mu1 * ty3 + y1)
            Line(Color, {xStart, yStart}, {xEnd, yEnd})
            mu1 += muDelta
            xStart = xEnd
            yStart = yEnd
        end for

end procedure


Mapping the linear frame buffer.

Niel2.e neglects to check that the linear frame buffer has been set up
correctly ie; When linear mode is available but the code to map the
linear frame buffer fails, for whatever reason, niel2.e should resort
to bank switching for the mode.

I found the machine code in niel2.e to map the linear frame buffer is
missing some steps needed to map the buffer correctly.

n.b. Many linear modes on various video cards I have done testing on
don't get mapped correctly wich makes screen output invalid.
(data is output to an invalid address rather than the screen address.)

after the call to int 31h func 800h (dpmi physical address mapping).
there should be;
	* Allocate LTD descriptor.	int 31h func 000h
	* Set segmant base address.	int 31h func 007h
	* Set segment limit. 		int 31h func 008h ((maxx*maxy*bytepp)-1)

	Also the size specified in si:di for int 31h 800h should be
	'maxx*maxy*bytepp' not 4194304d.

To unmap the linear buffer Niel2.e should
	* Get segment base address.	int 31h func 006h
	* Unmap physical memroy.	int 31h func 801h
	* Free LTD descriptor.		int 31h func 001h

Below is an attempt to create an include file to map the linear buffer.
Content is untested but it may be used as a template to map the linear
frame buffer for future versions of Niel2.e.

include bits.e
include mixedlib.e

constant
	--
	lpALLOCLTDDESC=define_asm_func(
	ENTER_PROC(0)&{
	#66,#8B,#4D,#08,        -- mov cx, word ptr [ebp+8]
	#31,#C0,                -- xor eax, eax
	#CD,#31,                -- int #31
	#73,#02,                -- jnc @F
	#31,#C0                 -- xor eax, eax
	-- @@:
	}&LEAVE_PROC(0),
	{WORD}, WORD, 4)

constant
	--
	lpFREELTDDESC=define_asm_proc(
	ENTER_PROC(0)&{
	#66,#8B,#5D,#08,        -- mov bx, word ptr [ebp+8]
	#B8,#01,#00,#00,#00,    -- mov eax, 0001
	#CD,#31                 -- int #31
	}&LEAVE_PROC(0),
	{WORD}, 4)

constant
	--
	lpSETSEGBASEADDR=define_asm_proc(
	ENTER_PROC(0)&{
	#66,#8B,#5D,#08,        -- mov bx word ptr [ebp+8]
	#66,#8B,#55,#0C,        -- mov dx word ptr [ebp+12]
	#8B,#4D,#0C,            -- mov ecx [ebp+12]
	#C1,#E9,#10,            -- shr ecx, 16
	#B8,#07,#00,#00,#00,    -- mov eax, #0007
	#CD,#31                 -- int #31
	}&LEAVE_PROC(0),
	{WORD, DWORD}, 4)

constant
	--
	lpGETSEGBASEADDR=define_asm_func(
	ENTER_PROC(0)&{
	#66,#8B,#5D,#08,        -- mov bx word ptr [ebp+8]
	#B8,#06,#00,#00,#00,    -- mov eax, #0006
	#CD,#31,                -- int #31
	#73,#04,                -- jnc @F
	#31,#C0,                -- xor eax, eax
	#EB,#08,                -- jmp leave
    	-- @@:
    	#C1,#E1,#10,            -- shl ecx, 16
    	#66,#89,#D1,            -- mov cx, dx
    	#89,#C8                 -- mov eax, ecx
    	-- leave:
	}&LEAVE_PROC(0),
	{WORD}, DWORD, 4)

constant
	--
	lpSETSEGLIMIT=define_asm_proc(
	ENTER_PROC(0)&{
	#66,#8B,#5D,#08,        -- mov bx word ptr [ebp+8]
	#66,#8B,#55,#0C,        -- mov dx word ptr [ebp+12]
	#8B,#4D,#0C,            -- mov ecx [ebp+12]
	#C1,#E9,#10,            -- shr ecx, 16
	#B8,#08,#00,#00,#00,    -- mov eax, #0008
	#CD,#31                 -- int #31
	}&LEAVE_PROC(0),
	{WORD, DWORD}, 4)

constant
	--
	SETDESCACCESS=define_asm_proc(
	ENTER_PROC(0)&{
	#66,#8B,#5D,#08,        -- mov bx word ptr [ebp+8]
	#8A,#6D,#0C,            -- mov ch byte ptr [ebp+12]
	#8A,#4D,#10,            -- mov cl byte ptr [ebp+16]
	#B8,#09,#00,#00,#00,    -- mov eax, #0009
	#CD,#31                 -- int #31
	}&LEAVE_PROC(0),
	{WORD, BYTE, BYTE}, 4)

constant
	--
	lpMAPPHYSMEMORY=define_asm_func(
	ENTER_PROC(0)&{
	#8B,#5D,#08,            -- mov ebx, [ebp+8]
	#8B,#75,#10,            -- mov esi, [ebp+16]
	#66,#8B,#4D,#08,        -- mov cx, word ptr [ebp+8]
	#66,#8B,#7D,#10,        -- mov di, word ptr [ebp+16]
	#C1,#EB,#10,            -- shr ebx, 16
	#C1,#EE,#10,            -- shr esi, 16
	#B8,#00,#08,#00,#00,    -- mov eax #0800
 	#CD,#31,                -- int #31
	#73,#04,                -- jnc @F
	#31,#C0,                -- xor eax, eax
	#EB,#08,                -- jmp leave
	-- @@:
	#C1,#E3,#10,            -- shl ebx, 16
	#66,#89,#CB,            -- mov bx, cx
	#89,#D8                 -- mov eax, ebx
	-- leave:
	}&LEAVE_PROC(0),
	{DWORD, DWORD}, WORD, 4)

constant
	--
	lpFREEPHYSMEMORY=define_asm_proc(
	ENTER_PROC(0)&{
	#8B,#5D,#08,            -- mov ebx, [ebp+8]
	#66,#8B,#4D,#08,        -- mov cx, word ptr [ebp+8]
	#C1,#EB,#10,            -- shr ebx, 16
	#B8,#01,#08,#00,#00,    -- mov eax #0801
	#CD,#31                 -- int #31
	}&LEAVE_PROC(0),
	{WORD}, 4)

global	
function
	--
	Map_Linear_Framebuffer(dword phys, word maxx, word maxy, byte bytepp)
	dword size word desc
	
	desc=-1
	size=maxx*maxy*bytepp
	phys=c_func(lpMAPPHYSMEMORY, {phys, size})
	if phys then
		desc=c_func(lpALLOCLTDDESC,{1})
		if desc then
-- ToDo: Theese should be functions, If SETSEGBASEADDR or SETSEGLIMIT fails then
we should
-- free the useless descriptor and unmap the physical address and resort to bank
switching.
			c_proc(lpSETSEGBASEADDR, {desc, phys})
			c_proc(lpSETSEGLIMIT,  {desc, size-1})
			else c_proc(lpFREEPHYSMEMORY,  {phys})
		end if
	end if
	
	return desc	-- the selector to linear buffer.
	
end function

global
procedure
	--
	Unmap_Linear_Framebuffer(word sel)
	atom addr
	
	addr=c_func(lpGETSEGBASEADDR, {sel})
	c_proc(lpFREEPHYSMEMORY, {addr})
	c_proc(lpFREELTDDESC,     {sel})
	
end procedure


new topic     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu