Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 07:12 19 Feb 2026 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : PicoMite V6.02.00 release candidates - Structured types

     Page 12 of 14    
Author Message
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 02:57pm 20 Jan 2026
Copy link to clipboard 
Print this post

I think I am on an issue with heap management. Because I in the version I first submitted I never got issues. But now in the version with dynamic memory I get issues. Which actually leads me to suspect that this dynamic allocating and deallocating causes the heap to corrupt. I also tried to do reverse order in deallocation but still get the error. Which leads me back to my question:
What are the differences of GetMemory and GetMemorySafe also I realized that in the code
sometimes they are called with &array and sometimes just array. sometimes calles with &array.

  if (spritebuff[bnbr].mymaster == -1){
               FreeMemorySafe((void **)&spritebuff[bnbr].spritebuffptr);
           }

and then it is also called without the &

             FreeMemory((unsigned char *)spritebuff[i].spritebuffptr);


Looking at the code I could not really figure out why.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10965
Posted: 03:14pm 20 Jan 2026
Copy link to clipboard 
Print this post

I've made major changes which reduce the memory footprint of sprites. getspritebounds will be called the first time a sprite(B is used on that sprite but the memory left allocated to improve performance for subsequent calls. Because of the fact that the sprite structure is only allocated when a sprite is created for most programs the overall memory footprint should be much lower than before.

Please do not pull code from github until I do a release. At any time it is likely to be junk

Attached the current state of play FYI

Draw.zip
Edited 2026-01-21 01:15 by matherp
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 03:24pm 20 Jan 2026
Copy link to clipboard 
Print this post

It is weird but I needed to reflash the pico with the flashnuke. So the heap error disappered after flashing with flashnuke
 
mclout999

Guru

Joined: 05/07/2020
Location: United States
Posts: 502
Posted: 03:37pm 20 Jan 2026
Copy link to clipboard 
Print this post

Where can I get Flashnuke?
They call me Shai-Hulud (The maker)
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 04:11pm 20 Jan 2026
Copy link to clipboard 
Print this post

  mclout999 said  Where can I get Flashnuke?

https://datasheets.raspberrypi.com/soft/flash_nuke.uf2
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 04:53pm 20 Jan 2026
Copy link to clipboard 
Print this post

I can get the final version which needs to calculate the bounds on every collision to work with:
inside fun_sprite
 short boundsleft[255];
 short boundsright[255];
 short boundstop[255];
 short boundsbottom[255];
             
               
 getspritebounds(bnbr,boundsleft,boundsright,boundstop,boundsbottom);
....
rest of collision check.

Even when just allocating ONCE with GetMemory and not freeing it, keeping it in a static variable inside fun_sprite I get a continous memory drain. it is very weird, because I do not even call freememory.

this causes trouble:
static short *boundsleft=NULL;
static short *boundsright=NULL;
static short *boundstop=NULL;
static short *boundsbottom=NULL;
and then calling
getspritebounds(bnbr,boundsleft,boundsright,boundstop,boundsbottom);


the static should keep the values valid on the heap. I use all same sized sprites.
And I do not free. So in getspritebounds I just check if it is NULL and then call GetMemory only once. But it continously drains the memory. Very weird. And if I allocate memory and free it then the whole thing crashes even the display. So something is even weirder with memory management.
Edited 2026-01-21 02:59 by ksinger
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10965
Posted: 05:29pm 20 Jan 2026
Copy link to clipboard 
Print this post

V6.02.00RC8

PicoMiteBV6.02.00RC8.zip

This version includes a major rework of the sprite engine whilst maintaining full compatibility with older versions. See the attached

SPRITE_User_Manual.pdf

