View Full Version : [C related] Structs, records, pointers...
Legolas
20-12-2006, 01:31 PM
I'm a bit in stuck... I need to convert following code to pascal:
#define OAM_SUB ((uint16*)0x07000400)
SpriteEntry OAMCopySub[128];
void updateOAM(void) {
unsigned int i;
for(i = 0; i < 128 * sizeof(SpriteEntry) / 4 ; i++)
{
((uint32*)OAM_SUB)[i] = ((uint32*)OAMCopySub)[i];
}
}
where SpriteEntry is a struct. OAM_SUB is translated as
const
OAM_SUB : puint16 = pointer($07000400);
The problem is that I can't figure a way to typecast hte array of record to OAM_SUB :scratch:
VilleK
20-12-2006, 01:48 PM
You can do something like this:
type
PInt32 = ^integer;
var
Data : array[0..10] of TMyRecord;
begin
PInt32(@Data)^ := 42;
end;
JernejL
20-12-2006, 01:55 PM
I'm a bit in stuck... I need to convert following code to pascal:
#define OAM_SUB ((uint16*)0x07000400)
SpriteEntry OAMCopySub[128];
void updateOAM(void) {
unsigned int i;
for(i = 0; i < 128 * sizeof(SpriteEntry) / 4 ; i++)
{
((uint32*)OAM_SUB)[i] = ((uint32*)OAMCopySub)[i];
}
}
where SpriteEntry is a struct. OAM_SUB is translated as
const
OAM_SUB : puint16 = pointer($07000400);
The problem is that I can't figure a way to typecast hte array of record to OAM_SUB :scratch:
declare stuff like this:
OAMCopySub = packed record or something
POAMCopySub = ^OAMCopySub; // a pointer variant
then use POAMCopySub in variable and set it to that pointer.
Legolas
20-12-2006, 02:20 PM
Thanks to all! :D
Now I'm @ work, so I'll try later :)
Legolas
20-12-2006, 08:08 PM
Ok, I have found a solution that works, or at least that compiles :roll:
I have tried this "monster":
for i := 0 to (128 * sizeof(SpriteEntry) div 4) - 1 do
pu32((@OAM_SUB[i])^) := pu32((@OAMCopySub[i])^);
As I have said before, it compiles, though it does not work as expected, because I get corrupted sprites. Hopefully it should be a wrong (or missing) typecast somewhere...
Bug hunting time :rambo:
JernejL
21-12-2006, 12:22 AM
pointer wrestling in C is bad enough, translating such code is one of worst tasks you can get, good luck :/
Setharian
21-12-2006, 05:50 AM
I'm not familiar with GBA (?) types, so I'll use the regular Delphi ones....
var
OAMCopySub: array[0..127] of SpriteEntry;
...
procedure UpdateOAM;
type
PLongs ^TLongs;
TLongs = array[0..MAXWORD-1] of Longword;
begin
for i := 0 to (128 * SizeOf(SpriteEntry) div SizeOf(Longword)) -1 do
begin
PLongs(OAM_SUB)^[i] := PLongs(@OAMCopySub)^[i];
end;
end;
if pu32 is ^Longword, then u32 should be a Longword and thus all you have to do is replace Longword by u32 ;)
on the other hand if you have a "Move" procedure at your disposal you could as well use it.....
Move(OAMCopySub, OAM_SUB^, SizeOf(OAMCopySub));
I think this is the easiest solution if it can be done...
Legolas
21-12-2006, 01:08 PM
Yes, in fact it is NDS code :mrgreen:
Move could be a solution, but it works only on Dualis emulator; on real hardware the memory is not copied at all. To tell short, I have decided to replace this loop by a dma copy, that takes care to copy the right amount of bytes at time.
dmaCopy(@OAMCopySub, OAM_SUB, sizeof(OAMCopySub));
Legolas
11-01-2007, 08:24 PM
I'm resuming this old thread because I need some other help :P
Well, I have converted a struct to pascal but I have some alignment problems. The original code is this:
typedef struct sTransferRegion {
uint32 heartbeat;
int16 touchX, touchY;
int16 touchXpx, touchYpx;
int16 touchZ1, touchZ2;
uint16 tdiode1, tdiode2;
uint32 temperature;
uint16 buttons;
union {
uint8 curtime[8];
struct {
u8 rtc_command;
u8 rtc_year;
u8 rtc_month;
u8 rtc_day;
u8 rtc_incr;
u8 rtc_hours;
u8 rtc_minutes;
u8 rtc_seconds;
};
};
uint16 battery;
uint16 aux;
pTransferSound soundData;
vuint32 mailAddr;
vuint32 mailData;
vuint8 mailRead;
vuint8 mailBusy;
vuint32 mailSize;
} TransferRegion, * pTransferRegion;
And this is my (bad) translation
sTransferRegion = record
heartbeat: cuint32;
touchX, touchY: cint16;
touchXpx, touchYpx: cint16;
touchZ1, touchZ2: cint16;
tdiode1, tdiode2: cuint16;
temperature: cuint32;
buttons: cuint16;
union: record
case integer of
0: (curtime: array [0..7] of cuint8);
1: (
rtc_command: cuint8;
rtc_year: cuint8;
rtc_month: cuint8;
rtc_day: cuint8;
rtc_incr: cuint8;
rtc_hours: cuint8;
rtc_minutes: cuint8;
rtc_seconds: cuint8;
);
end;
battery: cuint16;
aux: cuint16;
soundData: pTransferSound;
mailAddr: cuint32;
mailData: cuint32;
mailRead: cuint8;
mailBusy: cuint8;
mailSize: cuint32;
end;
TransferRegion = sTransferRegion;
pTransferRegion = ^sTransferRegion;
I think that the problem is in the union part... the nested record I have used is an ugly trick to avoid the limitation that forces to put variant parts as the last field in a record.
Any better solution? :scratch:
JSoftware
11-01-2007, 08:56 PM
my first idea was that it should be a packed record but having a second look it seems to align just fine...
edit: or wait a minute. won't the last field be scewed into the last 4 padded bytes?
Legolas
11-01-2007, 09:47 PM
Uhm... I don't know... sizeof gives 60 for c struct and 56 for pascal record :think:
JSoftware
11-01-2007, 09:49 PM
sizeof the unpacked record in delphi is 60. What exactly is a vuintxx?
edit: a quick search tells me it means a volatile field? how could the end of a c struct be volatile?
Legolas
11-01-2007, 10:04 PM
Really I don't care about volatile, because it is an optimization that fpc can't handle yet, so I simply ignore it.
Correction: the record size is 60 too... I forgot to remove a "packed" I have put to make a try :oops:
BTW, the alignment problem remains :(
VilleK
12-01-2007, 08:09 AM
If you find out where in the struct the alignment differs then
you could make a packed record, and then inserting padding
bytes manually until it fits.
Like this:
sTransferRegion = packed record
heartbeat: cuint32;
touchX, touchY: cint16;
touchXpx, touchYpx: cint16;
touchZ1, touchZ2: cint16;
tdiode1, tdiode2: cuint16;
pad1,pad2 : byte; //padding
buttons: cuint16;
pad3,pad4 : byte; //padding
...etc
Also my first guess would be that the c/pascal alignment could
differ at the last 8-bit fields: mailRead, mailBusy: cuint8;
Legolas
14-01-2007, 02:34 PM
So, I resolved that alignment issue. To tell the truth it was the effect and not the cause... :roll:
Now I have another problem (I hope it will be the last one...). I have a function in a c library that requires as parameter a pointer to a void function:
typedef void (* VoidFunctionPointer)(void);
void irqSet(IRQ_MASK irq, VoidFunctionPointer handler);
I have translated it as:
procedure irqSet(irq: IRQ_MASK; handler: Pointer); cdecl; external;
and it works if I use it in this way:
irqSet(IRQ_VBLANK, @myProcedure);
Now the problem comes if I try to pass to irqSet a void function that is implemented in another c library:
extern void Wifi_Interrupt();
translated as:
procedure Wifi_Interrupt(); cdecl; external;
hangs on:
irqSet(IRQ_WIFI, @Wifi_Interrupt); :scratch:
JSoftware
14-01-2007, 02:39 PM
would this make any difference?
type
VoidFunctionPointer = procedure; cdecl;
procedure irqSet(irq: IRQ_MASK; handler: VoidFunctionPointer); cdecl; external;
Legolas
14-01-2007, 03:23 PM
Unfortunately, the only difference is that in this way does not work for pascal procedures too :(
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.