tags:

views:

94

answers:

1

Hello. I'm trying to rewrite this asm code in C, but my asm knowledge very bad.


struct
{
 union
 {
  struct{
  WORD  ShiftZ0;
  WORD  ShiftZ1;
  WORD  ShiftZ2;
  WORD  ShiftZ3; };
  struct{
  DWORD ShiftZ01;
  DWORD ShiftZ23; };
 };
  short ShiftZ0Align;
  short ShiftZ1Align;
  short ShiftZ2Align;
  short ShiftZ3Align;
  int   deltaZ0ToNextLine;
  int   deltaZ1ToNextLine;
  void *Palette;
} AsmDrawData;

inline void AsmDrawWithZ16(BYTE *zdata,BYTE *data,WORD *zbuffer,void *video,int no_dot) {
__asm
  {
  cmp     no_dot,0
  je      end
  mov     esi,zdata
  mov     edi,video
  mov     ebx,zbuffer
  mov     ecx,AsmDrawData.Palette
lp:
  mov     eax,AsmDrawData.ShiftZ01
  add     ax,[esi]
  cmp     ax,[ebx]
  jle     end_out_byte
  mov     [ebx],ax
  mov     edx,data
  movzx   edx,byte ptr [edx]
  mov     DX_REG,[ecx+edx*(COLOR_DEPTH/8)]
  mov     [edi],DX_REG
end_out_byte:
  add     edi,(COLOR_DEPTH/8)
  add     ebx,2
  add     esi,2
  inc     data
  dec     no_dot
  jg      lp
end:
  }
}

This is what I write, but this wrong:

inline void AsmDrawWithZ16(BYTE *zdata,BYTE *data,WORD *zbuffer,void *video,int no_dot)     {
  for( int i = 0; i < no_dot; i++ ) { 
   if( ((WORD*)zdata)[i] + AsmDrawData.ShiftZ0 >= ((WORD*)zbuffer)[i] )
    {
        ((WORD*)zbuffer)[i] = ((WORD*)zdata)[i] + AsmDrawData.ShiftZ0;
        ((WORD*)video)[i]   = ((WORD*)AsmDrawData.Palette)[((BYTE*)data)[i]];
    }
  }
}

Where I could be wrong? (sorry for my very very bad english)

+1  A: 

This is not a real answer. It's just some ideas and a rewriting of the function as I understand it in hopefully a more clear form.

I highly suspect that your problem was with the line:

 if( ((WORD*)zdata)[i] + AsmDrawData.ShiftZ0 >= ((WORD*)zbuffer)[i] )

In this code you cast the zdata pointer from a byte to a word pointer. That seems odd to me. The assembly does appear to have done the same thing, though. Since you probably know more about how the zdata field gets populated you can probably make a better determination about it.

This zbuffer algorithm appears to be fairly standard, so even without trying to reverse engineer this assembly you should be able to re-implement it in C fairly easily.

I rewrote this, . I like to keep this localized, so I just declare local pointers at the top that have the correct types (and also use the C99 stdint names because they are more portable than WORD).

#include <stdint.h>

inline void AsmDrawWithZ16(BYTE *zdata,BYTE *data,WORD *zbuffer,void *video,int no_dot) {
  uint8_t * zd = zdata;  // Should this be 8 or 16 bit
  uint8_t * dat = data;
  uint16_t * zb = zbuffer;
  uint16_t shz = AsmDrawData.ShiftZ0;
  uint16_t * vid = (uint16_t *)video;

  for( int i = 0; i < no_dot; i++ ) {
    uint16_t X = shz + zd[i];
    if( X >= zb[i] )  // Is this the correct direction of the compare
     {
        zb[i] = zdata[i] + X;  // update the depth
        vid[i] = AsmDrawData.Palette[ dat[i] ]; // update the color
     }
  }
}
nategoose
It seems to be correct. I change zd type to uint16_t (because zdata actually 16 bit Z buffer) and almost of rendering good. There is another error with it, but I think that I can fix it. But maybe I can't :)
XRazont
I understand what wrong. There are sign/unsigned confusion with some operations. This is correct:
XRazont
int16_t * zd = (int16_t *)zdata;uint8_t * dat = data;int16_t * zb = (int16_t *)zbuffer;uint16_t shz = AsmDrawData.ShiftZ0;uint16_t * vid = (uint16_t *)video;[...]int16_t X = shz + zd[i];[...]zb[i] = X; // update the depth
XRazont