Log In  

Hello, I have a use case for some external tooling interacting with a running game. While the game is running I'd like it to process messages sent to it by the tooling. Currently it's not possible to do non-blocking reads from stdin. Calls to serial(0x804, ...) will block until the pico 8 process receives something. What I'd like to do is something like this:

function _update()
  -- Hypothetically stat returns true if there's data available on stdin, false otherwise,
  if stat(123) then
    serial(0x804, 0x4300, 1)
    local message_type = peek(0x4300, 1)
    process_message(message_type)
  end
end

It would be useful to have some way to tell if there's data available on stdin or to perform non-blocking reads from stdin.

P#112550 2022-06-01 07:37

Does it not work to use a coroutine?

For example, something like this seems like it'd work:

function _init()
  msgstate = -1
end

function _update()
  if msgstate == -1 then
    msglen = 1
    msgc = cocreate(_stdin)
    msgstate = 0
  elseif msgstate == 0 then
    if costatus(msgc) == "dead" then
      msglen = @0x4300
      msgc = cocreate(_stdin)
      msgstate = 1
    end
  else
    if costatus(msgc) == "dead" then
      msgstate = -1
      print(chr(peek(0x4300,msglen)))
    end
  end
end

function _stdin()
  serial(0x804,0x4300,msglen)
end
P#112556 2022-06-01 10:27

coroutines don’t seem relevant, the issue is about pico8 buffering or releasing standard streams

P#112558 2022-06-01 11:00

coroutines are not threads, and indeed serial blocking when nothing is received makes it very difficult to handle error or intermittent transmission.
+1

P#112559 2022-06-01 11:14
1

+1; here's a full example of how this is a problem (built together with citizenerased)

x=64
y=64
s=""
function _update()
 local b=btn()
 x+=b\2%2-b%2
 y+=b\8%2-b\4%2

 local len=serial(0x804,0x4300,1)
 if len>0 then
  s..=chr(@0x4300)
 end
end

function _draw()
 cls()
 spr(0,x,y)
 print(s,0,0)
end

invoke this as cat | pico8 -run /path/to/cart.p8 and then type lines of text in your terminal for it to appear in-game. (ctrl-c to exit)

we couldn't figure out a way to move the player while no text was being inputted (because p8 gets stuck waiting for serial to return when there's no input on stdin)

note that this runs fine if you run it normally or with echo hello instead of cat (i.e. when stdin is closed)

P#112575 2022-06-01 16:54
3

little bump – and a suggestion for OP to move this from chat to bugs!

P#127335 2023-03-19 18:31

Not sure if this is exactly a bug more so a quirk of how windows handles pipes.
https://en.wikipedia.org/wiki/Anonymous_pipe usually the workaround is to check if there is anything in stdin before trying to read from it, something like stat(123) would be ideal which is what the original post is asking for.

That being said, to so easily be able to hang pico-8 (pico-8.exe not just the vm) isn't great, so putting it under bugs isn't a bad idea.

Unless the program on the other end of the pipe properly closes it, if pico-8 tries to read a byte from the pipe currently it will hang until it gets the number of bytes it needs, and there doesn't seem to be any way to check if there are any bytes on stdin to read before trying to, so you can't even read them in one at a time either.

Also be sure that if you are using a pipeline to push data onto std in, to use the echo command to properly flush stdout on each newline. Otherwise the data might just be stuck in a buffer on one end and not get to pico-8 at the other.
For Example use: pico -run sender.p8 |echo|pico -run reader.p8 (works on windows via powershell)

P#127339 2023-03-19 21:54
1

I would love to give RP-8 the ability to sync to other devices/software but having stdin reads potentially block is making this task much more difficult. It'd be nice to be able to surface sync in native Mac/Windows/Linux builds and not just via GPIO. (Plus sync via GPIO will be a mess for other reasons.)

P#128455 2023-04-12 00:29

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 10:50:43 | 0.070s | Q:24