'******************************************************************************
'* 
'* SEGA MEGADRIVE VIDEO EMULATION (VIDEO DEVICE) (internal implementation)
'*
'* Current emulation is not cycle-wise
'*
'* Supported platform/bus: Sega consoles
'*
'* Version history:
'*  2009 - initial emulation (WadiM)
'*
'****************************************************************************** 

//DEBUG.ON 'uncomment to enable debug messages (can be slow for hi-freq events)
  //DIRECT.OFF 'uncomment to disable "direct" calls to internal implementation

'device interface support
public use object DEVICE

'internal implementation (direct)
public use internal "SMDVIDEO"

//device name
DeviceName="Sega Megadrive Video"
DebugName="VIDEO" 

//variables
dim i as integer

'----------------------------- Video memory -----------------------------------

//Video memory (16Kb of internal memory)
use object MEMORY_BUFFER as vidmem : vidmem.Size=64*1024 '64Kb

'---------------------- Resulting image and palette ---------------------------

//Video bitmap
use object BITMAP_IMAGE as image

//SMD Palette
for i=0 to 511 : image.Palette(i)= _
  RGB(36*(i and 7), 36*(shr(i,3) and 7), 36*(shr(i,6) and 7)) : next i

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

//Read counter port
public function HV_PORT(Index as byte) as byte
 result=HVPort(Index)
 ?? DebugPrefix;"<HVPort[";Index;"]=";Hex(result,2);"h"
end direct HVPort

//Write data port
public property DATA_PORT(Index as byte,Value as byte)
 ?? DebugPrefix;">DataPort[";Index;"=";Hex(Value,2);"h"
 DataPort(Index)=Value
end direct DataPort

//Read data port
public function DATA_PORT(Index as byte) as byte
 result=DataPort(Index)
 ?? DebugPrefix;"<DataPort[";Index;"=";Hex(result,2);"h"
end direct DataPort

//Write control port
public property CTRL_PORT(Index as byte,Value as byte)
 ?? DebugPrefix;">CtrlPort[";Index;"=";Hex(Value,2);"h"
 ControlPort(Index)=Value
end direct ControlPort

//Read state port
public function STATE_PORT(Index as byte) as byte
 result=StatePort(Index)
 ?? DebugPrefix;"<StatePort[";Index;"=";Hex(result,2);"h"
end direct StatePort

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

//Rendering event handler
function RenderEvent(freq as integer,eventid as dword) as boolean
 result=true 'need next event call
 'render screen only if something changed
 if (Changed) or (vidmem.Changed) then
  RenderScreen
  'output result
  pc.DrawScreen(image.Object) 
  Changed=false : vidmem.Changed=false
 end if
 'set vertical retrace IRQ 
 VSYNC=true //: if IRQAllowed then pc.SetIRQ(0,true)
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

 //set initial data
 InitInternal(vidmem.Object,image.Object) 'init internal inplementation

 //register rendering event
 pc.NewFreqEvent(60)=RenderEvent '60Hz screen rendering (NTSC)

 //success
 result=true

end 

//Device finalization
public procedure DEV_DONE(stream as object)
 //clear bitmap
 image.height=0
 //parent call
 DEV_DONE(stream)
end

