'******************************************************************************
'* 
'* VIDEO GRAPHIC ARRAY ADAPTER (VGA) (VIDEO DEVICE)
'*
'* Introduced in x86 PS/2 models
'*
'* Supported platform/bus: X86
'* 
'* Version history:
'*  2007 - initial emulation (by WadiM)
'*
'****************************************************************************** 

//DEBUG.ON 'uncomment to enable debug messages (can be slow for hi-freq events)

'ISA device interface support
public use object DEVICE_ISA

//device name
DeviceName="VGA Video Adapter"
DeviceGroupName="VGA"
DebugName="VID_VGA" 

'internal implementation (temporary)
use internal "VGAVIDEO" as vga

//Chargen
use object MEMORY_STREAM as CharGen : CharGen.Size=8*256
CharGen.Bytes(0)=ArrayFile("Fonts\ru8x8.fnt",0,256*8) 'default font

'-------------------------------- H/W Interface -------------------------------

//Write video memory
public function WriteMemory alias vga.WriteMemory

//Read memory
public function ReadMemory alias vga.ReadMemory

//Write vga ports
public property Ports alias vga.Ports

//Read vga ports
public function Ports alias vga.Ports

'-------------------------- Port stubs to trace VGA ports ---------------------

//if VGA port tracing needed, uncomment and attach next handlers (temporary)

'Write all ports
public property PORTS2(Index as word, Value as byte)
 PORTS(Index)=Value 'parent call
 ?? DebugPrefix;">PORT(";Hex(Index,4);")=";Hex(value,2)
end

'Read all ports
public function PORTS2(Index as word) as byte
 result=PORTS(Index) 'parent call
 ?? DebugPrefix;"<PORT(";Hex(Index,4);")=";Hex(result,2)
end

'------------------------------ Rendering -------------------------------------

//Rendering event handler (50Hz by default)
function RenderEvent(freq as integer,eventid as dword) as boolean
 result=true 'need next event call
 'render screen only if something changed
 if vga.Changed then : vga.Changed=false
 dim aspect as double
 if Height=0 then : aspect=320/200 : else
 if abs((Width/Height)-4/3)<abs((Width/Height)-320/200) then
    aspect=4/3 
 else 
   aspect=320/200
 end if : end if
 pc.DrawScreen(vga.RenderScreen,aspect) 
 end if
end

//Cursor blink event (4Hz by default)
function CursorEvent(freq as integer,eventid as dword) as boolean
 result=true 'need next event call
 CursorFlag=not(CursorFlag)
end

'---------------------------- DEVICE Interface --------------------------------

//Device initialization
public function DEV_INIT(stream as object,byref EventFreq as integer) as boolean

 'parent call
 if not DEV_INIT(stream,EventFreq) then exit(false)
 if EventFreq<100 then EventFreq=100

 //register 50Hz rendering event
 pc.NewFreqEvent(50)=RenderEvent '50Hz rendering
 pc.NewFreqEvent(4)=CursorEvent  '4Hz cursor blinking

 //success
 result=true

end 

