'******************************************************************************
'* 
'* BK CHIPSET (CHIPSET DEVICE)
'*
'* Supported platform/bus: Soviet PDP-11 based home computers BK-0010/11
'*
'* Version history:
'*  2009 - initial emulation (by WadiM)
'*
'****************************************************************************** 

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

//parent DEVSET implementation
public use object DEVSET

//motherboard name
DeviceName="BK Chipset"
DebugName="CHIPSET"

//variables
dim i as integer

'---------------------------- Video device (VID) ------------------------------

//Video 
public use object VID_BK as vid : AddDevice(vid)
for i=0x4000/1024 to 0x7FFF/1024 //video memory
    mem.KBReader(i)=vid.ReadMemory : mem.KBWriter(i)=vid.WriteMemory : next

'------------------------------ Keyboard (KBC) --------------------------------

//Keyboard
public use object KBC_BK as kbc : AddDevice(kbc)
pc.HandleKey=kbc.HandleKey

'------------------ Handling of I/O registers at 0xFF80..0xFFFF ---------------

//Memory writer
protected function MemIOWriter(Addr as dword, Value as byte) as boolean //ROM areas
 //TODO - timer emulation ("AFR_DEMO" etc)
 select case Addr 
 case 0xFFB0 : kbc.STATE_REG(1)=Value //low byte of keyboard state register
 case 0xFFB1 : kbc.STATE_REG(2)=Value //high byte of keyboard state register
 case 0xFFB4 '177664 (low byte of screen scroll register)
    vid.SCROLL_REG=Value
 case else
    if Addr>=0xFF80 then ?? DebugPrefix;">UnkReg[";Oct(Addr,4);"]:=";Oct(Value,2)
 end select
 result=true
end

//Memory reader
protected function MemIOReader(Addr as dword, byref Value as byte) as boolean
 //TODO - timer emulation ("AFR_DEMO" etc)
 result=true
 select case Addr 
 case 0xFFB0 : Value=kbc.STATE_REG(1) //low byte of keyboard state register
 case 0xFFB1 : Value=kbc.STATE_REG(2) //high byte of keyboard state register
 case 0xFFB2 : Value=kbc.DATA_REG(1) //low byte of keyboard data register
 case 0xFFB3 : Value=kbc.DATA_REG(2) //high byte of keyboard data register
 case 0xFFCE '177716 (low byte of external i/o devices register)
    Value=0x80 'need this by some soft (such as "Tennis")
    if not kbc.HasPressedKeys then Value=Value or 0x40
 case 0xFFB4 '177664 (low byte of screen scroll register)
    Value=vid.SCROLL_REG
 case else : result=false 'read ROM
    if Addr>=0xFF80 then ?? DebugPrefix;"<UnkReg[";Oct(Addr,4);"]:=";Oct(Value,2)
 end select
end

'------------------------------ IRQ Emulation ---------------------------------

//IRQ flags
dim HasIRQs as boolean 'is one of IRQ active
dim IRQ1 as boolean  'vector 04  (incorrect address, STOP key)
dim IRQ12 as boolean 'vector 060 (keyboard)


//Set IRQ
public function SetIRQ(Index as integer, State as boolean) as boolean
 ?? DebugPrefix;"SetIRQ(";Hex(Index,2);"h, ";State;")"
 select case Index 
 case 1 'address error or STOP key
    IRQ1=State : result=true
 case 12 'keyboard
    IRQ12=State : result=true
 case else :  result=false : end select
 if result then HasIRQs=IRQ1 or IRQ12
end

//Get IRQ
public function GetIRQ(Process as boolean,byref Address as dword) as integer
 result=-1 : if HasIRQs then
   select case TRUE 
   case IRQ1 'address error or STOP key
     result=1 : if Process then IRQ1=false
   case IRQ12 'keyboard
     if (cpu.Flags and 0x80)=0 then 'P-flag
        result=12 : if Process then IRQ12=false
      end if
   end select
   if result>=0 then : Address=result*4
      if Process then HasIRQs=IRQ1 or IRQ12
   end if
 end if
 ?? DebugPrefix;"GetIRQ(";Process;")=";result
end

//Configure IRQs
pc.SetIRQ=SetIRQ : pc.GetIRQ=GetIRQ

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

//Device initialization
protected function DEV_INIT(stream as object,byref EventFreq as integer) as boolean
 dim i as integer, s as string
  
 'parent call
 if not DEV_INIT(stream,EventFreq) then exit(false)
 if EventFreq<100 then EventFreq=100

 'success 
 result=true
end

