Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault with set_use_custom_draw #36

Open
tjkirch opened this issue Mar 25, 2023 · 3 comments
Open

Segfault with set_use_custom_draw #36

tjkirch opened this issue Mar 25, 2023 · 3 comments

Comments

@tjkirch
Copy link
Contributor

tjkirch commented Mar 25, 2023

That said, set_use_custom_draw does seem like the right approach for this. If you can reproduce the segfaults we should figure out why they occur.

Originally posted by @rtsuk in #35 (comment)


Here's a minimal reproduction:

#![no_std]
extern crate alloc;

use {
    alloc::boxed::Box,
    anyhow::Error,
    crankstart::{
        crankstart_game,
        graphics::Graphics,
        sprite::{Sprite, SpriteManager},
        Game, Playdate,
    },
    crankstart_sys::{LCDBitmapFlip, PDRect},
};

struct State {
    // If the sprite is not stored, the crash doesn't happen
    _sprite: Sprite,
}

impl State {
    pub fn new(_playdate: &Playdate) -> Result<Box<Self>, Error> {
        // Load an image, assign it to a custom-draw sprite, add the sprite.
        // Crash doesn't happen unless a bitmap is assigned to the sprite.
        let bitmap = Graphics::get().load_bitmap("graphics/wedge")?;
        let sprite_manager = SpriteManager::get_mut();
        let mut sprite = sprite_manager.new_sprite()?;
        // No crash unless it's custom-draw.
        sprite.set_use_custom_draw()?;
        sprite.set_image(bitmap, LCDBitmapFlip::kBitmapUnflipped)?;
        sprite_manager.add_sprite(&sprite)?;
        Ok(Box::new(Self { _sprite: sprite }))
    }
}

impl Game for State {
    fn update(&mut self, _playdate: &mut Playdate) -> Result<(), Error> {
        Ok(())
    }

    fn update_sprite(&mut self, _: &mut Sprite, _: &mut Playdate) -> Result<(), Error> {
        Ok(())
    }

    // Same crash happens with or without this definition:
    fn draw_sprite(&self, _: &Sprite, _: &PDRect, _: &PDRect, _: &Playdate) -> Result<(), Error> {
        Ok(())
    }
}

crankstart_game!(State);

The result:

Loading C API game: target/Golf Date.pdx/pdex.so
16:23:47: Loading: OK

Thread 1 "PlaydateSimulat" received signal SIGSEGV, Segmentation fault.
0x0000555555968c88 in _compositeRow ()
(gdb) bt
#0  0x0000555555968c88 in _compositeRow ()
#1  0x00005555559735da in LCDBitmap_drawBitmap ()
#2  0x0000555555980d70 in LCD_drawBitmap ()
#3  0x00005555559828b9 in LCDSprite_draw ()
#4  0x000055555597d71c in LCDDisplayList_drawScreenRect ()
Dwarf Error: Cannot find DIE at 0xccf referenced from DIE at 0x1349f [in module target/Golf Date.pdx/pdex.so]

The backtrace is the same whether I define draw_sprite or not. Is it not being hooked up properly? Or is draw_sprite required to take some action that the SDK depends upon having happened?

@rtsuk
Copy link
Collaborator

rtsuk commented Mar 25, 2023

I don't recall seeing any C examples that use custom draw and then also set an image on the sprite. I'm not sure what the Playdate will do in that case.

@tjkirch
Copy link
Contributor Author

tjkirch commented Mar 26, 2023

If it's just something that shouldn't be done, I could make a doc comment :) A more mechanical fix might involve a bool on Sprite that tracks whether set_use_custom_draw has been called and whether an image has been set, failing if one or the other has already happened...

@rtsuk
Copy link
Collaborator

rtsuk commented Mar 27, 2023

The backtrace suggests the crash is in the Playdate code, so maybe that's not a good thing to do? One could write a C version and see what happens. That, or ask on the forums.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants