render objs on top of scrolled area instead of into 256x256 area

This commit is contained in:
Matthew Laux 2022-08-02 00:51:26 -05:00
parent f4ca6cf847
commit 2adf5b741b
3 changed files with 24 additions and 30 deletions

View File

@ -181,23 +181,6 @@ static void render_background(struct dmg *dmg, int lcdc)
} }
} }
static void scroll(struct dmg *dmg)
{
int scroll_y = lcd_read(dmg->lcd, REG_SCY);
int scroll_x = lcd_read(dmg->lcd, REG_SCX);
int lines;
for (lines = 0; lines < 144; lines++) {
int src_y = (scroll_y + lines) & 0xff;
int cols;
for (cols = 0; cols < 160; cols++) {
int src_off = (src_y << 8) + ((scroll_x + cols) & 0xff);
dmg->lcd->pixels[lines * 160 + cols] = dmg->lcd->buf[src_off];
}
}
}
struct oam_entry { struct oam_entry {
u8 pos_y; u8 pos_y;
u8 pos_x; u8 pos_x;
@ -221,18 +204,22 @@ static void render_objs(struct dmg *dmg)
lcd_x = oam->pos_x - 8; lcd_x = oam->pos_x - 8;
lcd_y = oam->pos_y - 16; lcd_y = oam->pos_y - 16;
off = 256 * lcd_y + lcd_x; off = 160 * lcd_y + lcd_x;
int eff_addr = 0x8000 + 16 * oam->tile; int eff_addr = 0x8000 + 16 * oam->tile;
int b, i; int b, i;
for (b = 0; b < 16; b += 2) { for (b = 0; b < 16; b += 2) {
int data1 = dmg_read(dmg, eff_addr + b); int data1 = dmg_read(dmg, eff_addr + b);
int data2 = dmg_read(dmg, eff_addr + b + 1); int data2 = dmg_read(dmg, eff_addr + b + 1);
for (i = 7; i >= 0; i--) { for (i = 7; i >= 0; i--) {
dmg->lcd->buf[off] = ((data1 & (1 << i)) ? 1 : 0) << 1; if (off < 0 || off >= 160 * 144) {
dmg->lcd->buf[off] |= (data2 & (1 << i)) ? 1 : 0; // terrible clipping. need to not have an if per-pixel
continue;
}
dmg->lcd->pixels[off] = ((data1 & (1 << i)) ? 1 : 0) << 1;
dmg->lcd->pixels[off] |= (data2 & (1 << i)) ? 1 : 0;
off++; off++;
} }
off += 248; off += 152;
} }
} }
} }
@ -284,14 +271,12 @@ void dmg_step(void *_dmg)
// printf("window\n"); // printf("window\n");
} }
lcd_apply_scroll(dmg->lcd);
if (lcdc & LCDC_ENABLE_OBJ) { if (lcdc & LCDC_ENABLE_OBJ) {
render_objs(dmg); render_objs(dmg);
} }
scroll(dmg);
// now copy 256x256 buf to 160x144 based on window registers
lcd_copy(dmg->lcd);
lcd_draw(dmg->lcd); lcd_draw(dmg->lcd);
} }
} else { } else {

View File

@ -66,10 +66,20 @@ void lcd_put_pixel(struct lcd *lcd, u8 x, u8 y, u8 value)
lcd->pixels[y * LCD_WIDTH + x] = value; lcd->pixels[y * LCD_WIDTH + x] = value;
} }
void lcd_copy(struct lcd *lcd) void lcd_apply_scroll(struct lcd *lcd)
{ {
// use all the registers to compute the pixel data int scroll_y = lcd_read(lcd, REG_SCY);
int scroll_x = lcd_read(lcd, REG_SCX);
int lines;
for (lines = 0; lines < 144; lines++) {
int src_y = (scroll_y + lines) & 0xff;
int cols;
for (cols = 0; cols < 160; cols++) {
int src_off = (src_y << 8) + ((scroll_x + cols) & 0xff);
lcd->pixels[lines * 160 + cols] = lcd->buf[src_off];
}
}
} }
int lcd_step(struct lcd *lcd) int lcd_step(struct lcd *lcd)

View File

@ -58,9 +58,8 @@ void lcd_clear_bit(struct lcd *lcd, u16 addr, u8 bit);
int lcd_isset(struct lcd *lcd, u16 addr, u8 bit); int lcd_isset(struct lcd *lcd, u16 addr, u8 bit);
void lcd_set_mode(struct lcd *lcd, int mode); void lcd_set_mode(struct lcd *lcd, int mode);
// i feel like i'm going to need to call this every cycle and update regs
int lcd_step(struct lcd *lcd); int lcd_step(struct lcd *lcd);
void lcd_copy(struct lcd *lcd); void lcd_apply_scroll(struct lcd *lcd);
// output the pixels to the screen // output the pixels to the screen
void lcd_draw(struct lcd *lcd); void lcd_draw(struct lcd *lcd);