Results 1 to 4 of 4

Thread: Spot the mistake...

  1. #1

    Spot the mistake...

    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...
    [pascal]
    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;
    [/pascal]

    the lines from the code above that cause the crashes, regardless of surface depth are...
    [pascal]
    R := (Pixel2 and $FF0000) - (Pixel1 and $FF0000);
    G := (Pixel2 and $00FF00) - (Pixel1 and $00FF00);
    B := (Pixel2 and $0000FF) - (Pixel1 and $0000FF);
    [/pascal]
    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?
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  2. #2

    Spot the mistake...

    Dom

    Is this a PPC Mac or an Intel mac?If it's PPC that remember that the High and Low bytes are swapped over,so the masks would not work.

    so

    $FF0000

    would need to be

    $0000FF

    Just a thought

    Dean
    <A HREF="http://www.myhpf.co.uk/banner.asp?friend=139328">
    <br /><IMG SRC="http://www.myhpf.co.uk/banners/60x468.gif" BORDER="0">
    <br /></A>

  3. #3

    Spot the mistake...

    It's an Intel Mac, but I'm not sure if MacOS X being based on FreeBSD would make any endian difference.
    <br /><br />There are a lot of people who are dead while they are still alive. I want to be alive until the day I die.<br />-= Paulo Coelho =-

  4. #4

    Spot the mistake...

    Endian is down to the hardware I think. I'm sure you could test the theory in a small app.
    <A HREF="http://www.myhpf.co.uk/banner.asp?friend=139328">
    <br /><IMG SRC="http://www.myhpf.co.uk/banners/60x468.gif" BORDER="0">
    <br /></A>

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •