Starting with OpenComputers 1.3 computers need an “Operating System” to function - OpenOS is no longer built-in. As of 1.4(.2?) you even need an EEPROM in your computers, which acts as the BIOS of the machine. While this makes it slightly more annoying to set up computers, it opens up a lot more possibilities for people that want to write their own OSes; which is what this article is all about!
The only thing built-in now is the “machine” booting the BIOS. This “machine” wrapper is a non-editable Lua script responsible for setting up the sandbox and super-low-level interaction with the “host” side of things (that being Java/Scala). When a computer is powered on, that script is loaded and run. After estabilishing the sandboxed environment it looks for an EEPROM and tries to run the data on it as a Lua script. If that fails the computer crashes. Otherwise that BIOS is run. For the provided one (Lua BIOS, crafted using EEPROM + book) it will perform the actions previously done by the machine itself:
init.luascript is found, the computer crashes with a
no bootable medium founderror.
But since you can program the EEPROM however you like you could also boot from a network device, for example.
There are a few libraries documented on the wiki that are in fact part of OpenOS, so when you're implementing your own operation system, those won't be at your disposal. Most notably that includes the
filesystem libraries. For a definite reference for what's available in an init script, check the kernel. The following list isn't guaranteed to be complete and/or up-to-date!
_G _VERSION assert error getmetatable ipairs load next pairs pcall rawequal rawget rawlen rawset select setmetatable tonumber tostring type xpcall bit32.arshift bit32.band bit32.bnot bit32.bor bit32.btest bit32.bxor bit32.extract bit32.lrotate bit32.lshift bit32.replace bit32.rrotate bit32.rshift coroutine.create coroutine.resume coroutine.running coroutine.status coroutine.wrap coroutine.yield debug.getinfo debug.traceback math.abs math.acos math.asin math.atan math.atan2 math.ceil math.cos math.cosh math.deg math.exp math.floor math.fmod math.frexp math.huge math.ldexp math.log math.max math.min math.modf math.pi math.pow math.rad math.random math.randomseed math.sin math.sinh math.sqrt math.tan math.tanh os.clock os.date os.difftime os.time string.byte string.char string.dump string.find string.format string.gmatch string.gsub string.len string.lower string.match string.rep string.reverse string.sub string.upper table.concat table.insert table.pack table.remove table.sort table.unpack checkArg component.doc component.fields component.invoke component.list component.methods component.proxy component.slot component.type computer.address computer.addUser computer.beep computer.energy computer.freeMemory computer.getArchitectures computer.getArchitecture computer.getBootAddress computer.maxEnergy computer.pullSignal computer.pushSignal computer.removeUser computer.setArchitecture computer.setBootAddress computer.shutdown computer.tmpAddress computer.totalMemory computer.uptime computer.users unicode.char unicode.charWidth unicode.isWide unicode.len unicode.lower unicode.reverse unicode.sub unicode.upper unicode.wlen unicode.wtrunc
Unlike in OpenOS you don't have the primary system for components in BIOS. That means you cannot just write
component.redstone.setOutput, you have to manually create your proxy for the component first. For several reasons the proxy system is provided via the machine itself, so you can still use that. To get a proxy, use the
component.proxy method. It expects the address of the component to wrap. You can either write that down manually, or get the list of components using
component.list and go from there.
For example, to get the first best redstone component, you can do the following:
local r = component.proxy(component.list("redstone")())
This works because
component.list returns a Lua iterator: a function that can be called repeatedly to get the next element in whatever it iterates over, returning
nil once there are no more elements.
When an init script returns, the computer powers down, so you'll want to have a “main loop” in there, regardless of how you structure your OS otherwise. Signals must be processed using
computer.pullSignal, you're free to use any model to provide this to programs running in your OS you please - this is what OpenOS'
event.pull does, for example.
You'll also want to take care of setting up attached components during your OS' boot routine, such as binding GPUs to screens.
Aside from that, go crazy, be creative!