This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
blunty666's profile picture

Bios Level Coroutine Override

Started by blunty666, 01 September 2014 - 09:06 AM
blunty666 #1
Posted 01 September 2014 - 11:06 AM
Hi All,

I'm currently (slowly) coding my own OS and thought running it from within the shell seemed somewhat inelegant, so I've created a top level coroutine override in the same vain as Nevercast's. It's presented as a function that takes two arguments. The first is the function you want to be run at top level, this gets called from within a pcall so any errors can be captured. Any errors are then passed to an error handler function which can be passed as the second optional argument, though if none is specified there is a default error handler instead.

For example using the function:

local function main()
  parallel.waitForAny(
	function()
	  os.run({}, "/rom/programs/shell")
	end,
	function()
	  rednet.run()
	end
  )
end

run(main)
would be the easiest example, since this is what is already called by the original bios (before multishell and 1.6 that is).

Or if you didn't want rednet running in the background you could use:

local function main()
  os.run({}, "/rom/programs/shell")
end

run(main)
as the function to be run.

From my testing this works for CC1.6+ and should hopefully work for previous versions. It can be used from within the startup program or can be run from anywhere within the shell and will still work.

Download: http://pastebin.com/iU09rXRs
Spoiler

local function run(mainFunc, errFunc)
  if type(mainFunc) ~= "function" then
	error("Nothing to run", 2)
  end

  local oldOsShutdown, oldCoroutineStatus = os.shutdown, coroutine.status

  local function clearScreen()
	term.redirect(type(term.native) == "function" and term.native() or term.native)
	term.setBackgroundColour(colours.black)
	term.setTextColour(colours.white)
	term.setCursorPos(1, 1)
	term.setCursorBlink(false)
	term.clear()
  end

  local function coroutineStatusOverride(...)
	return "dead"
  end

  local function osShutdownOverride()

	clearScreen()

	rednet.close()
	os.unloadAPI("rednet")
	os.loadAPI("/rom/apis/rednet")

	rawset(os, "shutdown", oldOsShutdown)
	rawset(coroutine, "status", oldCoroutineStatus)

	local ok, err = pcall(mainFunc)

	if not ok then
	  clearScreen()
	  pcall( function()
		if type(errFunc) == "function" then
		  errFunc(err)
		else
		  printError(err)
		  print("Press any key to continue")
		  os.pullEvent("key")
		end
	  end )
	end

	os.shutdown()

  end

  rawset(os, "shutdown", osShutdownOverride)
  rawset(coroutine, "status", coroutineStatusOverride)

end
tenshae #2
Posted 03 September 2014 - 04:33 PM
This is… great, actually. Mind if I use this in my OS? (credit will be given obviously)
blunty666 #3
Posted 03 September 2014 - 05:30 PM
This is… great, actually. Mind if I use this in my OS? (credit will be given obviously)
Yes of course, feel free to use this however you please. Should probably put something about that in the first post :)/>
ElvishJerricco #4
Posted 04 September 2014 - 10:00 PM
Wow this is a clever way to do the override. There was a whole code golf game dedicated to this sort of thing starting with my first submission here. The shortest one was also mine, clocking in at 29 characters here. There were several good ideas in that thread about how to do the override but I think your's is pretty cool.
blunty666 #5
Posted 04 September 2014 - 10:20 PM
Wow this is a clever way to do the override. There was a whole code golf game dedicated to this sort of thing starting with my first submission here. The shortest one was also mine, clocking in at 29 characters here. There were several good ideas in that thread about how to do the override but I think your's is pretty cool.
How have I not seen that topic before, love this kind of stuff, always good to do as a technical exercise! Don't think I'll be trying to beat 29 characters any time soon though…