The main change is the implementation of static objects which do not take memory but collide with sprites. See the attached demo. This effectively gives you up to 64 movable sprites and 64 static sprites. In addition it includes new functionality from ksinger. See the manual for details of the SPITE(B function which allows you to interrogate interactions between sprites and the background screen image.

Option explicit
Option default none
Option console serial
MODE 2
FRAMEBUFFER create
FRAMEBUFFER write f
CLS

'brownian motion demo using sprites with static object collisions
Dim integer x(64),y(64),c(64)
Dim float direction(64)
Dim integer i,j,k, collision=0
Dim string q$

' Create the atom sprites
For i=1 To 64
 direction(i)=Rnd*360 'establish the starting direction for each atom
 c(i)=RGB(Rnd*255,Rnd*255,Rnd*255) 'give each atom a colour
 Circle 10,10,4,1,,RGB(white),c(i) 'draw the atom
 Sprite read i,6,6,9,9 'read it in as a sprite
Next i
CLS rgb(myrtle)

' Load background image (pick something 320x240)
'Load jpg "b:/img320"

' Draw screen border
Box 0,0,MM.HRES,MM.VRES

' Draw red obstacle boxes and define them as static objects
' Box 1 - top left area
Box 60,40,50,50,3,RGB(red),RGB(red)
Sprite static 1, 60, 40, 50, 50

' Box 2 - top right area  
Box 210,40,50,50,3,RGB(red),RGB(red)
Sprite static 2, 210, 40, 50, 50

' Box 3 - center
Box 135,95,50,50,3,RGB(red),RGB(red)
Sprite static 3, 135, 95, 50, 50

' Box 4 - bottom left area
Box 60,150,50,50,3,RGB(red),RGB(red)
Sprite static 4, 60, 150, 50, 50

' Box 5 - bottom right area
Box 210,150,50,50,3,RGB(red),RGB(red)
Sprite static 5, 210, 150, 50, 50

' Place the atoms on screen
k=1
For i=MM.HRES\9 To MM.HRES\9*8 Step MM.HRES\9
 For j=MM.VRES\9 To MM.VRES\9*8 Step MM.VRES\9
   ' Skip positions that would overlap with boxes
   If Not inside_box(i, j, 9) Then
     Sprite show k,i,j,1
     x(k)=i
     y(k)=j
     vector k,direction(k), 0, x(k), y(k) 'load up the vector move
   Else
     ' Find a random valid position that doesn't overlap boxes
     Do
       x(k) = Rnd*(MM.HRES-9)
       y(k) = Rnd*(MM.VRES-9)
     Loop Until Not inside_box(x(k), y(k), 9)
     Sprite show k,x(k),y(k),1
     vector k,direction(k), 0, x(k), y(k)
   EndIf
   k=k+1
 Next j
Next i

' Main animation loop
Do
 For i=1 To 64
   vector i, direction(i), 1, x(i), y(i)
   Sprite show i,x(i),y(i),1
   ' Check for sprite collisions OR background object collisions
   If sprite(S,i)<>-1 Then
     break_collision i
   EndIf
 Next i

 FRAMEBUFFER copy f,n
 Print Timer
 Timer = 0
Loop

' Check if a position is inside any of the static boxes
Function inside_box(px As integer, py As integer, size As integer) As integer
 Local integer b
 For b = 1 To 5
   If Sprite(ST, b, A) Then  ' If static object is active
     If px + size > Sprite(ST, b, X) And px < Sprite(ST, b, X) + Sprite(ST, b, W) Then
       If py + size > Sprite(ST, b, Y) And py < Sprite(ST, b, Y) + Sprite(ST, b, H) Then
         inside_box = 1
         Exit Function
       EndIf
     EndIf
   EndIf
 Next b
 inside_box = 0
End Function

' Vector movement subroutine
Sub vector(myobj As integer, angle As float, distance As float, x_new As integer, y_new As integer)
 Static float y_move(64), x_move(64)
 Static float x_last(69), y_last(64)
 Static float last_angle(64)
 
 If distance=0 Then
   x_last(myobj)=x_new
   y_last(myobj)=y_new
 EndIf
 If angle<>last_angle(myobj) Then
   y_move(myobj)=-Cos(Rad(angle))
   x_move(myobj)=Sin(Rad(angle))
   last_angle(myobj)=angle
 EndIf
 x_last(myobj) = x_last(myobj) + distance * x_move(myobj)
 y_last(myobj) = y_last(myobj) + distance * y_move(myobj)
 x_new=Cint(x_last(myobj))
 y_new=Cint(y_last(myobj))
End Sub

' Handle collisions - break them by bouncing
Sub break_collision(atom As integer)
 Local integer j=1, col, bg_hit, hit
 Local integer bx, by, bw, bh, ax, ay
 Local float current_angle=direction(atom)
 Local float dx, dy
 
 ' Check what type of collision occurred
 If sprite(e,atom)=1 Then
   ' Collision with left of screen
   current_angle=360-current_angle
 ElseIf sprite(e,atom)=2 Then
   ' Collision with top of screen
   current_angle=((540-current_angle) Mod 360)
 ElseIf sprite(e,atom)=4 Then
   ' Collision with right of screen
   current_angle=360-current_angle
 ElseIf sprite(e,atom)=8 Then
   ' Collision with bottom of screen
   current_angle=((540-current_angle) Mod 360)
 Else
   ' Check for static object collision
   bg_hit = 0
   For col = 1 To Sprite(C, atom)
     hit = Sprite(C, atom, col)
     If hit >= &H80 And hit < &HF0 Then
       ' Static object collision (codes 0x80-0xBF)
       bg_hit = hit And &H3F  ' Extract object number
       Exit For
     EndIf
   Next col
   
   If bg_hit > 0 Then
     ' Bounce off static object - determine which side was hit
     bx = Sprite(ST, bg_hit, X)
     by = Sprite(ST, bg_hit, Y)
     bw = Sprite(ST, bg_hit, W)
     bh = Sprite(ST, bg_hit, H)
     ax = x(atom) + Sprite(W, atom)\2
     ay = y(atom) + Sprite(H, atom)\2
     
     ' Determine if collision is more horizontal or vertical
     dx = Abs(ax - (bx + bw\2))
     dy = Abs(ay - (by + bh\2))
     
     If dx / bw > dy / bh Then
       ' Horizontal bounce (hit left or right side)
       current_angle = 360 - current_angle
     Else
       ' Vertical bounce (hit top or bottom)
       current_angle = ((540 - current_angle) Mod 360)
     EndIf
   Else
     ' Collision with another sprite or corner
     current_angle = current_angle + 180
   EndIf
 EndIf
 
 direction(atom) = current_angle
 vector atom, direction(atom), j, x(atom), y(atom) 'break the collision
 Sprite show atom, x(atom), y(atom), 1
 
 ' If the simple bounce didn't work, try a random bounce
 Do While (sprite(t,atom) Or sprite(e,atom)) And j<10
   Do
     direction(atom) = Rnd*360
     vector atom, direction(atom), j, x(atom), y(atom)
     j = j + 1
   Loop Until x(atom)>=0 And x(atom)<=MM.HRES-sprite(w,atom) And y(atom)>=0 And y(atom)<=MM.VRES-sprite(h,atom)
   Sprite show atom, x(atom), y(atom), 1
 Loop
 
 ' If that didn't work then place the atom randomly (avoiding boxes)
 Do While (sprite(t,atom) Or sprite(e,atom))
   direction(atom) = Rnd*360
   Do
     x(atom) = Rnd*(MM.HRES-sprite(w,atom))
     y(atom) = Rnd*(MM.VRES-sprite(h,atom))
   Loop Until Not inside_box(x(atom), y(atom), sprite(w,atom))
   vector atom, direction(atom), 0, x(atom), y(atom)
   Sprite show atom, x(atom), y(atom), 1
 Loop
End Sub

Edited 2026-01-21 03:29 by matherp
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 05:31pm 20 Jan 2026
Copy link to clipboard 
Print this post

Performance is the same I am printing too much debug info. But the recalculation of boundaries is ok.
Edited 2026-01-21 03:37 by ksinger
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10965
Posted: 05:34pm 20 Jan 2026
Copy link to clipboard 
Print this post

  Quote  So at least I can test the performance and the info is that it is now too slow.

It only calculates them once, the first time sprite(b is used for that sprite. This will have no more performance impact than pre-calculating them
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 05:40pm 20 Jan 2026
Copy link to clipboard 
Print this post

yeah, additionally thats right.

but something is seriously wrong with the memory management.
I tried malloc and free but that was also leading to a problem.
I tried GetSystemMemory, GetTempMemory,...

It seems that all these functions make trouble when they are used too late.
By the way I used your recommended gcc settings and also patched gpio.c.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10965
Posted: 05:47pm 20 Jan 2026
Copy link to clipboard 
Print this post

Have you run my code just posted? your demo has lots of optimisations that could be done. There is also a pause statement in the demo, remove that and he runs like Usain Boult.
For the avoidance of doubt, there is guaranteed nothing wrong with the memory management. It is robust and hasn't been changed recently.
Edited 2026-01-21 05:45 by matherp
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 07:52am 21 Jan 2026
Copy link to clipboard 
Print this post

The Pause was just there for debugging of course. I will have a close look at your basic code. And thanks for the nice doc also to sprites. the students will love it. We had a problem with the pong clone for quantum blocks but now with the sprite(b,.. we can use also non-sprite objects so we should be able to simulate the behaviour of photons. Great work!

I used GetMemory and the FreeMemory for the bounds... array inside fun_sprite and could not get it to work. It was always leaking memory allocations or leading to display probkems. But I was on 6.01.0. I can send you the firmware and the corresponding draw.c. Maybe you can tell me what I did wrong.

so in the fun_sprite I do:
   static short *boundsleft=NULL;
   static short *boundsright=NULL;
   static short *boundstop=NULL;
   static short *boundsbottom=NULL;
   getspritebounds(bnbr,boundsleft,boundsright,boundstop,boundsbottom);

so static for just once initializing then in getspritebound I do:
   if(!boundsleft) boundsleft= (short *)GetMemory(h*sizeof(short));
   if(!boundsright) boundsright= (short *)GetMemory(h*sizeof(short));
   if(!boundstop) boundstop= (short *)GetMemory(w*sizeof(short));
   if(!boundsbottom) boundsbottom= (short *)GetMemory(w*sizeof(short));

so only alloc it when it is null. Should therefore just happen once. And all sprites have same dimensions.
I never free it and I still get a heap memory leak during the demo.bas (mario clone thing). so it runs for about 100 loops and then I get heap error.

have a try. (attached is the firmware and the Draw.c and draw.h I use the git sources otherwise).

And if you free things then you get display problems.

I also used the patched gpio.c and gcc13.1 as recommended. By the way it does not work with newer gcc versions. which is kind of weird. Do you know why?
6.01withspritebbutleak.zip
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 07:56am 21 Jan 2026
Copy link to clipboard 
Print this post

The pico uses multi cores? Maybe it is a race condition. Oh and I play the mod file from Jeroen Tel (https://modarchive.org/index.php?request=view_by_moduleid&query=210142). Love the guy he made already great tunes on the sid(c64). Maybe it is caused by the audio codec I have seen that they use getmemory also. And I have not seen any mutexes and use of critical sections in the memory allocation code.
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 08:01am 21 Jan 2026
Copy link to clipboard 
Print this post

Actually it was another tune I converted the https://api.modarchive.org/downloads.php?moduleid=67508#dtn-super_mario_brothers.xm file to mod:
dtn-super_mario_brothers.zip

that together with the basic source should reproduce the leak.
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 08:12am 21 Jan 2026
Copy link to clipboard 
Print this post

But with disabled sound it still happens. Here for reference the demo file with sound disabled. it prints out the free memory.
demo4.zip
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 08:16am 21 Jan 2026
Copy link to clipboard 
Print this post

I also realize that it it goes down from 160k to 100k and then jumps to 980k. So maybe it is some integer overflow problem. but it should not drop in the first place.
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 08:18am 21 Jan 2026
Copy link to clipboard 
Print this post

And I am using picomiteHDMIUSB on the pico2 without wifi.
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10965
Posted: 08:33am 21 Jan 2026
Copy link to clipboard 
Print this post

You have a bug in your build. Use my posted RC8 version and it runs forever with memory usage absolutely stable with or without modfile playback. Tested on RP2350 HDMIUSB and RP2040 VGA. Note the on the USB version there is significant overhead caused by all the print statements running at 115200. Use OPTION CONSOLE SCREEN.
If you want it to run fast, cache all the sprite(b commands at the top of the loop
x15%=sprite(b,(n\3) mode 5+1,3)

Edited 2026-01-21 18:43 by matherp
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 10:29am 21 Jan 2026
Copy link to clipboard 
Print this post

Thanks for the info. Oh and the leaking is caused by  getspritebounds(bnbr,boundsleft,boundsright,boundstop,boundsbottom)
and it should be
getspritebounds(bnbr,&boundsleft,&boundsright,&boundstop,&boundsbottom);
with short ** parameters.

Great. So I also assume that the second CPU never uses memory allocation to avoid race conditions.
Edited 2026-01-21 20:29 by ksinger
 
ksinger
Regular Member

Joined: 06/01/2026
Location: United Kingdom
Posts: 70
Posted: 10:30am 21 Jan 2026
Copy link to clipboard 
Print this post

OPTION CONSOLE SCREEN
that's a good one
 
     Page 12 of 14    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2026