Log In  

Hi, I was experimenting with a way of making a multiplayer game on Pico-8 (on different cartriges to have more screen space).
So I was looking for a way to communicate from the cart to the host OS, I know it's possible to inject and retreive data on the web exports with javascript but I'm trying to find a way to do it localy .

I have tried that code:

cls()
i_channel=0x804
o_channel=0x805
input=''
output=''

function _update()
    local nb=0
    repeat
        nb=serial(i_channel,0x8000,0x1000)
        for i=0,nb do
            input..=chr(peek(0x8000+i))
        end
    until nb==0

    if (btnp(⬅️)) output..='⬅️' stdout('left ')
    if (btnp(➡️)) output..='➡️' stdout('right ')
    if (btnp(⬆️)) output..='⬆️' stdout('up ')
    if (btnp(⬇️)) output..='⬇️' stdout('down ')
    if (btnp(🅾️)) output..='🅾️' stdout('𝘰 ')
    if (btnp(❎)) output..='❎'   stdout('𝘹 ')
end

function _draw()
    print('\^rf'..output,2,2,7)
    print('\^rw'..input,66,2,13)
end

function stdout(str)
    for i,c in pairs(split(str,'')) do
        poke(0x9000+i-1,ord(c))
    end
    serial(o_channel,0x9000,#str) 
end

it uses the stdin and stdout of the cart to read and write into files when called like this:
> pico8 < input_file.txt > output_file.txt -run mycart.p8
The problem I ran into is that I can't use the same file for the input and output.

My best attempt was to use a pipeline to redirect the stdout of a cart to the stdin of another one like this:
> pico8 -run mycart.p8 | pico8 -run mycart.p8
The problem here is that a strange thing is happening, the first cart boots and works fine but the second one freezes until the first one is shutdown. Then it works as intended, I get the output from the first cart. But I am not able to make the to instances of the cart run at the same time and communicate.

Any idea how to pull it of ?

P#144253 2024-03-23 23:56 ( Edited 2024-03-23 23:59)

I don't know how you would solve this, but I'm pretty sure the reason you're running into the freezing issue is that OS's generally handle writing to files by either loading the file under the hood (in the case of "appending") or just starting a new file fresh (in the case of "writing"), then replacing the file on disk with the new file. As such, the carts are only ever actually writing to their own versions of the file in their own memory.

If you know of a way to interpret output from a cart as a signal to close an reopen the file in use for stdout, then that might work, but it'd have to be signal in a different way than stdout itself.

P#144266 2024-03-24 02:44

It might be using buffered i/o, meaning it won't flush the writes until the buffer is full or certain things happen. Sometimes an EOL character will flush the buffer, it all depends on the API. Usually something will flush it eventually.

If so, the first instance might not be flushing until the app shuts down, unless you write a lot of data.

The default C stdio buffer is usually 4k. Try writing at least 4k and see if it gets flushed. Then try 64k just to see if that works.

You could also try adding newlines to each string.

Edit: I tried these things. Didn't help.

P#144982 2024-03-29 14:30 ( Edited 2024-03-29 20:15)

how do you plan to play a multiplayer game with 2 windows?
only 1 window will get inputs…

if you want more ‘real estate’, look at the ‘secret’ x_displays command line option (and _map_display(id))

P#144984 2024-03-29 14:40

I looked into it... it's definitely stalling the entire second app when it gets to the point where it calls serial(804...) to read stdin.

I don't think there's much you can do right now. I think @zep might need to change how he handles it when it's a pipe. Also I think the | pipe in the shell is uni-directional. You might have to use PowerShell to create a named pipe and then pass its UNC path (\\.\pipe\mypipename) to the -i and -o parameters on each app (using serial(805...) and serial(806...) respectively instead), maybe even two named pipes, one for each direction. But I honestly dunno if it can be made to work without @zep making sure it does.

Also, even if you comment out the serial(804...) so it doesn't try to read stdin, the second app still softlocks if it tries to write to serial(805...) when you press a button. I don't think a shell pipe is bidirectional. You can make a bidirectional one with PowerShell, I think.

BTW I tried named pipes myself briefly but couldn't get them to work. I might just be inept, I dunno, it's not something I've worked with before.

PS: I'm not sure how stdio is supposed to work, at least on Windows, since the app automatically detaches from the shell that spawned it. I can see how redirecting to/from a file might work, but the default shell i/o doesn't seem to...?

P#145031 2024-03-29 20:05 ( Edited 2024-03-29 20:20)

So I looked into it and decided to go the easy way doing it with web export and using javascript to read/rite data to gpio pins. My plan is that the js will open the other window(s) and doing so it will have access to the gpio pins of the other window(s). The main cart will be the one getting all the input as it can be the only one focused, and the other carts will just show the game state.

But the problem I face now is how to stream data with gpio pins in web ? Could serial() be a solution ?

I'm thinking as I use a javascript listener that notify me when a gpio value changes, could I write and override gpio pins data in a single frame and still be able to get all data or is the js gpio array only updated each frame ?

Idealy if I can have that working I could render the game in the main cartrige and stream out the resulting draw buffer to other cartriges that would simply stream in the data to the 0x6000 address and thus acting as simple TVs that display the signal they're given

P#146005 2024-04-07 23:01 ( Edited 2024-04-07 23:06)

you cannot exit from the browser sandbox this way
using gpio pins.
you could use gpio to communicate with a web-server and then a second pico would do the same.

gpio pins are only available on some linux os (and only using devkit).

have you see seen:
https://github.com/freds72/pico8-net

(but really - this is really not usable as a solution - not sure what you really want to do here on a single machine)

P#146058 2024-04-08 14:09 ( Edited 2024-04-08 14:12)
1

on desktop, you need to use the standard streams channels, not gpio

see this example: https://www.lexaloffle.com/bbs/?tid=38732

P#146059 2024-04-08 14:12

Oh thanks, this is just what I was looking for !

P#146106 2024-04-08 21:36

[Please log in to post a comment]