| @@ -61,7 +61,12 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { | |||||
| uint8_t* ptr = ppu->line_data; | uint8_t* ptr = ppu->line_data; | ||||
| if (!(mem->mask & ppu_Mask_Back)) { | if (!(mem->mask & ppu_Mask_Back)) { | ||||
| memset(ptr, 0, nes_ppu_render_w); | |||||
| // Emulate the happy part of the backdrop override quirk | |||||
| int pal_idx = ((mem->addr & 0x3F00U) == 0x3F00U) ? | |||||
| (mem->addr & 0x1FU) : 0; | |||||
| // Don't use the rendering palette (masked transparency) | |||||
| memset(ptr, mem->pal_bank[0x300 + pal_idx], | |||||
| nes_ppu_render_w); | |||||
| } else { | } else { | ||||
| int back_bank = nes_PPU_Nametable_Bank_Index + | int back_bank = nes_PPU_Nametable_Bank_Index + | ||||
| ((mem->addr >> 10) & 3); | ((mem->addr >> 10) & 3); | ||||
| @@ -75,32 +80,33 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { | |||||
| const uint8_t* nametable = mem->bank[back_bank] + (y_coarse * 32) + x_coarse; | const uint8_t* nametable = mem->bank[back_bank] + (y_coarse * 32) + x_coarse; | ||||
| const uint8_t* attrs = mem->bank[back_bank] + 0x3C0U + ((y_coarse >> 2) << 3); | const uint8_t* attrs = mem->bank[back_bank] + 0x3C0U + ((y_coarse >> 2) << 3); | ||||
| // Partial left column | |||||
| ptr += 8 - mem->x; | ptr += 8 - mem->x; | ||||
| // TODO: Omit if left column is masked? | |||||
| { | |||||
| const uint8_t* pal = mem->palette + | |||||
| (((attrs[x_coarse >> 2] >> | |||||
| ( (x_coarse & 2) + | |||||
| ((y_coarse & 2) << 1))) & 3) << 2); | |||||
| const int ch = *nametable; | |||||
| const int bank = (ch >> 6) + bank_off; | |||||
| const int addr_off = ((ch & 0x3F) << 4) + y_fine; | |||||
| const uint8_t* data = mem->bank[bank] + addr_off; | |||||
| const uint8_t pl0 = data[0]; | |||||
| const uint8_t pl1 = data[8]; | |||||
| const int pat0 = (pl0 & 0x55) | ((pl1 << 1) & 0xAA); | |||||
| const int pat1 = ((pl0 >> 1) & 0x55) | (pl1 & 0xAA); | |||||
| switch (mem->x) { | |||||
| case 0: ptr[-8] = pal[(pat1 >> 6) & 3]; | |||||
| case 1: ptr[-7] = pal[(pat0 >> 6) & 3]; | |||||
| case 2: ptr[-6] = pal[(pat1 >> 4) & 3]; | |||||
| case 3: ptr[-5] = pal[(pat0 >> 4) & 3]; | |||||
| case 4: ptr[-4] = pal[(pat1 >> 2) & 3]; | |||||
| case 5: ptr[-3] = pal[(pat0 >> 2) & 3]; | |||||
| case 6: ptr[-2] = pal[(pat1 >> 0) & 3]; | |||||
| case 7: ptr[-1] = pal[(pat0 >> 0) & 3]; | |||||
| } | |||||
| // Omit if left column is masked | |||||
| if (mem->mask & ppu_Mask_Left_Back) { | |||||
| const uint8_t* pal = mem->palette + | |||||
| (((attrs[x_coarse >> 2] >> | |||||
| ( (x_coarse & 2) + | |||||
| ((y_coarse & 2) << 1))) & 3) << 2); | |||||
| const int ch = *nametable; | |||||
| const int bank = (ch >> 6) + bank_off; | |||||
| const int addr_off = ((ch & 0x3F) << 4) + y_fine; | |||||
| const uint8_t* data = mem->bank[bank] + addr_off; | |||||
| const uint8_t pl0 = data[0]; | |||||
| const uint8_t pl1 = data[8]; | |||||
| const int pat0 = (pl0 & 0x55) | ((pl1 << 1) & 0xAA); | |||||
| const int pat1 = ((pl0 >> 1) & 0x55) | (pl1 & 0xAA); | |||||
| switch (mem->x) { | |||||
| case 0: ptr[-8] = pal[(pat1 >> 6) & 3]; | |||||
| case 1: ptr[-7] = pal[(pat0 >> 6) & 3]; | |||||
| case 2: ptr[-6] = pal[(pat1 >> 4) & 3]; | |||||
| case 3: ptr[-5] = pal[(pat0 >> 4) & 3]; | |||||
| case 4: ptr[-4] = pal[(pat1 >> 2) & 3]; | |||||
| case 5: ptr[-3] = pal[(pat0 >> 2) & 3]; | |||||
| case 6: ptr[-2] = pal[(pat1 >> 0) & 3]; | |||||
| case 7: ptr[-1] = pal[(pat0 >> 0) & 3]; | |||||
| } | |||||
| } | } | ||||
| // TODO: Mapper ppu_bus | // TODO: Mapper ppu_bus | ||||
| @@ -119,8 +125,6 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { | |||||
| const uint8_t* data = mem->bank[bank] + addr_off; | const uint8_t* data = mem->bank[bank] + addr_off; | ||||
| const uint8_t pl0 = data[0]; | const uint8_t pl0 = data[0]; | ||||
| const uint8_t pl1 = data[8]; | const uint8_t pl1 = data[8]; | ||||
| //const int pat0 = ((pl0 & 0x55) << 1) | ((pl1 & 0x55) << 2); | |||||
| //const int pat1 = ((pl0 & 0xAA) << 0) | ((pl1 & 0xAA) << 1); | |||||
| const int pat0 = (pl0 & 0x55) | ((pl1 << 1) & 0xAA); | const int pat0 = (pl0 & 0x55) | ((pl1 << 1) & 0xAA); | ||||
| const int pat1 = ((pl0 >> 1) & 0x55) | (pl1 & 0xAA); | const int pat1 = ((pl0 >> 1) & 0x55) | (pl1 & 0xAA); | ||||
| @@ -135,12 +139,14 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { | |||||
| ptr += 8; | ptr += 8; | ||||
| } | } | ||||
| // Left Nametable | |||||
| for (; x_coarse < 32; ++x_coarse) { | for (; x_coarse < 32; ++x_coarse) { | ||||
| render_bg(); | render_bg(); | ||||
| // TODO: Mapper ppu_bus | // TODO: Mapper ppu_bus | ||||
| ++nametable; | ++nametable; | ||||
| } | } | ||||
| // Right Nametable | |||||
| back_bank ^= 0b01; | back_bank ^= 0b01; | ||||
| nametable = mem->bank[back_bank] + (y_coarse * 32); | nametable = mem->bank[back_bank] + (y_coarse * 32); | ||||
| attrs = mem->bank[back_bank] + 0x3C0U + ((y_coarse >> 2) << 3); | attrs = mem->bank[back_bank] + 0x3C0U + ((y_coarse >> 2) << 3); | ||||
| @@ -150,6 +156,38 @@ void nes_ppu_render_line(nes_PPU* ppu, nes_PPU_Memory* mem) { | |||||
| // TODO: Mapper ppu_bus | // TODO: Mapper ppu_bus | ||||
| ++nametable; | ++nametable; | ||||
| } | } | ||||
| // Partial right column | |||||
| { | |||||
| const uint8_t* pal = mem->palette + | |||||
| (((attrs[x_coarse >> 2] >> | |||||
| ( (x_coarse & 2) + | |||||
| ((y_coarse & 2) << 1))) & 3) << 2); | |||||
| const int ch = *nametable; | |||||
| const int bank = (ch >> 6) + bank_off; | |||||
| const int addr_off = ((ch & 0x3F) << 4) + y_fine; | |||||
| const uint8_t* data = mem->bank[bank] + addr_off; | |||||
| const uint8_t pl0 = data[0]; | |||||
| const uint8_t pl1 = data[8]; | |||||
| const int pat0 = (pl0 & 0x55) | ((pl1 << 1) & 0xAA); | |||||
| const int pat1 = ((pl0 >> 1) & 0x55) | (pl1 & 0xAA); | |||||
| switch (mem->x) { | |||||
| case 8: ptr[7] = pal[(pat0 >> 0) & 3]; | |||||
| case 7: ptr[6] = pal[(pat1 >> 0) & 3]; | |||||
| case 6: ptr[5] = pal[(pat0 >> 2) & 3]; | |||||
| case 5: ptr[4] = pal[(pat1 >> 2) & 3]; | |||||
| case 4: ptr[3] = pal[(pat0 >> 4) & 3]; | |||||
| case 3: ptr[2] = pal[(pat1 >> 4) & 3]; | |||||
| case 2: ptr[1] = pal[(pat0 >> 6) & 3]; | |||||
| case 1: ptr[0] = pal[(pat1 >> 6) & 3]; | |||||
| } | |||||
| } | |||||
| } | |||||
| // TODO: Mapper ppu_bus | |||||
| if (!(mem->mask & ppu_Mask_Left_Back)) { | |||||
| memset(ppu->line_data, mem->palette[0], 8); | |||||
| } | } | ||||
| // TODO: Draw Sprites | // TODO: Draw Sprites | ||||