Skip to content

Commit 757fa4d

Browse files
committed
Finished the pixel fetcher!
1 parent af27ed3 commit 757fa4d

File tree

3 files changed

+104
-11
lines changed

3 files changed

+104
-11
lines changed

core/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const OAM_VISIBLE_SPRITES_LOCATION: i32 = BG_PRIORITY_MAP_LOCATION + BG_P
4040
export const OAM_VISIBLE_SPRITES_SIZE: i32 = 0x0b;
4141

4242
export const PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION: i32 = OAM_VISIBLE_SPRITES_LOCATION + OAM_VISIBLE_SPRITES_SIZE;
43-
export const PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_SIZE: i32 = 0x3c;
43+
export const PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_SIZE: i32 = 0x50;
4444

4545
export const FRAME_LOCATION: i32 = PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_SIZE;
4646
export const FRAME_SIZE: i32 = 0x016c00;

core/graphics/lcd.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export class Lcd {
3939
static coincidenceCompare: i32 = 0;
4040

4141
// Also known as LCDC
42-
// http://www.codeslinger.co.uk/pages/projects/gameboy/graphics.html
42+
// http://gbdev.gg8.se/wiki/articles/LCDC
4343
// Bit 7 - LCD Display Enable (0=Off, 1=On)
4444
// Bit 6 - Window Tile Map Display Select (0=9800-9BFF, 1=9C00-9FFF)
4545
// Bit 5 - Window Display Enable (0=Off, 1=On)

core/graphics/pixelPipeline/pixelFetcher.ts

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Fetcher for the pixel pipeline
22
// https://youtu.be/HyzD8pNlpwI?t=2957
33
import { PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION } from '../../constants';
4-
import { checkBitOnByte, setBitOnByte } from '../../helpers/index';
4+
import { checkBitOnByte, setBitOnByte, resetBitOnByte } from '../../helpers/index';
55
import { Lcd } from '../lcd';
66
import { getTileDataAddress } from '../tiles';
77
import { LoadFromVramBank } from '../util';
@@ -189,17 +189,110 @@ function _readTileData(byteNumber: i32): i32 {
189189

190190
function _storeFetchIntoFifo(): void {
191191
if (PixelFetcher.isSprite) {
192-
// TODO: Do some Mixing
192+
// Need to mix the pixel on top of the old data
193+
194+
// Get the location of where we will be mixing
195+
// Which is the first 8 pixels in the fifo
196+
let pixelFifoIndex = PixelPipeline.pixelFifoIndex * 4;
197+
198+
// Get our priority per pixel, and type per pixel
199+
let priorityPerPixel = eightBitLoadFromGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 2);
200+
let typePerPixel = eightBitLoadFromGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 3);
201+
202+
// Go one by one for the 8 pixels in the current fifo
203+
for (let i = 0; i < 8; i++) {
204+
// Don't draw a sprite, over a sprite
205+
if (checkBitOnByte(i, typePerPixel)) {
206+
continue;
207+
}
208+
209+
// Get the Palette Color Ids of the pixel in our current sprite
210+
// Colors are represented by getting X position of ByteTwo, and X positon of Byte One
211+
// To Get the color Id.
212+
// For example, the result of the color id is 0000 00[xPixelByteTwo][xPixelByteOne]
213+
// See: How to draw a tile/sprite from memory: http://www.codeslinger.co.uk/pages/projects/gameboy/graphics.html
214+
let spritePaletteColorId = 0;
215+
if (checkBitOnByte(i, PixelFetcher.tileDataByteOne)) {
216+
// Byte one represents the second bit in our color id, so bit shift
217+
spritePaletteColorId += 1;
218+
spritePaletteColorId = spritePaletteColorId << 1;
219+
}
220+
if (checkBitOnByte(i, PixelFetcher.tileDataByteZero)) {
221+
spritePaletteColorId += 1;
222+
}
223+
224+
// Palette ColorId zero (last two bits of pallette) of a sprite are always transparent
225+
// http://gbdev.gg8.se/wiki/articles/Video_Display
226+
if (spriteColorId !== 0) {
227+
continue;
228+
}
229+
230+
// Load the data for the pixel
231+
let fifoTileDataByteZero = eightBitLoadFromGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 0);
232+
let fifoTileDataByteOne = eightBitLoadFromGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 1);
233+
234+
// Get the Palette Color Ids of the pixel in the Fifo
235+
let fifoPaletteColorId = 0;
236+
if (checkBitOnByte(i, fifoTileDataByteOne)) {
237+
// Byte one represents the second bit in our color id, so bit shift
238+
fifoPaletteColorId += 1;
239+
fifoPaletteColorId = fifoPaletteColorId << 1;
240+
}
241+
if (checkBitOnByte(i, fifoTileDataByteZero)) {
242+
fifoPaletteColorId += 1;
243+
}
244+
245+
// NOTE:
246+
// We are trying to draw a sprite pixel over a BG/Window pixel
247+
// There are multiple cases where we NEED to draw a sprite pixel over a Background
248+
// 1. The LCDC Bit 0 - BG/Window Display/Priority is cleared, thus BG priority is ignored
249+
// 2. The Sprite Priority bit is NOT set. If it is, we can only draw over BG color id 0.
250+
// 3. (CGB Only) The BG Priority bit is NOT set. If it is, If it is, we can only draw over BG color id 0.
251+
let shouldShowRelativeToLcdcPriority = Cpu.GBCEnabled && !Lcd.bgDisplayEnabled;
252+
let shouldShowRelativeToOamPriority = !checkBitOnByte(6, PixelFetcher.tileAttributes) || fifoPaletteColorId === 0;
253+
let shouldShowRelativeToBgPriority = !checkBitOnByte(i, priorityPerPixel) || fifoPaletteColorId === 0;
254+
255+
if (shouldShowRelativeToLcdcPriority || (shouldShowRelativeToOamPriority && shouldShowRelativeToBgPriority)) {
256+
// Mix the pixel!
257+
258+
// Replace the pixel data in the fifo with out sprite
259+
if (checkBitOnByte(1, spritePaletteColorId)) {
260+
setBitOnByte(i, fifoTileDataByteOne);
261+
} else {
262+
resetBitOnByte(i, fifoTileDataByteOne);
263+
}
264+
if (checkBitOnByte(0, spritePaletteColorId)) {
265+
setBitOnByte(i, fifoTileDataByteZero);
266+
} else {
267+
resetBitOnByte(i, fifoTileDataByteZero);
268+
}
269+
270+
// Note: Don't need to worry about priority,
271+
// since sprite can't draw over sprites
272+
273+
// Set that we are a sprite
274+
setBitOnByte(i, typePerPixel);
275+
276+
// Write back to the fifo
277+
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex, fifoTileDataByteZero);
278+
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 1, fifoTileDataByteOne);
279+
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 3, typePerPixel);
280+
}
281+
}
193282
} else {
194283
// Simply add the pixels to the end of the fifo
195-
// * 3, because Fifo has the 2 data tile bytes, and for WasmBoy Specifically,
196-
// We add the attributes byte for GBC BG
197-
let pixelFifoLocation = PixelPipeline.numberOfPixelsInFifo * 3;
198-
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoLocation, PixelFetcher.tileDataByteZero);
199-
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoLocation + 1, PixelFetcher.tileDataByteOne);
200-
if (Cpu.GBCEnabled) {
201-
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoLocation + 1, PixelFetcher.tileAttributes);
284+
// * 4, because Fifo has the 2 data tile bytes, and for WasmBoy Specifically,
285+
// A third byte representing the priority for each pixel (0 = no priority bit, 1 = priority bit)
286+
// and a 4th byte representing the type of pixel (0 = BG/Window, 1 = Sprite)
287+
let pixelFifoIndex = PixelPipeline.numberOfPixelsInFifo * 4;
288+
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex, PixelFetcher.tileDataByteZero);
289+
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 1, PixelFetcher.tileDataByteOne);
290+
let tilePriority = 0;
291+
if (checkBitOnByte(7, PixelFetcher.tileAttributes)) {
292+
tilePriority = 0xff;
202293
}
294+
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 2, tilePriority);
295+
eightBitStoreIntoGBMemory(PIXEL_PIPELINE_ENTIRE_SCANLINE_FIFO_LOCATION + pixelFifoIndex + 3, 0);
203296
PixelPipeline.numberOfPixelsInFifo += 8;
204297
}
205298
}

0 commit comments

Comments
 (0)