Code:
//==============================================================================
// GPU Driver
// (C) 2009 Black Phoenix
//
//Driver requirement:
// FS must be set to GPU_PTR, so it can write to GPU
//
//All GPU functions preserve all registers except ones they take as parameters
//Draw functions return GPU data address in parameter register
//
//FIXME: refresh-on-demand support (see _GPU.Command.DrawOnce)
//==============================================================================
define GPU_DRIVER_VERSION,200;
//-- GPU registers -------------------------------------------------------------
define GPU.Height, 65514;
define GPU.Width, 65515;
define GPU.RAMReset, 65530;
define GPU.Halt, 65531;
define GPU.HWClear, 65533;
define GPU.Reset, 65534;
define GPU.State, 65535;
//-- GPU command set -----------------------------------------------------------
_GPU.Command.DrawOnce: db 15,25,-9996661,1,7,0,9,201,0,14,25,-9996661,0,-9996660;
_GPU.Command.Begin: db 14,25,65515,-9996661,14,25,65514,-9996662,-9996660;
_GPU.Command.End: db 201,0,-9996660;
_GPU.Command.Clear: db 214,0,-9996661,-9996660;
_GPU.Command.SetColor: db 215,0,-9996661,-9996660;
_GPU.Command.DrawRect: db 228,0,-9996661,-9996662,-9996660;
_GPU.Command.DrawOutl: db 234,0,-9996661,-9996662,-9996660;
_GPU.Command.DrawCirc: db 226,250000,-9996661,-9996662,-9996660;
_GPU.Command.DrawLine: db 227,0,-9996661,-9996662,-9996660;
_GPU.Command.DrawText: db 246,0,-9996661,-9996662,-9996660;
_GPU.Command.SetFont: db 217,25,-9996661,-9996660;
_GPU.Command.SetSize: db 218,25,-9996661,-9996660;
_GPU.Command.SetShade: db 276,25,-9996661,-9996660;
_GPU.Command.SetFlash: db 98,1,59,1,1,34,1,276,1,-9996660;
_GPU.Command.SetAlign: db 14,25,65473,1,-9996660;//250025 -9996661 FIXME: doesnt work
_GPU.Command.SetWidth: db 277,25,-9996661,-9996660;
_GPU.Command.SetOffset:db 219,25,-9996661,-9996660;
_GPU.Command.RotScale: db 233,250025,-9996661,-9996662,-9996660;
_GPU.PleaseWaitProgram: //30 bytes
db 215,0,9,240,0,13,15,201,0,255,255,255,255,397,497,80,108,101,97,115,101;
db 32,119,97,105,116,46,46,46,0;
//-- Internal params -----------------------------------------------------------
alloc Screen.Width;
alloc Screen.Height;
alloc Screen.BasePtr;
alloc Screen.ResourcePtr;
alloc Screen.DataPtr;
alloc Screen.Drawing;
alloc Screen.NeedRefreshPtr;
alloc Screen.ControlBits; //Control bit set
//BIT 0: Draw screen only once
//BIT 1: Don't set screen resolution
//GPU.Init() - Initialize GPU driver
GPU.Init:
mov FS:#GPU.RAMReset,1; //Reset RAM entirely
lea ESI,CS:#_GPU.PleaseWaitProgram;
mov EDI,FS;
mcopy 30; //30 bytes "please wait" program
mov FS:#GPU.HWClear,1; //Enable hardware clear
mov FS:#GPU.Halt,0; //Halt GPU
mov FS:#0,FS:#0; //Flush cache
mov FS:#GPU.State,1;
mov CS:#Screen.BasePtr,0;
mov CS:#Screen.ResourcePtr,32768;
mov CS:#Screen.DataPtr,63488;
mov CS:#Screen.Height,512;
mov CS:#Screen.Width,776;
mov CS:#Screen.Drawing,0;
mov CS:#Screen.ControlBits,0;
ret
//GPU.SetVideoMode(width,height) - Set GPU screen size and videomode
GPU.SetVideoMode:
mov CS:#Screen.Width,EAX;
mov CS:#Screen.Height,EBX;
ret
//GPU.Begin() - Begin GPU rendering
GPU.Begin:
mov FS:#GPU.Halt,1;
mov CS:#Screen.BasePtr,0;
mov CS:#Screen.ResourcePtr,32768;
mov CS:#Screen.DataPtr,63488;
mov CS:#Screen.Drawing,1;
push ESI; push EAX; push EBX; push ECX;
bit CS:#Screen.ControlBits,0;
jz @GPU.NoDrawOnce;
//Create draw flag
mov CS:#Screen.NeedRefreshPtr,CS:#Screen.ResourcePtr;
inc CS:#Screen.ResourcePtr;
call GPU.NeedRefresh;
//Image not refreshed unless requested by driver
mov EAX,CS:#Screen.NeedRefreshPtr;
mov ESI,_GPU.Command.DrawOnce;
call GPU.Command.Internal;
//No hardware clear
mov FS:#GPU.HWClear,0;
@GPU.NoDrawOnce:
bit CS:#Screen.ControlBits,1;
jz @GPU.DontSetRes;
mov EAX,CS:#Screen.Width;
mov EBX,CS:#Screen.Height;
mov ESI,_GPU.Command.Begin;
call GPU.Command.Internal;
@GPU.DontSetRes:
pop ECX; pop EBX; pop EAX; pop ESI;
ret
//GPU.End() - End GPU rendering and flush to screen
GPU.End:
push ESI;
mov ESI,_GPU.Command.End;
call GPU.Command.Internal;
pop ESI;
mov FS:#GPU.Halt,0;
mov FS:#0,FS:#0; //Flush
mov CS:#Screen.Drawing,0;
ret
//Internal - force GPU refresh
GPU.NeedRefresh:
push ESI;
mov ESI,CS:#Screen.NeedRefreshPtr;
mov FS:#ESI,1; //Need refresh
mov FS:#0,FS:#0;
pop ESI;
ret
//Internal - checks if GPU is ready. Else triggers int 28
GPU.CheckReady:
cmp CS:#Screen.Drawing,0;
jne @GPUReady;
int 28;
@GPUReady:
ret
//Render_SetResource(gpuptr,ptr,count)
GPU.SetResource:
push EDI;
mov EDI,EAX;
@setloop:
mov FS:#EDI,#EBX;
inc EDI; inc EBX;
loop @setloop;
mov FS:#0,FS:#0; //Flush update
call GPU.NeedRefresh;
pop EDI;
ret
//Render_CreateResource(ptr,count)
GPU.CreateResouce:
push ECX;
mov ECX,EBX;
call GPU.CreateResource.EAX;
pop ECX;
ret
//Internal - Create resource pointed by EAX (ECX - size)
GPU.CreateResource.EAX:
push ESI; push ECX; mov ESI,CS:#Screen.ResourcePtr;
@createres.eax:
mov FS:#ESI,#EAX;
inc EAX; inc ESI;
loop @createres.eax;
pop ECX;
mov EAX,CS:#Screen.ResourcePtr;
add CS:#Screen.ResourcePtr,ECX;
pop ESI;
ret
//Internal - Create resource pointed by EBX (ECX - size)
GPU.CreateResource.EBX:
push ESI; push ECX; mov ESI,CS:#Screen.ResourcePtr;
@createres.ebx:
mov FS:#ESI,#EBX;
inc EBX; inc ESI;
loop @createres.ebx;
pop ECX;
mov EBX,CS:#Screen.ResourcePtr;
add CS:#Screen.ResourcePtr,ECX;
pop ESI;
ret
//Internal - Create text pointed by EBX (null terminated)
GPU.CreateResource.EBX.Text:
push ESI; push ECX; mov ESI,CS:#Screen.ResourcePtr;
mov ECX,0;
@createres.ebx.text:
mov FS:#ESI,#EBX;
inc EBX; inc ESI; inc ECX;
cmp #EBX,0;
jne @createres.ebx.text;
add ECX,1; mov FS:#ESI,0;
mov EBX,CS:#Screen.ResourcePtr;
add CS:#Screen.ResourcePtr,ECX;
pop ECX; pop ESI;
ret
@GetGPUStat.0: mov EAX,CS:#Screen.BasePtr; jmp @GetGPUStat.Ret;
@GetGPUStat.1: mov EAX,CS:#Screen.ResourcePtr; jmp @GetGPUStat.Ret;
@GetGPUStat.2: mov EAX,CS:#Screen.DataPtr; jmp @GetGPUStat.Ret;
GPU.GetResourceStat:
cmp EAX,0; je @GetGPUStat.0;
cmp EAX,1; je @GetGPUStat.1;
cmp EAX,2; je @GetGPUStat.2;
mov EAX,0;
@GetGPUStat.Ret:
ret
//GPU.Clear(clearcolor) - Clear background with color
GPU.Clear:
push ESI; push ECX;
mov ECX,4; call GPU.CreateResource.EAX; //COLOR
mov ESI,_GPU.Command.Clear;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.Rectangle(vec2,vec2) - Draw rectangle
GPU.Rectangle:
push ESI; push ECX;
mov ECX,2; call GPU.CreateResource.EAX; //VEC2F
mov ECX,2; call GPU.CreateResource.EBX; //VEC2F
mov ESI,_GPU.Command.DrawRect;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.Circle(vec2,radius) - Draw circle
GPU.Circle:
push ESI; push ECX;
mov ECX,2; call GPU.CreateResource.EAX; //VEC2F
mov ECX,1; call GPU.CreateResource.EBX; //FLOAT
mov ESI,_GPU.Command.DrawCirc;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.Line(vec2,vec2) - Draw a line
GPU.Line:
push ESI; push ECX;
mov ECX,2; call GPU.CreateResource.EAX; //VEC2F
mov ECX,2; call GPU.CreateResource.EBX; //VEC2F
mov ESI,_GPU.Command.DrawLine;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.OutlineRect(vec2,vec2) - Draw outlined rectangle
GPU.OutlineRect:
push ESI; push ECX;
mov ECX,2; call GPU.CreateResource.EAX; //VEC2F
mov ECX,2; call GPU.CreateResource.EBX; //VEC2F
mov ESI,_GPU.Command.DrawOutl;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//-- Advanced rendering --------------------------------------------------------
GPU.DrawPolygon://GPU.DrawPolygon(ghandle)
GPU.DrawVxBuf://GPU.DrawVertexBuffer(ghandle)
int 29;
ret
//GPU.RenderText(pos,text)
GPU.RenderText:
push ESI; push ECX;
mov ECX,2; call GPU.CreateResource.EAX; //VEC2F
call GPU.CreateResource.EBX.Text; //STRING
mov ESI,_GPU.Command.DrawText;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.SetFont(font)
GPU.SetFont:
push ESI; push ECX;
mov ECX,1; call GPU.CreateResource.EAX; //FLOAT
mov ESI,_GPU.Command.SetFont;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.SetAlign(align)
GPU.SetAlign:
push ESI; push ECX;
mov ECX,1; call GPU.CreateResource.EAX; //FLOAT
mov ESI,_GPU.Command.SetAlign;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.SetSize(size)
GPU.SetSize:
push ESI; push ECX;
mov ECX,1; call GPU.CreateResource.EAX; //FLOAT
mov ESI,_GPU.Command.SetSize;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.SetShade(shade)
GPU.SetShade:
push ESI; push ECX;
mov ECX,1; call GPU.CreateResource.EAX; //FLOAT
mov ESI,_GPU.Command.SetShade;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.SetFlash(rate)
GPU.SetFlash:
push ESI; push ECX;
mov ECX,1; call GPU.CreateResource.EAX; //FLOAT
mov ESI,_GPU.Command.SetFlash;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
//GPU.SetColor(col)
GPU.SetColor:
push ESI; push ECX;
mov ECX,4; call GPU.CreateResource.EAX; //COLOR
mov ESI,_GPU.Command.SetColor;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
GPU.SetOffset://GPU.SetOffset(vec)
push ESI; push ECX;
mov ECX,1; call GPU.CreateResource.EAX; //COLOR
mov ESI,_GPU.Command.SetOffset;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
GPU.SetRotateScale://GPU.SetRotateScale(rot,scale)
push ESI; push ECX;
mov ECX,1; call GPU.CreateResource.EAX; //VEC2F
mov ECX,1; call GPU.CreateResource.EBX; //FLOAT
mov ESI,_GPU.Command.RotScale;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
GPU.SetWidth://GPU.SetWidth(width)
push ESI; push ECX;
mov ECX,1; call GPU.CreateResource.EAX; //COLOR
mov ESI,_GPU.Command.SetWidth;
call GPU.Command.Internal;
pop ECX; pop ESI;
ret
GPU.Command://GPU.Command(..)
call GPU.CheckReady; //GPU must be ready...
push EDI;
dec ESI;
@CommandLoop:
inc ESI;
mov EDI,CS:#Screen.BasePtr;
cmp #ESI,-9996660; je @CommandExit;
cmp #ESI,-9996661; je @CommandReg0;
cmp #ESI,-9996662; je @CommandReg1;
cmp #ESI,-9996663; je @CommandReg2;
cmp #ESI,-9996664; je @CommandReg3;
//Send byte
mov FS:#EDI,#ESI; inc CS:#Screen.BasePtr;
jmp @CommandLoop;
@CommandExit:
pop EDI;
ret
//Internal - Send GPU command
GPU.Command.Internal:
add ESI,CS; sub ESI,DS;
call GPU.Command;
ret
@CommandReg0: mov FS:#EDI,EAX; inc CS:#Screen.BasePtr; jmp @CommandLoop;
@CommandReg1: mov FS:#EDI,EBX; inc CS:#Screen.BasePtr; jmp @CommandLoop;
@CommandReg2: mov FS:#EDI,ECX; inc CS:#Screen.BasePtr; jmp @CommandLoop;
@CommandReg3: mov FS:#EDI,EDX; inc CS:#Screen.BasePtr; jmp @CommandLoop;
GPU.Render3D_Start:
GPU.Render3D_End:
GPU.Render3D_Scale:
GPU.Render3D_Translate:
GPU.Render3D_Rotate:
GPU.Render3D_LookAt:
GPU.Render3D_SetPerspective:
GPU.Render3D_Terrain:
GPU.Render3D_Cube:
GPU.Render3D_Plane:
int 29;
ret
//GPU.DriverCommand(cmd,...)
GPU.DriverCommand: //Serves as way to provide extra functions
cmp EAX,0; je GPU.DriverCommand.0;
cmp EAX,1; je GPU.DriverCommand.1;
GPU.DriverCommand.End:
ret
GPU.DriverCommand.0: //0: CMD_DRIVER_VERSION
mov EAX,GPU_DRIVER_VERSION;
jmp GPU.DriverCommand.End;
GPU.DriverCommand.1: //1: CMD_SET_CONTROL_BITS
mov CS:#Screen.ControlBits,EBX;
jmp GPU.DriverCommand.End; That works for me in BlackFOX. It's a GPU driver for CPU, but this can be adapted to be controlled via E2 (E2 can write commands to CPU RAM, and CPU can execute them)
Bookmarks