#need help translating C to odin

1 messages · Page 1 of 1 (latest)

digital rose
#

hello, i need help understanding/rewriting c code to odin (following this tutorial on sdl3: https://solhsa.com/gp2/ch02.html)

  int* gFrameBuffer
  char* pix;
  int pitch;
  
  SDL_LockTexture(gSDLTexture, NULL, (void**)&pix, &pitch);
  for (int i = 0, sp = 0, dp = 0; i < WINDOW_HEIGHT; i++, dp += WINDOW_WIDTH, sp += pitch)
    memcpy(pix + sp, gFrameBuffer + dp, WINDOW_WIDTH * 4);

from what i understand framebuffer and pix are arrays? and in memcpy(pix + sp is sp offset from the pointer?

in odin, i'm trying to do this:

gframe_buffer: ^int

    pix: rawptr
    pitch: i32

    sdl.LockTexture(&texture, nil, &pix, &pitch)

    sp := 0
    dp := 0

    for i := 0; i < window_height; i += 1 {
        sp += pitch
        dp += window_width
        mem.copy(pix + sp, gframe_buffer + dp, window_width * 4)
    }

but i get error Mismatched types in binary expression 'pix + sp' : 'rawptr' vs 'int'
i tried looking for stuff on how i could do this on the odin docs but couldn't find any

thanks!

floral linden
#

Odin doesn't allow arithmetic directly on pointers like that. The direct equivalent would be to use multipointers and slice them with the offset as the starting point, e.g.

gFrameBuffer: [^]i32 // note: NOT int, that's different from C's int!
texture: ^sdl.Texture // SDL gives you a pointer to the Texture when you create it, keep that pointer

pix: [^]u8
pitch: i32
sdl.LockTexture(texture, nil, cast(^rawptr)&pix, &pitch)

dp, sp: i32
for i in 0..<window_height {
  mem.copy(pix[sp:], gFrameBuffer[dp:], window_width * 4)
  dp += window_width // you want to add these *after* you copy, otherwise you're skipping the entire first row (and the last row will read and write past the end)
  sp += pitch
}

Odin splits C's pointers into two types: ^T (pointer to one thing) and [^]T (pointer to an array of things with an unknown length). The latter (multipointers) behave mostly like slices, except they don't know the length of the data (so keep in mind, they're not bounds-checked!). Slicing them with a start offset does the same thing that C's pointer arithmetic does, while making it more apparent that it's an offset into an array (which it is)

digital rose
#

that makes sense. thanks!
&pix needs to be casted cast(^rawptr) it will be ^[^]u8?

if i want something like that as a parameter to a proc, do i do

proc(a: ^rawptr) or proc(a: ^[^]u8)

if i do rawptr how do i know what type it is? do you want a rawptr cause you don't care?

floral linden
#

It's the same thing the C code is doing, in essence; pix is a pointer to an array of bytes, but LockTexture needs a pointer to that pointer because it's going to change it, and it's ^rawptr/void** because it doesn't care what type of pointer it is

#

rawptr is specifically "a pointer to something" without specifying what. It's the equivalent to C's void*

#

Odin will allow pointers to implicitly convert to rawptr (which is happening to the first two arguments of mem.copy), but that implicit conversion doesn't extend to ^rawptr

digital rose
#

gonna keep going on the tutorial to try to see more examples and understand more xD

i'll come back to this thread if I have more questions
thank you!

digital rose
#

i have another function i'm trying to translate:

//unsigned short *gLut;
void render(Uint64 aTicks)
{
  int i, j;
  for (i = 0; i < WINDOW_HEIGHT; i++)
  {
    for (j = 0; j < WINDOW_WIDTH; j++)
    {
      int lut = gLut[(i) * WINDOW_WIDTH + j];
      gFrameBuffer[(j) + (i) * WINDOW_WIDTH] = lut | 0xff000000;
    }
  }
}

i have this in odin

render :: proc(aticks: int) {
    for i in 0..<window_height {
        for j in 0..<window_width {
            lut := gLut[(i) * window_width + j]
            gframe_buffer[(j) + (i) * window_width] = cast(int)(lut | cast(u16)0xff000000)
        }
    }
}

and I get this error

[DEBUG] 4278190080
u16 -> 2
src/llvm_backend_const.cpp(518): Assertion Failure: `sz >= max_count` max_count: 4, sz: 2, written: 0, type u16

not sure what the error message means

floral linden
#

Any assertion failure during a build is a compiler bug

#

Though it could have something to do with trying to cast 0xff000000 to u16? Normally that would be a regular, intended compile error (constants aren't allowed to truncate)

#

You probably want cast(int)lut | 0xff000000

#

(or, more directly from the C code, probably i32 rather than int--C's int isn't the same as Odin's int)

#

Huh, yeah, even this causes the same assertion

main :: proc() {
  x := cast(u16)0xff000000
}

That's definitely a compiler bug

digital rose
#

okay good to know! thanks
i'll try using i32

floral linden
#

Depends on what type gLut and gframe_buffer are, really

digital rose
#

i have this

gLut: []u16
gframe_buffer: []int