|
Forum Index : Microcontroller and PC projects : PicoMite V6.02.00 release candidates - Structured types
| Author | Message | ||||
| ksinger Regular Member Joined: 06/01/2026 Location: United KingdomPosts: 70 |
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 KingdomPosts: 10965 |
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 KingdomPosts: 70 |
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 StatesPosts: 502 |
Where can I get Flashnuke? They call me Shai-Hulud (The maker) |
||||
| ksinger Regular Member Joined: 06/01/2026 Location: United KingdomPosts: 70 |
https://datasheets.raspberrypi.com/soft/flash_nuke.uf2 |
||||
| ksinger Regular Member Joined: 06/01/2026 Location: United KingdomPosts: 70 |
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 KingdomPosts: 10965 |
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 KingdomPosts: 70 |
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 KingdomPosts: 10965 |
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 KingdomPosts: 70 |
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 KingdomPosts: 10965 |
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 KingdomPosts: 70 |
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 KingdomPosts: 70 |
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 KingdomPosts: 70 |
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 KingdomPosts: 70 |
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 KingdomPosts: 70 |
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 KingdomPosts: 70 |
And I am using picomiteHDMIUSB on the pico2 without wifi. |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 10965 |
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 KingdomPosts: 70 |
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 KingdomPosts: 70 |
OPTION CONSOLE SCREEN that's a good one |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2026 |