Ogres are like Onions
Hello everyone! This time, I’ve fortunately logged a normal amount of time. Let’s dive in!
Close the Window!
After the background rendering was complete, it was time to work on the next layer: the window. The window is exactly as it sounds — the layer between sprites and the background that can have ui and stuff.
The window starts at a position dictated by wx and wy (0xff4b and 0xff4a in memory), and those two dictate the top-left corner of the window layer (though wx - 7 is the actual top-left x coord). If a game wants to have a window layer that ends, it will switch off the window layer BETWEEN scanlines, which my current implementation cannot do because I render the whole frame at VBlank (after all scanlines) for simplicity, and it’s not strictly necessary.
The code implementation of the window layer was relatively similar to background:
fn window_active_for_pixel(&self, screen_x: u8, screen_y: u8) -> bool {
if (self.read_byte(0xff40) >> 5) & 0x1 == 0 {
return false;
}
let wy = self.read_byte(0xff4a);
let wx = self.read_byte(0xff4b);
if screen_y >= wy && screen_x >= wx.saturating_sub(7) {
return true;
}
false
}
fn window_pixel_value(&self, screen_x: u8, screen_y: u8) -> TilePixelValue {
let window_y = screen_y - self.read_byte(0xff4a);
let window_x = screen_x + 7 - self.read_byte(0xff4b);
let window_tile_map_index = (window_y / 8) as u16 * 32 + (window_x / 8) as u16;
let window_tile_map_base = if (self.read_byte(0xff40) >> 6) & 0x1 == 0 {
0x9800
} else {
0x9c00
};
let tile =
&self.index_to_tile(self.read_byte(window_tile_map_base + window_tile_map_index));
tile[(window_y % 8) as usize][(window_x % 8) as usize]
}
The next step is the final layer: Sprites! Sprites will be more involved and unique compared to background and window. I still can’t believe the Sharp SM83 did all this for developers. See y’all next time!
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.