2

Hi,

on a Mac (Big Sur) I did some experiments with drawing a 3D starfield using lines.

Cart #mefuzakofe-0 | 2021-02-23 | Code ▽ | License: CC4-BY-NC-SA
2

However, PICO-8 regularly crashes completely (play around with the 6 buttons for the star speed in all 3 directions) and a debug with lldb on the Mac terminal uncovered the following:

So there seems to be a problem in 0.2.2 with line drawing somewhere.

I hope this can be fixed for the upcoming 0.2.2b

• Martin
P#88079 2021-02-23 23:35

Could it be that PICO-8 crashes on division by zero?

P#88111 2021-02-24 17:18

After doing quite a bit of testing, I've pinpointed what I believe are the minimal conditions that need to be true to trigger the crash.

When executing the command line(x1,y1,x2,y2), the following conditions must be true for a crash to occur (the same thing happens if y1 and y2 are exchanged, but for the sake of simplicity, y1 is assumed to be positive here):

• flr(x1)!=flr(x2)
• y1>=0 and y1<128
• flr(y2-y1)==0x8000
• flr(y2)<0x8080

I've prepared a demonstration cart which, in v0.2.2, should crash almost immediately. It tries to draw lines using the values for y and i in the code, and it also displays two of the aforementioned conditions. It consistently crashes the moment both conditions display true.

 ```y=0x8000 for i=128,0,-0x0000.0001 do cls() print(" i = "..tostr(i,true)) print(" y = "..tostr(y,true)) print(" y+i = "..tostr(y+i,true)) print() print(" flr(y)==0x8000 = "..tostr(flr(y)==0x8000)) print("flr(y+i)<0x8080 = "..tostr(flr(y+i)<0x8080)) flip() line(0,i,1,y+i) end```

Cart #takepujona-0 | 2021-02-24 | Code ▽ | License: CC4-BY-NC-SA

The line() command with large-magnitude negative numbers appears to behave strangely in general; I don't remember what arguments triggered it exactly, but one line command I tried while pinpointing the bug filled almost the entire screen up with pixels, which shouldn't happen with a single line! I hope zep can fix this for v0.2.2b just as much as you do.

EDIT: Oh my, the web export behaves strangely! It seems that the text for the pause menu becomes jumbled after the crash conditions happen, instead of the PICO-8 player just crashing outright...and then when I reset the cart, it gives me a "syntax error: ) expected" message and a "attempt to call a nil value" message at the same time, after which I can't do anything. Curiouser and curiouser...

P#88113 2021-02-24 19:18 ( Edited 2021-02-24 19:24)
2

Thanks @leissler, @JWinslow23 -- this is fixed for 0.2.2b

It was happening when ABS(dy1-dy0) >= 32768, causing some int32's to overflow during clipping calculations (I've been trying to remove int64's where possible because they are very slow under asm.js). In 0.2.2 the low-level putpixel doesn't do any range checking, so when the clipping is incorrect it means arbitrary memory can be clobbered, which seems to produce the weirdest behaviour under the web version.

P#88139 2021-02-25 03:57

I just installed 0.2.2c and it's much more stable now.
However, I still get PICO-8 to crash if I let the stars go fast enough and play around with insane speeds.
lldb says the following:

I don't think it's too critical anymore, but just good to know that there is still a vulnerability in the line drawing code somewhere.

The latest code I used is this

 ```st={} pst={} stc={7,6,13,5} o=count(stc) zd=256 ns=250 sx,sy,sz=0,0,-2 function _init() xd=64*zd yd=64*zd srand(0x0000.72f5) for i=0,ns-1 do st[3*i]=rnd(2*xd)-xd st[3*i+1]=rnd(2*yd)-yd st[3*i+2]=rnd(zd) end end function getinput() if (btn(0)) sx-=10 if (btn(1)) sx+=10 if (btn(2)) sy-=10 if (btn(3)) sy+=10 if (btn(4)) sz-=0.2 if (btn(5)) sz+=0.2 end function _update60() getinput() for i=0,ns-1 do x,y,z=st[3*i],st[3*i+1],st[3*i+2] px,py,pz=x,y,z x+=sx y+=sy z+=sz if x>xd then x-=2*xd px=x py=y pz=z elseif x<-xd then x+=2*xd px=x py=y pz=z end if y>yd then y-=2*yd px=x py=y pz=z elseif y<-yd then y+=2*yd px=x py=y pz=z end if z<0 then z+=zd px=x py=y pz=z elseif z>zd then z-=zd px=x py=y pz=z end st[3*i],st[3*i+1],st[3*i+2]=x,y,z pst[3*i],pst[3*i+1],pst[3*i+2]=px,py,pz end end function _draw() cls(0) print(stat(1),0,0,14) for i=0,ns-1 do x,y,z=st[3*i],st[3*i+1],st[3*i+2] px,py,pz=pst[3*i],pst[3*i+1],pst[3*i+2] line(px/pz+64,py/pz+64,x/z+64,y/z+64,stc[1+flr(o*z/zd)]) end end ```
P#88577 2021-03-05 13:38

on web - it shows memory corruption artifacts, see ‘garbage lines’ on top.

P#88581 2021-03-05 15:09

Hah, like the good ol' Amiga times, when we had the "normal" crashes (called guru meditation, where the processor exception was handled) and then we had "freak-outs", which were totally unpredictable memory overwriting monsters with spectacular effects when chip-memory was randomly filled... good stuff ;)

P#88583 2021-03-05 15:32

The only hint I have here is that when I change the clipping plane from 0 to 1 or 2 then it gets significantly harder to crash it.
So instead of having this in the update()

 `if z<0 then z+=zd px=x py=y pz=z`

writing

 `if z<2 then z+=zd px=x py=y pz=z`

Since we are dividing by z, this would suggest that it's still about significantly large coordinates for the lines.

P#88593 2021-03-05 19:11 ( Edited 2021-03-05 19:13)