'******************************************************************************
'* 
'* SEGA MASTER SYSTEM 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 "SMSVIDEO"

//device name
DeviceName="Sega Master System Video"
DebugName="VIDEO" 

//variables
dim i as integer

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

//Video memory (16Kb of internal memory)
use object MEMORY_BUFFER as vidmem : vidmem.Size=0x4000

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

//Video bitmap
use object BITMAP_IMAGE as image : image.Width=256 : image.Height=192

//SMS Mode 4 Palette
for i=0 to 63 : image.Palette(i)= _
  RGB(85*(i and 3), 85*(shr(i,2) and 3), 85*(shr(i,4) and 3)) : next i

i=256-16 //TMS Modes Palette (at end of 256-entries of image palette)
image.Palette(i+0x0)=RGB(1,2,3)             'transparent
image.Palette(i+0x1)=RGB(0,0,0)             'black
image.Palette(i+0x2)=RGB(33,200,66)         'green
image.Palette(i+0x3)=RGB(94,220,120)        'light-green
image.Palette(i+0x4)=RGB(84,85,237)         'dark-blue
image.Palette(i+0x5)=RGB(125,118,252)       'light-blue
image.Palette(i+0x6)=RGB(212,82,77)         'dark-red
image.Palette(i+0x7)=RGB(66,235,245)        'cyan
image.Palette(i+0x8)=RGB(252,85,84)         'red
image.Palette(i+0x9)=RGB(255,121,120)       'light-red
image.Palette(i+0xA)=RGB(212,193,84)        'dark-yellow
image.Palette(i+0xB)=RGB(230,206,128)       'light-yellow
image.Palette(i+0xC)=RGB(33,176,59)         'dark-green
image.Palette(i+0xD)=RGB(201,91,186)        'purple
image.Palette(i+0xE)=RGB(204,204,204)       'gray
image.Palette(i+0xF)=RGB(255,255,255)       'white

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

//Read current scanline index port
public function VINDEX_PORT as byte
 result=VIndexPort
 ?? DebugPrefix;"<VIndexPort=";Hex(result,2);"h"
end direct VIndexPort

//Read current dot index port
public function HINDEX_PORT as byte
 result=HIndexPort
 ?? DebugPrefix;"<HIndexPort=";Hex(result,2);"h"
end direct HIndexPort

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

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

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

//Read state port
public function STATE_PORT as byte
 result=StatePort
 ?? DebugPrefix;"<StatePort=";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

