//Configuration.bcpl - XM support for RunMesa - R. Levin
//last modified by Johnsson:  September 22, 1980  3:07 PM 

get "AltoDefs.d"
get "AltoFileSys.d"
get "SysDefs.d"
get "RunMesa.d"

static	[
	ROMCompatibility
	]

manifest	[ EmulatorBR = #177740 ]

structure BankRegister: [
		  unused bit 12
		  primary bit 2
		  alternate bit 2
		]

let DetermineConfiguration() be
[DetermineConfiguration
let vers=table [
    #61014		//VERS
    #1401		//JMP 1 3
    ]
let engineeringNumber = vers() rshift 12
Zero(HardwareConfiguration,lHardwareInfo)
test engineeringNumber eq UnknownMachine
    ifso HardwareConfiguration>>HardwareInfo.AltoType = AltoI
    ifnot HardwareConfiguration>>HardwareInfo.AltoType = engineeringNumber
ROMCompatibility = 0;
switchon HardwareConfiguration>>HardwareInfo.AltoType into
  [
  case AltoII: case AltoIIXM: endcase
  case Dolphin: case Dorado:
    [
    HardwareConfiguration>>HardwareInfo.XMmicrocode = true
    HardwareConfiguration>>HardwareInfo.banks = memoryBanks
    ]
  default: return
  ]
ControlStoreType()
if HardwareConfiguration>>HardwareInfo.AltoType eq 2 then
  [ HardwareConfiguration>>HardwareInfo.banks = bank0only; return ]
HardwareConfiguration>>HardwareInfo.banks = memoryBanks & banks0123
memoryBanks =  FindMemoryBanks(banks0123)
HardwareConfiguration>>HardwareInfo.useXM =
  (HardwareConfiguration>>HardwareInfo.banks ne bank0only) &
  HardwareConfiguration>>HardwareInfo.XMmicrocode
]DetermineConfiguration


and let ControlStoreType() be
[ControlStoreType
manifest [
    RAM0loc = #1000; RAM0val = #111111
    RAM1loc = #11000; RAM1val = #52525
    PossibleRAMloc = #777-1
    ]
manifest highword = #2000
// versionTable is the mapping from version numbers available at
// run time to actual version numbers.
// Add new entries at release time
// Version 34 => Mesa 4.1
// Version 39 => Mesa 5.0 -- no distinction for BNDCHK fix patch
// Version 41 => Mesa 6.0
manifest tableLength = 3
let versionTable = table [ 34; 39; 41 ]
let compatibilityTable = table [ 34; 41; 41 ]
let saveRealRAM = vec 3
let savePossibleRAM = vec 3
let testRAM0 = nil
let WriteOne=table [  // (high,address,low)
    #55001		//STA 3 1 2
    #35003		//LDA 3 3 2
    #61012		//WRTRAM
    #35001		//LDA 3 1 2
    #1401		//JMP 1 3
    ]
let ReadOne=table [  // (pointer,address)
    #55001		//STA 3 1 2
    #115000		//MOV 0 3
    #61011		//RDRAM
    #41400		//STA 0 0 3
    #35001		//LDA 3 1 2
    #1401		//JMP 1 3
    ]
let JmpRAM=table [
    #61010		//JMPRAM
    #1401		//JMP 1 3
    ]
let initCP = table [
    #100; #171001;	//     L←ALLONES, SWMODE, :x1;
    #60110; #102020;	// x1: cp←L, :START;
    ]
let getVersionCode = table [
    #60110; #102020;	// x2: cp←L,:START;
    #60; #170776;	//     L←-2, SWMODE,:x2;
    ]
let readCP = table [
    #60060; #101001;	//     L←cp, SWMODE, :x3;
    #14030; #102020;	// x3: AC0←L, :START;
    ]
// Test for 3K RAM machine first
ReadOne(saveRealRAM,highword+RAM0loc);   ReadOne(saveRealRAM+1,RAM0loc);
ReadOne(saveRealRAM+2,highword+RAM1loc);   ReadOne(saveRealRAM+3,RAM1loc);
WriteOne(RAM0val,RAM0loc,RAM0val); WriteOne(RAM1val,RAM1loc,RAM1val);
ReadOne(lv testRAM0,RAM0loc);
WriteOne(saveRealRAM!0,RAM0loc,saveRealRAM!1);
WriteOne(saveRealRAM!2,RAM1loc,saveRealRAM!3);
test testRAM0 eq RAM0val
  ifso	// 3K RAM
    [
    HardwareConfiguration>>HardwareInfo.ControlStore = RAM3K
    HardwareConfiguration>>HardwareInfo.XMmicrocode = true
    return
    ]
  ifnot if testRAM0 ne RAM1val then AbortMsg("Your RAM doesn't work!");
// Test for 2K ROM
ReadOne(saveRealRAM,highword+RAM0loc);   ReadOne(saveRealRAM+1,RAM0loc);
ReadOne(saveRealRAM+2,highword+RAM0loc+1); ReadOne(saveRealRAM+3,RAM0loc+1);
WriteOne(initCP!0,RAM0loc,initCP!1);
WriteOne(initCP!2,RAM0loc+1,initCP!3);
JmpRAM(0,RAM0loc);				// cp ← -1

ReadOne(savePossibleRAM,highword+PossibleRAMloc);   ReadOne(savePossibleRAM+1,PossibleRAMloc);
ReadOne(savePossibleRAM+2,highword+PossibleRAMloc+1);
ReadOne(savePossibleRAM+3,PossibleRAMloc+1);
WriteOne(getVersionCode!0,PossibleRAMloc,getVersionCode!1);
WriteOne(getVersionCode!2,PossibleRAMloc+1,getVersionCode!3);
JmpRAM(0,PossibleRAMloc+1);
WriteOne(savePossibleRAM!0,PossibleRAMloc,savePossibleRAM!1);
WriteOne(savePossibleRAM!2,PossibleRAMloc+1,savePossibleRAM!3);

WriteOne(readCP!0,RAM0loc,readCP!1);
WriteOne(readCP!2,RAM0loc+1,readCP!3);
let valCP = JmpRAM(0,RAM0loc);
WriteOne(saveRealRAM!0,RAM0loc,saveRealRAM!1);
WriteOne(saveRealRAM!2,RAM0loc+1,saveRealRAM!3);
switchon valCP into
  [VersionCases
  case -2:		// no ROM on machine
    [
    endcase
    ]
  case -1:		// ancient ROM on machine
    [
    HardwareConfiguration>>HardwareInfo.mesaMicrocodeVersion = versionTable!0
    HardwareConfiguration>>HardwareInfo.ControlStore = RAMandROM
    endcase
    ]
  default:		// some other ROM on machine
    [
    HardwareConfiguration>>HardwareInfo.ControlStore = RAMandROM
    valCP = valCP & #77777	// ignore obsolete XM microcode version
    if valCP ge tableLength then endcase
    HardwareConfiguration>>HardwareInfo.XMmicrocode = true
    HardwareConfiguration>>HardwareInfo.mesaMicrocodeVersion = versionTable!valCP
    ROMCompatibility = compatibilityTable!valCP
    endcase
    ]
  ]VersionCases
]ControlStoreType


and let FindMemoryBanks(useable) = valof
[FindMemoryBanks
manifest testlocation = 0
let bankBit = #40000			// start with bank 1
let savedactiveInterrupts = @activeInterrupts
let GetAlternateBank=table [
    #61025		//XMLDA
    #1401		//JMP 1 3
    ]
let SetAlternateBank=table [
    #61026		//XMSTA
    #1401		//JMP 1 3
    ]
@activeInterrupts = 0
EmulatorBR>>BankRegister.alternate = 0
until bankBit eq #4000 do
    [
    EmulatorBR>>BankRegister.alternate = EmulatorBR>>BankRegister.alternate+1
    if (useable & bankBit) ne 0 then
      [
      let oldval = GetAlternateBank(0,testlocation)
      SetAlternateBank(oldval+1,testlocation)
      if GetAlternateBank(testlocation) ne oldval+1 then
	useable = useable & not bankBit
      SetAlternateBank(oldval,testlocation)
      ]
    bankBit = bankBit rshift 1
    ]
@wakeupsWaiting = 0
@activeInterrupts = savedactiveInterrupts
resultis useable
]FindMemoryBanks