'******************************************************************************
'* 
'* BK-0010 VIDEO EMULATION (VIDEO DEVICE)
'*
'* Supported platform/bus: Soviet PDP-11 based home computers BK-0010/11
'*
'* Current emulation is not cycle-wise
'*
'* Version history:
'*  2009 - initial emulation (by WadiM)
'*
'****************************************************************************** 

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

'device interface support
public use object DEVICE

//device name
DeviceName="BK-0010 Video"
DebugName="VIDEO" 

//variables
dim scrollreg as byte=0 'register of vertical scrolling (by 1 lines)

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

//Video memory 
use object MEMORY_BUFFER as vidmem : vidmem.Size=0x4000 
    vidmem.BaseAddress=0x4000 : vidmem.AddressRange=0x3FFF
    vidmem.AddressMask=0x3FFF : vidmem.AddressOffset=0

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

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

//Initial video palette 
image.Palette(0x0)=RGB(0,0,0) 		'black 
image.Palette(0x1)=RGB(255,255,255) 	'white

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

//Read/Write video memory
public function ReadMemory alias vidmem.ReadMemory
public function WriteMemory alias vidmem.WriteMemory

//Write scroll register
public property SCROLL_REG(Value as byte)
 ?? DebugPrefix;">ScrollReg=";Hex(Value,2);"h"
 scrollreg=Value and 0x2FF: vidmem.Changed=true
end

//Read scroll register
public function SCROLL_REG as byte
 result=scrollreg
 ?? DebugPrefix;"<ScrollReg=";Hex(result,2);"h"
end

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

const ScreenSize as integer=256*64

//Rendering of video memory to bitmap
procedure RenderScreen
 //variables
 dim x as integer, y as integer, i as integer, pos as integer=0
 dim b as byte, b1 as byte, b2 as byte, b3 as byte, b4 as byte
 dim b5 as byte, b6 as byte, b7 as byte, i64 as int64
 i=(scrollreg-216)*64 '216=0330 - scroll offset of first line of screen buffer
 if i<0 then i=i+ScreenSize else if i>=ScreenSize then i=i-ScreenSize
 image.pos=0 : vidmem.pos=i
 //rendering
 for y=0 to 255 : for x=0 to 63 //blocks 1x8
    'read 8-pixel block
    b=vidmem.Byte
    image.DrawBitMask(x*8,y,8,1,b, _
         image.Palette(1),image.Palette(0))
 next x : next y
 //mark memory unchanged
 vidmem.Changed=false
end

//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 vidmem.Changed then
  RenderScreen
  'output result
  pc.DrawScreen(image.Object,4/3) 
 end if
 'set vertical retrace IRQ 
 //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

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

 //success
 result=true

end 

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

