| @@ -150,10 +150,12 @@ static void sdl_render_done(nes_Renderer* rend) { | |||||
| } | } | ||||
| typedef enum { | typedef enum { | ||||
| Render_Mode_Sprite = 0b000, | |||||
| Render_Mode_Background = 0b001, | |||||
| Render_Mode_Behind = 0b010, | |||||
| Render_Mode_Collide = 0b100, | |||||
| Render_Mode_Sprite = 0b00000, | |||||
| Render_Mode_Background = 0b00001, | |||||
| Render_Mode_Behind = 0b00010, | |||||
| Render_Mode_Collide = 0b00100, | |||||
| Render_Mode_Flip_X = 0b01000, | |||||
| Render_Mode_Flip_Y = 0b10000, | |||||
| } Render_Mode; | } Render_Mode; | ||||
| @@ -165,13 +167,23 @@ static int render_sprite(nes_ppu* ppu, int index, | |||||
| uint8_t* sprite = &ppu->chr_mem[index * 16U]; | uint8_t* sprite = &ppu->chr_mem[index * 16U]; | ||||
| uint8_t* dst_line = (uint8_t*)loc; | uint8_t* dst_line = (uint8_t*)loc; | ||||
| const uint8_t* back_line = (uint8_t*)back_loc; | const uint8_t* back_line = (uint8_t*)back_loc; | ||||
| if (mode & Render_Mode_Flip_X) { | |||||
| dst_line += 7; | |||||
| back_line += 7; | |||||
| } | |||||
| if (mode & Render_Mode_Flip_Y) { | |||||
| dst_line += (7 * pitch); | |||||
| back_line += (7 * back_pitch); | |||||
| } | |||||
| for (int y = 8; y > 0; --y) { | for (int y = 8; y > 0; --y) { | ||||
| uint8_t lo = sprite[0U]; | uint8_t lo = sprite[0U]; | ||||
| uint8_t hi = sprite[8U]; | uint8_t hi = sprite[8U]; | ||||
| uint8_t* dst = dst_line; | uint8_t* dst = dst_line; | ||||
| const uint8_t* back = back_line; | const uint8_t* back = back_line; | ||||
| for (int x = 8; x > 0; --x) { | for (int x = 8; x > 0; --x) { | ||||
| int pal_idx = ((hi & 0x80) >> 6) | ((lo & 0x80) >> 7); | |||||
| int pal_idx = ( ((hi & 0x80) >> 6) | | |||||
| ((lo & 0x80) >> 7)); | |||||
| int nes_pal_idx = (pal_idx ? pal[pal_idx] : 0xFFU); | int nes_pal_idx = (pal_idx ? pal[pal_idx] : 0xFFU); | ||||
| if ( hit_pos < 0 && | if ( hit_pos < 0 && | ||||
| (ppu->mask & ppu_Mask_Back) && | (ppu->mask & ppu_Mask_Back) && | ||||
| @@ -183,13 +195,24 @@ static int render_sprite(nes_ppu* ppu, int index, | |||||
| if ((mode & Render_Mode_Behind) && *back != 0xFFU) { | if ((mode & Render_Mode_Behind) && *back != 0xFFU) { | ||||
| nes_pal_idx = 0xFFU; | nes_pal_idx = 0xFFU; | ||||
| } | } | ||||
| *dst++ = nes_pal_idx; | |||||
| ++back; | |||||
| *dst = nes_pal_idx; | |||||
| if (mode & Render_Mode_Flip_X) { | |||||
| dst--; | |||||
| back--; | |||||
| } else { | |||||
| dst++; | |||||
| back++; | |||||
| } | |||||
| hi <<= 1; | hi <<= 1; | ||||
| lo <<= 1; | lo <<= 1; | ||||
| } | } | ||||
| dst_line += pitch; | |||||
| back_line += back_pitch; | |||||
| if (mode & Render_Mode_Flip_Y) { | |||||
| dst_line -= pitch; | |||||
| back_line -= back_pitch; | |||||
| } else { | |||||
| dst_line += pitch; | |||||
| back_line += back_pitch; | |||||
| } | |||||
| ++sprite; | ++sprite; | ||||
| } | } | ||||
| return hit_pos; | return hit_pos; | ||||
| @@ -273,13 +296,18 @@ static void render_sprites(nes_ppu* ppu, | |||||
| const uint8_t* dst_back = back_offset + back_origin; | const uint8_t* dst_back = back_offset + back_origin; | ||||
| // TODO: Support 8x16 sprites | // TODO: Support 8x16 sprites | ||||
| int index = bank + sprite->index; | int index = bank + sprite->index; | ||||
| // TODO: Support mirroring | |||||
| int pal_idx = (sprite->attr & oam_Attr_Pal_Mask); | int pal_idx = (sprite->attr & oam_Attr_Pal_Mask); | ||||
| const uint8_t* pal = &ppu->palette[16 + (pal_idx * 4)]; | const uint8_t* pal = &ppu->palette[16 + (pal_idx * 4)]; | ||||
| Render_Mode mode = (sprite->attr & oam_Attr_Background) ? | Render_Mode mode = (sprite->attr & oam_Attr_Background) ? | ||||
| Render_Mode_Behind : | Render_Mode_Behind : | ||||
| Render_Mode_Sprite; | Render_Mode_Sprite; | ||||
| if (i_sprite == 0) mode |= Render_Mode_Collide; | if (i_sprite == 0) mode |= Render_Mode_Collide; | ||||
| if (sprite->attr & oam_Attr_Flip_X) { | |||||
| mode |= Render_Mode_Flip_X; | |||||
| } | |||||
| if (sprite->attr & oam_Attr_Flip_Y) { | |||||
| mode |= Render_Mode_Flip_Y; | |||||
| } | |||||
| int hit_pos = render_sprite(ppu, index, pal, mode, | int hit_pos = render_sprite(ppu, index, pal, mode, | ||||
| dst, pitch, | dst, pitch, | ||||
| dst_back, back_pitch); | dst_back, back_pitch); | ||||