swiDecompressLZSSVram does not return length of decompressed data, as documentation suggests
Bug Report
What's the issue you encountered?
The libnds documentation of swiDecompressLZSSVram states that it returns: "The length of the decompressed data, or a signed errorcode from the Open/Close functions."
Yet the implementation does not return any such value. It must have once upon a time (I relied on it in AmplituDS way back). According to gbatek, the swi-call has no return value. So I suppose the options are to either adjust this documentation or to obtain the length of the compressed data (e.g., from the header of the compressed data: (((uint32)source)) >> 8). Other such bios calls likely need a similar treatment.
Environment?
Run on an NDS Phat
I've looked at the DS and DSi mode BIOSes, and the functions seem to behave as documented. That is, >=0 on success (decompressed byte size) or <0 on failure (error code). Amusingly enough, gbatek seems to be wrong here. Are you sure you don't have an issue in your code?
I am fairly confident my code is correct. I am updating my source code of the game Amplituds to work with a newer (though not yet 2.0) version of libnds. The part of loading in sprite graphics, unchanged in that migration, for some reason stopped working other than for the first piece of sprite gfx loaded in at offset 0. I looked into the issue and noticed that the return values for this swi call are now gigantic numbers rather than decompressed file sizes, so the offsets for loading in subsequent compressed sprite gfx were no longer adequate for loading in gfx neatly besides each other in vram.
I do not see any changes really in the libnds code concerning the actual swi call, judging by the git history, so how the workings could change that significantly (with the exact same compressed sprite gfx as before by the way; I did not rerun any compression process) is something I do not comprehend. Once I moved on to using the header information instead of the swi call return value for determining the offsets in loading each piece of sprite gfx, all worked as expected again. In short, it's a mystery to me. Also, I tested it both on Phat DS and Desmume, with same results.
Just to be complete, my code for loading a compressed file into VRAM was:
// BIOS Function helper
int getSize(uint8 * source, uint16 * dest, uint32 r2) {
u32 size = *((u32*)source) >> 8;
return (size<<8) | 16;
}
// BIOS Function helper
uint8 readByte(uint8 * source) {
return *source++;
}
int decompressToVRAM(void* dest, enum FileType type, char *name) {
int result;
void *buffer;
FILE *fp;
int size;
TDecompressionStream decStream = {getSize, NULL, readByte};
fp = openFile(type, name);
fseek(fp, 0, SEEK_END);
size = ftell(fp);
rewind(fp);
buffer = malloc(size);
fread(buffer, 1, size, fp);
closeFile(fp);
result = swiDecompressLZSSVram(buffer, dest, 0, &decStream);
free(buffer);
return result;
}
which erroneously returned 34198976 for the first file (and similar values for the other files), and I now changed the last few lines to:
swiDecompressLZSSVram(buffer, dest, 0, &decStream);
result = (*((uint32*)buffer)) >> 8; // taken from header
free(buffer);
return result;
}
which then returns 512. A bit more reasonable. :) As I said, the same code and files used to work with an older 1.x version of libnds.