gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Audio > Strange MOD Header Problem

#14685 - Krakken - Sun Jan 11, 2004 9:33 am

Hey,

I've just started making myself a MOD player but have come accross a very strange problem. I'll try to explain it as best I can.

I am trying to load the header of the MOD file into a struct I have made with the help of a file format guide. I have checked and rechecked the guide and all seems well with the header.

The relevant code I am using is below:

Code:

extern const char RES_MOD[];


typedef struct _xSample {
    char    cName[22];
    ushort  iLength;
    char    cFineTune;
    uchar   cVolume;
    uint    wOffset;
} xSample, *pxSample;   

typedef struct _xMOD {
    char    cTitle[20];
    xSample xSampleList[15];
    char    cPatternCount;
    char    cEndPos;
    char    cPatternTable[128];
} xMOD, *pxMOD;   


xMOD *xmFile = RES_MOD;


The first instrument "appears" to load okay with the data shown as:


NAME: Dream Guitar 1
LENGTH: 16421
FINETUNE: 0
VOLUME: 64
OFFSET: 1917112588


The problem I have is when loading each subsequent sample. For example the second and third samples load as:


NAME: eam Guitar 2 (Should Be: "Dream Guitar 2")
LENGTH: 16384
FINETUNE: 0
VOLUME: 0
OFFSET: 1394625862



NAME: lap Bass (Should Be: "FM Slap Bass")
LENGTH: 0
FINETUNE: 0
VOLUME: 1
OFFSET: 1953391980


As you may have noticed it seems to cut 2 bytes off of each sample struct. To combat this I tried taking away 2 bytes from the sample struct. This produced results where it did the complete opposite and added 2 bytes to each sample struct.

I have no idea why it won't work. Can anyone help? This is what i'm following:
http://www.wotsit.org/search.asp?page=5&s=music (2nd File Down)

Thanks, Nat.

#14690 - poslundc - Sun Jan 11, 2004 3:01 pm

How are you "loading" them into the structure? I have sometimes run into very similar problems when trying to directly load arrays of structures that included strings.

Make sure that your strings are padded to the necessary byte length in your data file. If that fails, try removing the names from your structure and data (which is what I eventually did, and it got it working).

Dan.

#14691 - Krakken - Sun Jan 11, 2004 3:29 pm

Hi,

Thanks for your reply. I talked with JSensebe on the IRC channel and he explained to me what it almost certainly is.

You see, the ARM processor, for efficiency, cannot read a variable that is not aligned to an boundry offset of its own size.


A "word" (4 bytes) can only be placed at memory positions with an offset of a multiple of 4: 0, 4, 8, 12, 16 etc.

A "halfword" (2 bytes) is the same but can only be offset on a multiple of 2: 0, 2, 4, 6, 8 etc.


If you look closely at my sample struct:
Code:

typedef struct _xSample {
    char    cName[22];
    hword   iLength;
    char    cFineTune;
    uchar   cVolume;
    word   wOffset;
} xSample, *pxSample;

You will see that cName is at byte 0, iLength is at byte 22, cFineTune - byte 24, cVolume - byte 25, wOffset - byte *26* and the size of the struct is *30* bytes.

The compiler, so that the struct is compatible with the ARM processor, will offset wOffset to byte 28 (therefore making the total size of the struct, 32 bytes) so that it lies on the "word" boundary (0, 4, 8, 12, 16, 20, 24, 28) as the processor cannot read byte 26 to get a word value.

The first thing I tried, was to split wOffset into two "halfwords" wOffset_L and wOffset_H so that both would lie on the "halfword" boundary (0, 2, 4, ... 22, 24, 26, 28). Unfortunately I overlooked the fact that the struct was only 30 bytes in total. The compiler, again, would be padding that to 32 bytes so that the data could be read by the processor.

You said you took out the names from the file and struct and it worked. That would have set the struct to (30 - 22) 8 bytes which is compatible with the processor.

Hope this explains it,
Nat.

#14692 - poslundc - Sun Jan 11, 2004 3:39 pm

Yeah, mine wasn't an issue with struct padding; it had something to do with the way the compiler was assigning constant strings to the structures. The struct I had already took alignment into account.

Dan.

#15597 - SmileyDude - Sun Jan 25, 2004 11:43 pm

Whenever you find that GCC is sticking in extra padding when you don't want it, you can always put a #pragma pack(0) before the struct declaration, and a #pragma pack(4) at the end to reset it back to normal. The ARM doesn't like mis-alligned data, but GCC can generate code to access the mis-alligned data. This is a bit slower, but when you need to read/write to a specific external format, it's probably the best way to go.
_________________
dennis