Tutorial/custom oses: Difference between revisions

From OpenComputers: Rebooted
Jump to navigation Jump to search
imported>OCDoc Import
Imported from legacy OpenComputers documentation at ocdoc.cil.li
 
m Remove references to old versions of OC that had OpenOS in-ROM and didn't support EEPROMs; not relevant to any of the versions this wiki covers
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= Writing custom OSes =
= Writing custom OSes =


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!
Computers need an "Operating System" to function - OpenOS is not built in like CraftOS is built into ComputerCraft computers. 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!


== Booting ==
== Booting ==


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:
The only thing built-in 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:


1. It looks for a file system with address set via `computer.setBootAddress` (read via `computer.getBootAddress`). 2. On that file system it tries to load and execute a Lua script from a file named `init.lua`. 3. If it succeeds, that's it. The user script is now in control. If it fails, it iterates over all present file systems, performing step 2 again until it succeeds. 4. If no working `init.lua` script is found, the computer crashes with a `no bootable medium found` error.
# It looks for a file system with address set via <code>computer.setBootAddress</code> (read via <code>computer.getBootAddress</code>).
# On that file system it tries to load and execute a Lua script from a file named <code>init.lua</code>.
# If it succeeds, that's it. The user script is now in control. If it fails, it iterates over all present file systems, performing step 2 again until it succeeds.
# If no working <code>init.lua</code> script is found, the computer crashes with a <code>no bootable medium found</code> error.


But since you can program the EEPROM however you like you could also boot from a network device, for example.
But since you can program the EEPROM however you like you could also boot from a network device, for example.
Line 13: Line 16:
== What's Available? ==
== What's Available? ==


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 `io`, `package` and `filesystem` libraries. For a definite reference for what's available in an init script, check the kernel or [https://github.com/MightyPirates/OpenComputers/blob/master-MC1.12/src/main/resources/assets/opencomputers/lua/machine.lua machine.lua script for your current OpenComputers version]. The following list isn't guaranteed to be complete and/or up-to-date!
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 <code>io</code>, <code>package</code> and <code>filesystem</code> libraries. For a definite reference for what's available in an init script, check the kernel or [https://github.com/PC-Logix/OpenComputers/blob/master-MC1.21/src/main/resources/assets/opencomputers/lua/machine.lua machine.lua script for your current OpenComputers version]. The following list isn't guaranteed to be complete and/or up-to-date!


```lua _G _VERSION
<syntaxhighlight lang="lua">
_G
_VERSION


assert error getmetatable ipairs load next pairs pcall rawequal rawget rawlen rawset select setmetatable tonumber tostring type xpcall
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
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
coroutine.create
coroutine.resume
coroutine.running
coroutine.status
coroutine.wrap
coroutine.yield
-- Lua 5.3+ only:
coroutine.isyieldable


debug.getinfo debug.traceback debug.getlocal debug.getupvalue
debug.getinfo
debug.traceback
debug.getlocal
debug.getupvalue


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
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
-- Lua 5.3+ only:
math.maxinteger
math.mininteger
math.tointeger
math.type
math.ult


os.clock os.date os.difftime os.time
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
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
-- Lua 5.3+ only:
string.pack
string.unpack
string.packsize


table.concat table.insert table.pack table.remove table.sort table.unpack
table.concat
table.insert
table.pack
table.remove
table.sort
table.unpack
-- Lua 5.3+ only:
table.move
 
-- Lua 5.3+ only:
utf8.char
utf8.charpattern
utf8.codes
utf8.codepoint
utf8.len
utf8.offset


checkArg
checkArg


component.doc component.fields component.invoke component.list component.methods component.proxy component.slot component.type
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.getDeviceInfo computer.getProgramLocations computer.isRobot computer.maxEnergy computer.pullSignal computer.pushSignal computer.removeUser computer.setArchitecture computer.setBootAddress computer.shutdown computer.tmpAddress computer.totalMemory computer.uptime computer.users
computer.address
computer.addUser
computer.beep
computer.energy
computer.freeMemory
computer.getArchitectures
computer.getArchitecture
computer.getBootAddress
computer.getDeviceInfo
computer.getProgramLocations
computer.isRobot
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
unicode.char
 
unicode.charWidth
-- Lua 5.3 only: coroutine.isyieldable
unicode.isWide
 
unicode.len
string.pack string.unpack string.packsize
unicode.lower
 
unicode.reverse
table.move
unicode.sub
 
unicode.upper
math.maxinteger math.mininteger math.tointeger math.type math.ult
unicode.wlen
 
unicode.wtrunc
utf8.char utf8.charpattern utf8.codes utf8.codepoint utf8.len utf8.offset ```
</syntaxhighlight>


== Accessing components in BIOS ==
== Accessing components in BIOS ==


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.
Unlike in OpenOS you don't have the primary system for components in BIOS. That means you cannot just write <code>component.redstone.setOutput</code>, 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 <code>component.proxy</code> method. It expects the address of the component to wrap. You can either write that down manually, or get the list of components using <code>component.list</code> and go from there.


For example, to get the first best redstone component, you can do the following: ```lua 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.
For example, to get the first best redstone component, you can do the following: <syntaxhighlight lang="lua">
local r = component.proxy(component.list("redstone")())
</syntaxhighlight> This works because <code>component.list</code> returns a Lua iterator: a function that can be called repeatedly to get the next element in whatever it iterates over, returning <code>nil</code> once there are no more elements.


== A few more things ==
== A few more things ==


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.
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 <code>computer.pullSignal</code>, you're free to use any model to provide this to programs running in your OS you please - this is what OpenOS' <code>event.pull</code> 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.
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!
Aside from that, go crazy, be creative!

Latest revision as of 19:15, 25 August 2026

Writing custom OSes

Computers need an "Operating System" to function - OpenOS is not built in like CraftOS is built into ComputerCraft computers. 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!

Booting

The only thing built-in 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:

  1. It looks for a file system with address set via computer.setBootAddress (read via computer.getBootAddress).
  2. On that file system it tries to load and execute a Lua script from a file named init.lua.
  3. If it succeeds, that's it. The user script is now in control. If it fails, it iterates over all present file systems, performing step 2 again until it succeeds.
  4. If no working init.lua script is found, the computer crashes with a no bootable medium found error.

But since you can program the EEPROM however you like you could also boot from a network device, for example.

What's Available?

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 io, package and filesystem libraries. For a definite reference for what's available in an init script, check the kernel or machine.lua script for your current OpenComputers version. 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
-- Lua 5.3+ only:
coroutine.isyieldable

debug.getinfo
debug.traceback
debug.getlocal
debug.getupvalue

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
-- Lua 5.3+ only:
math.maxinteger
math.mininteger
math.tointeger
math.type
math.ult

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
-- Lua 5.3+ only:
string.pack
string.unpack
string.packsize

table.concat
table.insert
table.pack
table.remove
table.sort
table.unpack
-- Lua 5.3+ only:
table.move

-- Lua 5.3+ only:
utf8.char
utf8.charpattern
utf8.codes
utf8.codepoint
utf8.len
utf8.offset

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.getDeviceInfo
computer.getProgramLocations
computer.isRobot
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

Accessing components in BIOS

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.

A few more things

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!