GitHub Game Jam 2016: Day 3
Day 3: not much progress. I’ve added a little code to render a basic
game map, but most of my time has been taken up by
a bug in the Rust ncurses
bindings, which prevented
special “ACS” characters from displaying.
I spent three hours last night tracking down the bug, on the hunch
that Rust wasn’t correctly finding the array where the codes for the
special characters were kept (acs_map
). Long story short, after
looking through the disassembly of the game1, I found that the
function that accesses acs_map
was essentially a no-op:
000000000000ddb0 <_ZN7ncurses9constants7acs_map17hbae0ad2383a3a04eE>:
ddb0: 55 push %rbp
ddb1: 48 89 e5 mov %rsp,%rbp
ddb4: eb 00 jmp ddb6 <_ZN7ncurses9constants7acs_map17hbae0ad2383a3a04eE+0x6>
ddb6: eb 00 jmp ddb8 <_ZN7ncurses9constants7acs_map17hbae0ad2383a3a04eE+0x8>
ddb8: 5d pop %rbp
ddb9: c3 retq
ddba: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
After figuring that out, the question was how to get Rust to properly
read the array. acs_map
is a static global array (not a pointer to
one), and was currently declared as [chtype; 0]
(0 length because we
don’t know the length). *const chtype
caused
segfaults. [chtype; 128]
worked, and looking at the generated
assembly, I saw that Rust was memcpy
ing the array. I think this is
because arrays implement Copy
. The accessor function basically
looked like this:
pub fn acs_map() -> [chtype; 0] {
unsafe {
wrapped::acs_map
}
}
so Rust would copy the array…except it was told the array was 0-size,
so it did nothing, expecting that you wouldn’t be so naïve as to try
and dereference it, which of course we were. The solution was to cast
the base of the array to a pointer before accessing it, preventing
Rust from trying to memcpy
. Adding the length “fixed” it because
then Rust copied over the data we were trying to access first.
I’ve filed a pull request to fix the bug. Next up: actually rendering the programs you control. I’ll be talking a little more about game mechanics soon.
-
I’m terrible at reading AMD64 assembly, as we’re taught MIPS at school, never mind the fact that the Rust-generated assembly is a lot messier than C’s. ↩