savage
14-11-2006, 08:42 PM
I'm trying to compile a game on MacOS X, but at run-time I keep getting an "arithmetic error" AV on code that works perfectly fine on Win32 and Linux
The code is as follows...
procedure SDL_SubSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
var
R, G, B, Pixel1, Pixel2, TransparentColor : Cardinal;
Src, Dest : TSDL_Rect;
Diff : integer;
SrcAddr, DestAddr : cardinal;
_ebx, _esi, _edi, _esp : cardinal;
WorkX, WorkY : word;
SrcMod, DestMod : cardinal;
Bits : cardinal;
begin
if ( SrcSurface = nil ) or ( DestSurface = nil ) then
exit; // Remove this to make it faster
if ( SrcSurface.Format.BitsPerPixel <DestSurface> y + h then
begin
smallint( Src.h ) := y + h - Dest.y;
smallint( Dest.h ) := y + h - Dest.y;
if smallint( Dest.h ) < 1 then
exit;
end;
// Source's left side is less than the dest.clip
if Dest.x < x then
begin
Diff := x - Dest.x;
Src.x := Src.x + Diff;
smallint( Src.w ) := smallint( Src.w ) - Diff;
Dest.x := x;
smallint( Dest.w ) := smallint( Dest.w ) - Diff;
if smallint( Dest.w ) < 1 then
exit;
end;
// Source's Top side is less than the dest.clip
if Dest.y < y then
begin
Diff := y - Dest.y;
Src.y := Src.y + Diff;
smallint( Src.h ) := smallint( Src.h ) - Diff;
Dest.y := y;
smallint( Dest.h ) := smallint( Dest.h ) - Diff;
if smallint( Dest.h ) < 1 then
exit;
end;
end;
with SrcSurface^ do
begin
SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
Format.BytesPerPixel;
SrcMod := Pitch - Src.w * Format.BytesPerPixel;
TransparentColor := Format.colorkey;
end;
with DestSurface^ do
begin
DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
Format.BytesPerPixel;
DestMod := Pitch - Dest.w * Format.BytesPerPixel;
Bits := DestSurface.Format.BitsPerPixel;
end;
SDL_LockSurface( SrcSurface );
SDL_LockSurface( DestSurface );
WorkY := Src.h;
case bits of
8 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt8( SrcAddr )^;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $E0) - (Pixel1 and $E0);
G := (Pixel2 and $1C) - (Pixel1 and $1C);
B := (Pixel2 and $03) - (Pixel1 and $03);
if R > $E0 then
R := 0;
if G > $1C then
G := 0;
if B > $03 then
B := 0;
PUInt8( DestAddr )^ := R or G or B;
end;
end;
inc( SrcAddr );
inc( DestAddr );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
15 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt16( SrcAddr )^;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $7C00) - (Pixel1 and $7C00);
G := (Pixel2 and $03E0) - (Pixel1 and $03E0);
B := (Pixel2 and $001F) - (Pixel1 and $001F);
if R > $7C00 then
R := 0;
if G > $03E0 then
G := 0;
if B > $001F then
B := 0;
PUInt16( DestAddr )^ := R or G or B;
end;
end;
inc( SrcAddr, 2 );
inc( DestAddr, 2 );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
16 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt16( SrcAddr )^;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $F800) - (Pixel1 and $F800);
G := (Pixel2 and $07E0) - (Pixel1 and $07E0);
B := (Pixel2 and $001F) - (Pixel1 and $001F);
if R > $F800 then
R := 0;
if G > $07E0 then
G := 0;
if B > $001F then
B := 0;
PUInt16( DestAddr )^ := R or G or B;
end;
end;
inc( SrcAddr, 2 );
inc( DestAddr, 2 );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
24 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $FF0000) - (Pixel1 and $FF0000);
G := (Pixel2 and $00FF00) - (Pixel1 and $00FF00);
B := (Pixel2 and $0000FF) - (Pixel1 and $0000FF);
if R > $FF0000 then
R := 0;
if G > $00FF00 then
G := 0;
if B > $0000FF then
B := 0;
PUInt32( DestAddr )^ := (PUInt32( DestAddr )^ and $FF000000)or ( R or G or B );
end;
end;
inc( SrcAddr, 3 );
inc( DestAddr, 3 );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
32 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt32( SrcAddr )^;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $FF0000) - (Pixel1 and $FF0000);
G := (Pixel2 and $00FF00) - (Pixel1 and $00FF00);
B := (Pixel2 and $0000FF) - (Pixel1 and $0000FF);
if R > $FF0000 then
R := 0;
if G > $00FF00 then
G := 0;
if B > $0000FF then
B := 0;
PUInt32( DestAddr )^ := R or G or B;
end
else
PUInt32( DestAddr )^ := Pixel2;
end;
inc( SrcAddr, 4 );
inc( DestAddr, 4 );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
end;
SDL_UnlockSurface( SrcSurface );
SDL_UnlockSurface( DestSurface );
end;
the lines from the code above that cause the crashes, regardless of surface depth are...
R := (Pixel2 and $FF0000) - (Pixel1 and $FF0000);
G := (Pixel2 and $00FF00) - (Pixel1 and $00FF00);
B := (Pixel2 and $0000FF) - (Pixel1 and $0000FF);
and the other similar code blocks.
I can't see why these lines would cause an AV on MacOS X, but not on Win32 or Linux all of which use the FreePascal compiler. Any ideas?
The code is as follows...
procedure SDL_SubSurface( SrcSurface : PSDL_Surface; SrcRect : PSDL_Rect;
DestSurface : PSDL_Surface; DestRect : PSDL_Rect );
var
R, G, B, Pixel1, Pixel2, TransparentColor : Cardinal;
Src, Dest : TSDL_Rect;
Diff : integer;
SrcAddr, DestAddr : cardinal;
_ebx, _esi, _edi, _esp : cardinal;
WorkX, WorkY : word;
SrcMod, DestMod : cardinal;
Bits : cardinal;
begin
if ( SrcSurface = nil ) or ( DestSurface = nil ) then
exit; // Remove this to make it faster
if ( SrcSurface.Format.BitsPerPixel <DestSurface> y + h then
begin
smallint( Src.h ) := y + h - Dest.y;
smallint( Dest.h ) := y + h - Dest.y;
if smallint( Dest.h ) < 1 then
exit;
end;
// Source's left side is less than the dest.clip
if Dest.x < x then
begin
Diff := x - Dest.x;
Src.x := Src.x + Diff;
smallint( Src.w ) := smallint( Src.w ) - Diff;
Dest.x := x;
smallint( Dest.w ) := smallint( Dest.w ) - Diff;
if smallint( Dest.w ) < 1 then
exit;
end;
// Source's Top side is less than the dest.clip
if Dest.y < y then
begin
Diff := y - Dest.y;
Src.y := Src.y + Diff;
smallint( Src.h ) := smallint( Src.h ) - Diff;
Dest.y := y;
smallint( Dest.h ) := smallint( Dest.h ) - Diff;
if smallint( Dest.h ) < 1 then
exit;
end;
end;
with SrcSurface^ do
begin
SrcAddr := cardinal( Pixels ) + UInt32( Src.y ) * Pitch + UInt32( Src.x ) *
Format.BytesPerPixel;
SrcMod := Pitch - Src.w * Format.BytesPerPixel;
TransparentColor := Format.colorkey;
end;
with DestSurface^ do
begin
DestAddr := cardinal( Pixels ) + UInt32( Dest.y ) * Pitch + UInt32( Dest.x ) *
Format.BytesPerPixel;
DestMod := Pitch - Dest.w * Format.BytesPerPixel;
Bits := DestSurface.Format.BitsPerPixel;
end;
SDL_LockSurface( SrcSurface );
SDL_LockSurface( DestSurface );
WorkY := Src.h;
case bits of
8 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt8( SrcAddr )^;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $E0) - (Pixel1 and $E0);
G := (Pixel2 and $1C) - (Pixel1 and $1C);
B := (Pixel2 and $03) - (Pixel1 and $03);
if R > $E0 then
R := 0;
if G > $1C then
G := 0;
if B > $03 then
B := 0;
PUInt8( DestAddr )^ := R or G or B;
end;
end;
inc( SrcAddr );
inc( DestAddr );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
15 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt16( SrcAddr )^;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $7C00) - (Pixel1 and $7C00);
G := (Pixel2 and $03E0) - (Pixel1 and $03E0);
B := (Pixel2 and $001F) - (Pixel1 and $001F);
if R > $7C00 then
R := 0;
if G > $03E0 then
G := 0;
if B > $001F then
B := 0;
PUInt16( DestAddr )^ := R or G or B;
end;
end;
inc( SrcAddr, 2 );
inc( DestAddr, 2 );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
16 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt16( SrcAddr )^;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $F800) - (Pixel1 and $F800);
G := (Pixel2 and $07E0) - (Pixel1 and $07E0);
B := (Pixel2 and $001F) - (Pixel1 and $001F);
if R > $F800 then
R := 0;
if G > $07E0 then
G := 0;
if B > $001F then
B := 0;
PUInt16( DestAddr )^ := R or G or B;
end;
end;
inc( SrcAddr, 2 );
inc( DestAddr, 2 );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
24 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt32( SrcAddr )^ and $00FFFFFF;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $FF0000) - (Pixel1 and $FF0000);
G := (Pixel2 and $00FF00) - (Pixel1 and $00FF00);
B := (Pixel2 and $0000FF) - (Pixel1 and $0000FF);
if R > $FF0000 then
R := 0;
if G > $00FF00 then
G := 0;
if B > $0000FF then
B := 0;
PUInt32( DestAddr )^ := (PUInt32( DestAddr )^ and $FF000000)or ( R or G or B );
end;
end;
inc( SrcAddr, 3 );
inc( DestAddr, 3 );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
32 :
begin
repeat
WorkX := Src.w;
repeat
Pixel1 := PUInt32( SrcAddr )^;
if ( Pixel1 <> TransparentColor ) and ( Pixel1 <0> 0 then
begin
R := (Pixel2 and $FF0000) - (Pixel1 and $FF0000);
G := (Pixel2 and $00FF00) - (Pixel1 and $00FF00);
B := (Pixel2 and $0000FF) - (Pixel1 and $0000FF);
if R > $FF0000 then
R := 0;
if G > $00FF00 then
G := 0;
if B > $0000FF then
B := 0;
PUInt32( DestAddr )^ := R or G or B;
end
else
PUInt32( DestAddr )^ := Pixel2;
end;
inc( SrcAddr, 4 );
inc( DestAddr, 4 );
dec( WorkX );
until WorkX = 0;
inc( SrcAddr, SrcMod );
inc( DestAddr, DestMod );
dec( WorkY );
until WorkY = 0;
end;
end;
SDL_UnlockSurface( SrcSurface );
SDL_UnlockSurface( DestSurface );
end;
the lines from the code above that cause the crashes, regardless of surface depth are...
R := (Pixel2 and $FF0000) - (Pixel1 and $FF0000);
G := (Pixel2 and $00FF00) - (Pixel1 and $00FF00);
B := (Pixel2 and $0000FF) - (Pixel1 and $0000FF);
and the other similar code blocks.
I can't see why these lines would cause an AV on MacOS X, but not on Win32 or Linux all of which use the FreePascal compiler. Any ideas?