Closed GoogleCodeExporter closed 9 years ago
Original comment by justin.h...@gmail.com
on 30 Apr 2009 at 3:02
Original comment by justin.h...@gmail.com
on 30 Apr 2009 at 3:02
Started work on buffer thread framework.
Original comment by justin.h...@gmail.com
on 1 May 2009 at 4:07
Added buffer code in r73 and r74, currently untested.
To turn on buffering, uncomment #define BUFFER_TEST 1 in main.c
Original comment by justin.h...@gmail.com
on 1 May 2009 at 5:58
Should be fixed as of r77... don't own nearly enough games to test; but works
fine
with my collection of 40 or so.
Anyone with uber games want to test?
Original comment by justin.h...@gmail.com
on 1 May 2009 at 11:31
ill test with a 120+ collection and report in a few
Original comment by jeanrmar...@gmail.com
on 2 May 2009 at 12:22
Buffering needs a bit more work from r77; (in r77 buffering was set to not
clear the
buffer; but keep growing it)
Next release will clean up the buffer and keep a fixed rendering window for
covers.
Original comment by justin.h...@gmail.com
on 2 May 2009 at 12:30
just tested, out of 4 times, 2 code dumped, and the other 2 only rendered about
45
covers out of the 128 I have, seems a bit unstable...
Hope the feedback helps
Original comment by jeanrmar...@gmail.com
on 2 May 2009 at 12:34
HELP!! I'm stumped and tired... :)
Problem occurs when i call BUFFER_RemoveCover(index) in main.c (Not right away,
but eventually leads to crash... which is mind numbing). The crash ends up
occuring in pngu.c in PNGU_DecodeTo4x4RGBA8. My guess is when i call free() on
the texture data in buffer.c, something isn't synced; b/c the texture doesn't
really seem to be deleted yet it is somehow invalid; (Since its causing PNGU to
crash).
Again... any help is appreciated.
Original comment by justin.h...@gmail.com
on 5 May 2009 at 5:45
AgentX had a good suggestion:
Could it be something simple like having to call a function to purge the texture
data/clear the memory or something?
I am calling free, but perhaps i need to do a deeper flush within GRRLIB when
this
happens...
Does anyone know what GX_Flush does??
I wonder if i have to use that once a texture is deleted...
Original comment by justin.h...@gmail.com
on 5 May 2009 at 3:07
On further thought; I wonder If i'm deleting the texture when its still in the
gx
draw queue or something...
maybe I need to do a couple of things:
(Not sure what this does...)
GX_InvalidateTexAll();
Most importantly probably; force the BUFFER_WINDOW size to be the same size as
the
DRAW_WINDOW, so I only draw covers currently buffered.
(Or better yet; make the DRAW_WINDOW smaller than the BUFFER_Window)
If someone is bored; please try these out for me :) I wont have time to code
for a
couple days
Original comment by justin.h...@gmail.com
on 5 May 2009 at 3:16
Hmmm I have a thought... All of the covers work perefectly if i leave these
lines
out of the makefile:
--section-start,.init=0x80a00100
But games don't boot...
What if i create a bootloader that i compile into the executable and start that
when
i want to boot a game. It will take in a few args, "Game id, region, ocarina,
etc..." and just boot the game.
Original comment by justin.h...@gmail.com
on 5 May 2009 at 9:09
I just wrote a boot loader that works very well boot backups when passed
parameters.... now to get it loading from the other dol :)
Original comment by justin.h...@gmail.com
on 5 May 2009 at 9:55
http://code.google.com/p/loadmii
yay
Original comment by justin.h...@gmail.com
on 5 May 2009 at 10:14
I think the answer may be simpler - if you get a request after the remove flag
has
been set then you will reload the texture (without calling free). Then you
will
remove it freeing the newly loaded texture. The ready flag is set and there is
no
texture.
Original comment by blackbir...@gmail.com
on 5 May 2009 at 10:28
Please fix the code and send me a patch to earn 5$
:)
Original comment by justin.h...@gmail.com
on 5 May 2009 at 10:42
simplist looks like:
/*Handle Load Requests*/
pthread_mutex_lock(&queue_mutex);
b = _cq.request[i] && !_cg.removed[i];
pthread_mutex_unlock(&queue_mutex);
I didn't look to see if the other flags cause an issue but that should stop a
ready
when it has been sceduled for removal. BTW I haven't written in C in about 10
years
so forgive any missing (s
Original comment by blackbir...@gmail.com
on 5 May 2009 at 11:01
changing
if(_texture_data[i].data != 0)
free(_texture_data[i].data);
_texture_data[i].data = 0;
pthread_mutex_unlock(&buffer_mutex[i]);
pthread_mutex_lock(&queue_mutex);
_cq.remove[i] = false;
_cq.ready[i] = false;
_cq.request[i] = false;
pthread_mutex_unlock(&queue_mutex);
to
if(_texture_data[i].data != 0)
free(_texture_data[i].data);
_texture_data[i].data = 0;
pthread_mutex_unlock(&buffer_mutex[i]);
pthread_mutex_lock(&queue_mutex);
_cq.remove[i] = false;
_cq.ready[i] = false;
pthread_mutex_unlock(&queue_mutex);
should allow a rerequest of a removed without killing the request (I assume
that
will show as missing images)
Original comment by blackbir...@gmail.com
on 5 May 2009 at 11:09
if I'm right then buy yourself a pint with the $5
Original comment by blackbir...@gmail.com
on 5 May 2009 at 11:16
And then the penny dropped...
void BUFFER_InitBuffer(int thread_count)
{
int i = 0;
/*Initialize Mutexs*/
pthread_mutex_init(&count_mutex, 0);
pthread_mutex_init(&queue_mutex, 0);
pthread_mutex_init(&quit_mutex, 0);
for(i = 0; i < MAX_BUFFERED_COVERS; i++)
pthread_mutex_init(&buffer_mutex[i], 0);
BUFFER_ClearCovers();
pthread_mutex_lock(&quit_mutex);
_requestQuit = false;
pthread_mutex_unlock(&quit_mutex);
for(i = 0; i < thread_count; i++)
{
if(i < MAX_THREADS)
pthread_create(&thread[i], 0, process, (void *)i);
}
}
should be
void BUFFER_InitBuffer(int thread_count)
{
int i = 0;
/*Initialize Mutexs*/
pthread_mutex_init(&count_mutex, 0);
pthread_mutex_init(&queue_mutex, 0);
pthread_mutex_init(&quit_mutex, 0);
for(i = 0; i < MAX_BUFFERED_COVERS; i++)
{
pthread_mutex_init(&buffer_mutex[i], 0);
_texture_data[i].data=0;
}
BUFFER_ClearCovers();
pthread_mutex_lock(&quit_mutex);
_requestQuit = false;
pthread_mutex_unlock(&quit_mutex);
for(i = 0; i < thread_count; i++)
{
if(i < MAX_THREADS)
pthread_create(&thread[i], 0, process, (void *)i);
}
}
as _texturedata never gets initialised and C doesn't 0 it. This should remove
garbage images as well and solve crashes in the png lib.
I woke me up as I couldn't figure out how a rare race situation could cause a
common
problem.
Original comment by blackbir...@gmail.com
on 6 May 2009 at 2:19
I couldn't get this to work in my current build r139, but I'm sure I'm not
implementing it right. Hopefully NullKill will have better luck...
Original comment by afou...@gmail.com
on 6 May 2009 at 4:48
I haven't tried it yet (about to); but looking over his suggested change im not
sure
it will make a difference
Original comment by justin.h...@gmail.com
on 6 May 2009 at 5:04
Yup; still crashes just as hard in the same spot. I Do appreciate the help
though...
keep the ideas coming!
Original comment by justin.h...@gmail.com
on 6 May 2009 at 5:06
some of the memory leaks fixed. It takes much longer to crash now :-)
#include "buffer.h"
#include "core/disc.h"
#include "core/fat.h"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define USBLOADER_PATH "SD:/usb-loader"
extern const u8 back_cover_png[];
#include <unistd.h>
void Sleep(unsigned long milliseconds)
{
if (milliseconds<1000)
usleep(milliseconds*1000);
else
sleep(milliseconds/1000);
}
void BUFFER_InitBuffer(int thread_count)
{
int i = 0;
/*Initialize Mutexs*/
pthread_mutex_init(&count_mutex, 0);
pthread_mutex_init(&queue_mutex, 0);
pthread_mutex_init(&quit_mutex, 0);
for(i = 0; i < MAX_BUFFERED_COVERS; i++)
{
pthread_mutex_init(&buffer_mutex[i], 0);
_texture_data[i].data=0;
}
BUFFER_ClearCovers();
pthread_mutex_lock(&quit_mutex);
_requestQuit = false;
pthread_mutex_unlock(&quit_mutex);
for(i = 0; i < thread_count; i++)
{
if(i < MAX_THREADS)
pthread_create(&thread[i], 0, process, (void *)i);
}
}
void BUFFER_RequestCover(int index, struct discHdr *header)
{
//int i;
if(index < MAX_BUFFERED_COVERS)
{
pthread_mutex_lock(&queue_mutex);
_cq.request[index] = true;
//for(i = 0; i < 6; i++)
//{
_cq.requestId[index] = header;
//}
pthread_mutex_unlock(&queue_mutex);
}
}
bool BUFFER_IsCoverReady(int index)
{
bool retval = false;
if(index < MAX_BUFFERED_COVERS)
{
pthread_mutex_lock(&queue_mutex);
retval = _cq.ready[index];
pthread_mutex_unlock(&queue_mutex);
}
return retval;
}
bool BUFFER_IsCoverQueued(int index)
{
bool retval = false;
if(index < MAX_BUFFERED_COVERS)
{
pthread_mutex_lock(&queue_mutex);
retval = _cq.request[index];
pthread_mutex_unlock(&queue_mutex);
}
return retval;
}
void BUFFER_RemoveCover(int index)
{
if(index < MAX_BUFFERED_COVERS)
{
pthread_mutex_lock(&queue_mutex);
_cq.ready[index] = false;
_cq.request[index] = false;
_cq.remove[index] = true;
pthread_mutex_unlock(&queue_mutex);
}
}
bool BUFFER_LockTexture(int index, GRRLIB_texImg* tex)
{
if(index >= MAX_BUFFERED_COVERS || index < 0)
return false;
pthread_mutex_lock(&queue_mutex);
if(_cq.ready[index])
{
pthread_mutex_unlock(&queue_mutex);
pthread_mutex_lock(&buffer_mutex[index]);
tex = &_texture_data[index];
if(tex->data == 0)
{
pthread_mutex_unlock(&buffer_mutex[index]);
return false;
}
else
{
return true;
}
}
else
{
pthread_mutex_unlock(&queue_mutex);
}
return false;
}
void BUFFER_ReleaseTexture(int index)
{
if(index < MAX_BUFFERED_COVERS)
pthread_mutex_unlock(&buffer_mutex[index]);
}
void BUFFER_KillBuffer()
{
pthread_mutex_lock(&quit_mutex);
_requestQuit = true;
pthread_mutex_unlock(&quit_mutex);
}
void BUFFER_ClearCovers()
{
int i;
pthread_mutex_lock(&count_mutex);
_cover_count = 0;
pthread_mutex_unlock(&count_mutex);
pthread_mutex_lock(&queue_mutex);
for(i = 0; i < MAX_BUFFERED_COVERS; i++)
{
_cq.ready[i] = false;
_cq.request[i] = false;
_cq.remove[i] = false;
pthread_mutex_lock(&buffer_mutex[i]);
if(_texture_data[i].data)
free(_texture_data[i].data);
pthread_mutex_unlock(&buffer_mutex[i]);
}
pthread_mutex_unlock(&queue_mutex);
}
void* process(void *arg)
{
int i = 0;
bool b = false;
/*Main Buffering Thread*/
//Fat_MountSDHC();
while(1)
{
for(i = 0; i < MAX_BUFFERED_COVERS; i++)
{
/*Handle Load Requests*/
pthread_mutex_lock(&queue_mutex);
b = _cq.request[i] && !_cq.remove[i];
pthread_mutex_unlock(&queue_mutex);
if(b)
{
pthread_mutex_lock(&buffer_mutex[i]);
/*Definitely dont need to load the same texture
twice*/
if(!(_texture_data[i].data))
{
void *imgData=0;
char filepath[128];
s32 ret;
sprintf(filepath, USBLOADER_PATH "/covers/%
s.png", _cq.requestId[i]->id);
ret = Fat_ReadFile(filepath, &imgData);
if (ret > 0) {
_texture_data[i] = GRRLIB_LoadTexture
((const unsigned char*)imgData);
free(imgData);
pthread_mutex_lock(&queue_mutex);
_cq.ready[i] = true;
pthread_mutex_unlock(&queue_mutex);
}
else
{
pthread_mutex_lock(&queue_mutex);
_cq.ready[i] = false;
pthread_mutex_unlock(&queue_mutex);
pthread_mutex_lock(&buffer_mutex[i]);
if(_texture_data[i].data != 0)
free(_texture_data[i].data);
_texture_data[i].data = 0;
pthread_mutex_unlock(&buffer_mutex
[i]);
}
}
pthread_mutex_unlock(&buffer_mutex[i]);
}
/*Handle Remove Requests*/
pthread_mutex_lock(&queue_mutex);
_cq.request[i] = false;
b = _cq.remove[i];
pthread_mutex_unlock(&queue_mutex);
if(b)
{
pthread_mutex_lock(&buffer_mutex[i]);
if(_texture_data[i].data != 0)
free(_texture_data[i].data);
_texture_data[i].data = 0;
pthread_mutex_unlock(&buffer_mutex[i]);
pthread_mutex_lock(&queue_mutex);
_cq.remove[i] = false;
_cq.ready[i] = false;
pthread_mutex_unlock(&queue_mutex);
}
Sleep(1);
}
pthread_mutex_lock(&quit_mutex);
if(_requestQuit)
{
pthread_mutex_unlock(&quit_mutex);
int m = 0;
/*Initialize Mutexs*/
pthread_mutex_destroy(&count_mutex);
pthread_mutex_destroy(&queue_mutex);
pthread_mutex_destroy(&quit_mutex);
for(m = 0; m < MAX_BUFFERED_COVERS; m++)
pthread_mutex_destroy(&buffer_mutex[m]);
return 0;
}
pthread_mutex_unlock(&quit_mutex);
}
}
Original comment by blackbir...@gmail.com
on 6 May 2009 at 8:53
Tested changes; some improvements though still crashes :)
nice work though
Original comment by justin.h...@gmail.com
on 6 May 2009 at 10:05
Finished. Still crashes but its correct now.
#include "buffer.h"
#include "core/disc.h"
#include "core/fat.h"
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define USBLOADER_PATH "SD:/usb-loader"
extern const u8 back_cover_png[];
#include <unistd.h>
void Sleep(unsigned long milliseconds)
{
if (milliseconds<1000)
usleep(milliseconds*1000);
else
sleep(milliseconds/1000);
}
void BUFFER_InitBuffer(int thread_count)
{
int i = 0;
/*Initialize Mutexs*/
pthread_mutex_init(&count_mutex, 0);
pthread_mutex_init(&queue_mutex, 0);
pthread_mutex_init(&quit_mutex, 0);
for(i = 0; i < MAX_BUFFERED_COVERS; i++)
{
pthread_mutex_init(&buffer_mutex[i], 0);
_texture_data[i].data=0;
}
BUFFER_ClearCovers();
pthread_mutex_lock(&quit_mutex);
_requestQuit = false;
pthread_mutex_unlock(&quit_mutex);
for(i = 0; i < thread_count; i++)
{
if(i < MAX_THREADS)
pthread_create(&thread[i], 0, process, (void *)i);
}
}
void BUFFER_RequestCover(int index, struct discHdr *header)
{
//int i;
if(index < MAX_BUFFERED_COVERS)
{
pthread_mutex_lock(&queue_mutex);
_cq.request[index] = true;
_cq.requestId[index] = header;
pthread_mutex_unlock(&queue_mutex);
}
}
bool BUFFER_IsCoverReady(int index)
{
bool retval = false;
if(index < MAX_BUFFERED_COVERS)
{
pthread_mutex_lock(&queue_mutex);
retval = _cq.ready[index];
pthread_mutex_unlock(&queue_mutex);
}
return retval;
}
bool BUFFER_IsCoverQueued(int index)
{
bool retval = false;
if(index < MAX_BUFFERED_COVERS)
{
pthread_mutex_lock(&queue_mutex);
retval = _cq.request[index];
pthread_mutex_unlock(&queue_mutex);
}
return retval;
}
void BUFFER_RemoveCover(int index)
{
if(index < MAX_BUFFERED_COVERS)
{
pthread_mutex_lock(&queue_mutex);
_cq.ready[index] = false;
_cq.request[index] = false;
_cq.remove[index] = true;
pthread_mutex_unlock(&queue_mutex);
}
}
void BUFFER_KillBuffer()
{
pthread_mutex_lock(&quit_mutex);
_requestQuit = true;
pthread_mutex_unlock(&quit_mutex);
}
void BUFFER_ClearCovers()
{
int i;
pthread_mutex_lock(&queue_mutex);
for(i = 0; i < MAX_BUFFERED_COVERS; i++)
{
_cq.ready[i] = false;
_cq.request[i] = false;
_cq.remove[i] = false;
pthread_mutex_lock(&buffer_mutex[i]);
if(_texture_data[i].data)
{
free(_texture_data[i].data);
_texture_data[i].data=0;
}
pthread_mutex_unlock(&buffer_mutex[i]);
}
pthread_mutex_unlock(&queue_mutex);
}
void* process(void *arg)
{
int i = 0;
bool b = false;
/*Main Buffering Thread*/
//Fat_MountSDHC();
while(1)
{
for(i = 0; i < MAX_BUFFERED_COVERS; i++)
{
/*Handle Load Requests*/
pthread_mutex_lock(&queue_mutex);
b = _cq.request[i] && !_cq.remove[i]&&!_cq.ready[i];
if (b) _cq.request[i]=false;
pthread_mutex_unlock(&queue_mutex);
if(b)
{
pthread_mutex_lock(&buffer_mutex[i]);
/*Definitely dont need to load the same texture
twice*/
if(!(_texture_data[i].data))
{
void *imgData=0;
char filepath[128];
s32 ret;
sprintf(filepath, USBLOADER_PATH "/covers/%
s.png", _cq.requestId[i]->id);
ret = Fat_ReadFile(filepath, &imgData);
if (ret > 0) {
_texture_data[i] = GRRLIB_LoadTexture
((const unsigned char*)imgData);
free(imgData);
pthread_mutex_lock(&queue_mutex);
_cq.ready[i] = true;
pthread_mutex_unlock(&queue_mutex);
}
else
{
pthread_mutex_lock(&queue_mutex);
_cq.ready[i] = false;
pthread_mutex_unlock(&queue_mutex);
if(_texture_data[i].data != 0)
free(_texture_data[i].data);
_texture_data[i].data = 0;
}
}
else
{
BUFFER_ClearCovers();
//it shouldn't get here but is!!!!!!!!!
}
pthread_mutex_unlock(&buffer_mutex[i]);
}
/*Handle Remove Requests*/
pthread_mutex_lock(&queue_mutex);
//_cq.request[i] = false;
b = _cq.remove[i];
if(b)
{
pthread_mutex_lock(&buffer_mutex[i]);
if(_texture_data[i].data != 0)
free(_texture_data[i].data);
_texture_data[i].data = 0;
pthread_mutex_unlock(&buffer_mutex[i]);
_cq.request[i] = false;
_cq.remove[i] = false;
_cq.ready[i] = false;
}
pthread_mutex_unlock(&queue_mutex);
Sleep(1);
}
pthread_mutex_lock(&quit_mutex);
if(_requestQuit)
{
pthread_mutex_unlock(&quit_mutex);
int m = 0;
/*Initialize Mutexs*/
pthread_mutex_destroy(&count_mutex);
pthread_mutex_destroy(&queue_mutex);
pthread_mutex_destroy(&quit_mutex);
for(m = 0; m < MAX_BUFFERED_COVERS; m++)
pthread_mutex_destroy(&buffer_mutex[m]);
return 0;
}
pthread_mutex_unlock(&quit_mutex);
}
}
Original comment by blackbir...@gmail.com
on 6 May 2009 at 10:46
The crashes are caused by png which aren't 160x225. To test replace
/**
* Load a texture from a buffer.
* @param my_png the PNG buffer to load.
* @return A GRRLIB_texImg structure filled with PNG informations.
*/
GRRLIB_texImg GRRLIB_LoadTexturePNG(const unsigned char my_png[]) {
PNGUPROP imgProp;
IMGCTX ctx;
GRRLIB_texImg my_texture;
ctx = PNGU_SelectImageFromBuffer(my_png);
PNGU_GetImageProperties (ctx, &imgProp);
if (imgProp.imgWidth * imgProp.imgHeight * 4!=160*225*4)
{
my_texture.data = memalign (32, imgProp.imgWidth * imgProp.imgHeight * 4);
PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight,
my_texture.data, 255);
}
else
{
my_texture.data=0;
}
PNGU_ReleaseImageContext (ctx);
if (imgProp.imgWidth * imgProp.imgHeight * 4!=160*225*4)
{
my_texture.w = imgProp.imgWidth;
my_texture.h = imgProp.imgHeight;
GRRLIB_FlushTex(my_texture);
}
return my_texture;
}
in GRRLib.
I should have fixed usb retries first (it doesn't start well)
Original comment by blackbir...@gmail.com
on 6 May 2009 at 10:49
woops
else
{
BUFFER_ClearCovers();
//it shouldn't get here but is!!!!!!!!!
}
needs taken away from buffer.c
had that in for testing
Original comment by blackbir...@gmail.com
on 6 May 2009 at 10:56
It just bloody dumped again with new images. Bugger. Takes a while though and
no
corruption either.
Original comment by blackbir...@gmail.com
on 6 May 2009 at 11:08
No more code dumps or corruption. I think woohoo is the word. BTW Justin, the
magic number is between 25 and 30 somewhere but it's bed time :-) and if you
mess
with the bit in main which calls BUFFER_RemoveCover and BUFFER_RequestCover to
do
all the removing first... In fact remove the cover in remove cover as well and
it
should be more responsive. I may get to it tomorrow.
Original comment by blackbir...@gmail.com
on 6 May 2009 at 11:39
Attachments:
Awesome! I'll test tonite.
Want me to add you to google code?
(BTW, if anyone else gets to this before me, please add it to svn)
Original comment by justin.h...@gmail.com
on 6 May 2009 at 11:43
Added you to google code so you can update with your fixes
Original comment by justin.h...@gmail.com
on 6 May 2009 at 11:44
Fixed, r158; thanks gc
Original comment by justin.h...@gmail.com
on 7 May 2009 at 5:14
Original issue reported on code.google.com by
justin.h...@gmail.com
on 30 Apr 2009 at 2:48