mirror of
https://github.com/mlaux/gb6.git
synced 2025-04-16 07:37:24 +00:00
attempt per scanline obj rendering
This commit is contained in:
parent
e32535b016
commit
eea33c7e57
78
src/dmg.c
78
src/dmg.c
@ -189,11 +189,11 @@ struct oam_entry {
|
||||
};
|
||||
|
||||
// TODO: only ten per scanline, priority, attributes, move to lcd.c
|
||||
static void render_objs(struct dmg *dmg)
|
||||
static void render_objs(struct dmg *dmg, int scanline)
|
||||
{
|
||||
struct oam_entry *oam = (struct oam_entry *) dmg->lcd->oam;
|
||||
int k, lcd_x, lcd_y, off;
|
||||
int tall = lcd_isset(dmg->lcd, REG_LCDC, LCDC_OBJ_SIZE);
|
||||
int height = lcd_isset(dmg->lcd, REG_LCDC, LCDC_OBJ_SIZE) ? 16 : 8;
|
||||
|
||||
for (k = 0; k < 40; k++, oam++) {
|
||||
if (oam->pos_y == 0 || oam->pos_y >= 160) {
|
||||
@ -206,33 +206,31 @@ static void render_objs(struct dmg *dmg)
|
||||
lcd_x = oam->pos_x - 8;
|
||||
lcd_y = oam->pos_y - 16;
|
||||
|
||||
off = 160 * lcd_y + lcd_x;
|
||||
int eff_addr = 0x8000 + 16 * oam->tile;
|
||||
int b, i, limit = 16;
|
||||
if (tall) {
|
||||
limit = 32;
|
||||
if (scanline < lcd_y || scanline >= lcd_y + height) {
|
||||
continue;
|
||||
}
|
||||
for (b = 0; b < limit; b += 2) {
|
||||
int use_tile = b;
|
||||
if (oam->attrs & OAM_ATTR_MIRROR_Y) {
|
||||
use_tile = (limit - 2) - b;
|
||||
|
||||
off = 160 * scanline + lcd_x;
|
||||
int eff_addr = 0x8000 + 16 * oam->tile;
|
||||
int use_tile = 2 * (scanline - lcd_y);
|
||||
if (oam->attrs & OAM_ATTR_MIRROR_Y) {
|
||||
use_tile = (height - 2) - use_tile;
|
||||
}
|
||||
int data1 = dmg_read(dmg, eff_addr + use_tile);
|
||||
int data2 = dmg_read(dmg, eff_addr + use_tile + 1);
|
||||
int i;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
if (off < 0 || off >= 160 * 144) {
|
||||
// terrible clipping. need to not have an if per-pixel
|
||||
continue;
|
||||
}
|
||||
int data1 = dmg_read(dmg, eff_addr + use_tile);
|
||||
int data2 = dmg_read(dmg, eff_addr + use_tile + 1);
|
||||
for (i = 7; i >= 0; i--) {
|
||||
if (off < 0 || off >= 160 * 144) {
|
||||
// terrible clipping. need to not have an if per-pixel
|
||||
continue;
|
||||
}
|
||||
int use_index = i;
|
||||
if (oam->attrs & OAM_ATTR_MIRROR_X) {
|
||||
use_index = 7 - i;
|
||||
}
|
||||
dmg->lcd->pixels[off] = ((data1 & (1 << use_index)) ? 1 : 0) << 1;
|
||||
dmg->lcd->pixels[off] |= (data2 & (1 << use_index)) ? 1 : 0;
|
||||
off++;
|
||||
int use_index = i;
|
||||
if (oam->attrs & OAM_ATTR_MIRROR_X) {
|
||||
use_index = 7 - i;
|
||||
}
|
||||
off += 152;
|
||||
dmg->lcd->pixels[off] = ((data1 & (1 << use_index)) ? 1 : 0) << 1;
|
||||
dmg->lcd->pixels[off] |= (data2 & (1 << use_index)) ? 1 : 0;
|
||||
off++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -263,23 +261,23 @@ void dmg_step(void *_dmg)
|
||||
lcd_clear_bit(dmg->lcd, REG_STAT, STAT_FLAG_MATCH);
|
||||
}
|
||||
|
||||
int lcdc = lcd_read(dmg->lcd, REG_LCDC);
|
||||
if (next_scanline >= 144 && next_scanline < 154) {
|
||||
lcd_set_mode(dmg->lcd, 1);
|
||||
}
|
||||
|
||||
// TODO: do all of this per-scanline instead of everything in vblank
|
||||
if (next_scanline == 144) {
|
||||
// vblank has started, draw all the stuff from ram into the lcd
|
||||
dmg_request_interrupt(dmg, INT_VBLANK);
|
||||
if (lcd_isset(dmg->lcd, REG_STAT, STAT_INTR_SOURCE_VBLANK)) {
|
||||
dmg_request_interrupt(dmg, INT_LCDSTAT);
|
||||
if (next_scanline == 144) {
|
||||
// vblank has started, draw all the stuff from ram into the lcd
|
||||
dmg_request_interrupt(dmg, INT_VBLANK);
|
||||
if (lcd_isset(dmg->lcd, REG_STAT, STAT_INTR_SOURCE_VBLANK)) {
|
||||
dmg_request_interrupt(dmg, INT_LCDSTAT);
|
||||
}
|
||||
|
||||
if (lcdc & LCDC_ENABLE_BG) {
|
||||
render_background(dmg, lcdc);
|
||||
}
|
||||
}
|
||||
|
||||
int lcdc = lcd_read(dmg->lcd, REG_LCDC);
|
||||
if (lcdc & LCDC_ENABLE_BG) {
|
||||
render_background(dmg, lcdc);
|
||||
}
|
||||
|
||||
} else {
|
||||
// not vblank
|
||||
if (lcdc & LCDC_ENABLE_WINDOW) {
|
||||
// printf("window\n");
|
||||
}
|
||||
@ -287,7 +285,7 @@ void dmg_step(void *_dmg)
|
||||
lcd_apply_scroll(dmg->lcd);
|
||||
|
||||
if (lcdc & LCDC_ENABLE_OBJ) {
|
||||
render_objs(dmg);
|
||||
render_objs(dmg, next_scanline);
|
||||
}
|
||||
|
||||
lcd_draw(dmg->lcd);
|
||||
|
@ -7,18 +7,18 @@
|
||||
|
||||
void lcd_set_bit(struct lcd *lcd, u16 addr, u8 bit)
|
||||
{
|
||||
lcd_write(lcd, addr, lcd_read(lcd, addr) | (1 << bit));
|
||||
lcd_write(lcd, addr, lcd_read(lcd, addr) | bit);
|
||||
}
|
||||
|
||||
void lcd_clear_bit(struct lcd *lcd, u16 addr, u8 bit)
|
||||
{
|
||||
lcd_write(lcd, addr, lcd_read(lcd, addr) & ~(1 << bit));
|
||||
lcd_write(lcd, addr, lcd_read(lcd, addr) & ~bit);
|
||||
}
|
||||
|
||||
int lcd_isset(struct lcd *lcd, u16 addr, u8 bit)
|
||||
{
|
||||
u8 val = lcd_read(lcd, addr);
|
||||
return val & (1 << bit);
|
||||
return val & bit;
|
||||
}
|
||||
|
||||
void lcd_set_mode(struct lcd *lcd, int mode)
|
||||
|
10
src/lcd.h
10
src/lcd.h
@ -23,11 +23,11 @@
|
||||
|
||||
#define REG_LCD_LAST REG_WX
|
||||
|
||||
#define STAT_FLAG_MATCH 2
|
||||
#define STAT_INTR_SOURCE_HBLANK 3
|
||||
#define STAT_INTR_SOURCE_VBLANK 4
|
||||
#define STAT_INTR_SOURCE_MODE2 5
|
||||
#define STAT_INTR_SOURCE_MATCH 6
|
||||
#define STAT_FLAG_MATCH (1 << 2)
|
||||
#define STAT_INTR_SOURCE_HBLANK (1 << 3)
|
||||
#define STAT_INTR_SOURCE_VBLANK (1 << 4)
|
||||
#define STAT_INTR_SOURCE_MODE2 (1 << 5)
|
||||
#define STAT_INTR_SOURCE_MATCH (1 << 6)
|
||||
|
||||
|
||||
#define LCDC_ENABLE_BG (1 << 0)
|
||||
|
Loading…
x
Reference in New Issue
Block a user