From 909cf66df05a7b1eb3ba3cef38dc3ce925608a37 Mon Sep 17 00:00:00 2001 From: Joaquin Date: Mon, 13 Mar 2023 01:50:12 +0200 Subject: [PATCH] [ppu] Begin work on rendering engine Began work on the PPU clock and rendering engine, currently does nothing major but the skeleton is here, closer and closer to finishing the main idea of the PPU. --- ppu.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/ppu.c b/ppu.c index ec8e57d..0f4444e 100644 --- a/ppu.c +++ b/ppu.c @@ -4,11 +4,11 @@ #include "cartridge.h" //needs acces to the cartridge to load CHR maps, since r/w functions are in-house instead of bus-wide like it is for busRead/Write it needs to be imported here too, quite like there are physical wires connecting the cartridge CHR bank pins to the PPU #define PPU_BUS_SIZE (0x3FFF) -byte ppuBus[PPU_BUS_SIZE]; +static byte ppuBus[PPU_BUS_SIZE]; PPU ppu; -inline word resolveNameTableAddress(word regData){ +static inline word resolveNameTableAddress(word regData){ return (regData & 0b0000111111111111) | (1 << (14 - 1)); } @@ -25,7 +25,7 @@ inline word resolveNameTableAddress(word regData){ fixed */ -word resolveAttributeTableAddress(word regData){ +static word resolveAttributeTableAddress(word regData){ locationRegister n; n.data = regData; byte trimmedCoarseX = n.field.coarseX >> 2; //trim the lowest 2 bits of coarse X @@ -65,7 +65,7 @@ fixed // // ---- -byte ppuRead(word address){ +static byte ppuRead(word address){ word cartResponse; @@ -84,7 +84,7 @@ byte ppuRead(word address){ } -void ppuWrite(word address, byte data){ +static void ppuWrite(word address, byte data){ if(!mapper000_Write(address, data, true)){ @@ -206,9 +206,10 @@ byte ppuRegRead(word address){ //send the registers to the bus so the components case 2: //ppustatus - return ppu.status.full; + returnData = ppu.status.full; ppu.status.vblank = 0; ppu.expectingLsb = false; + return returnData; break; @@ -263,6 +264,13 @@ void dumpPpuBus(){ } +//Clean up any left over memory from a reset +static void sterlize_ppu(){ + for(unsigned int i = 0; i < PPU_BUS_SIZE; i++){ + ppuBus[i] = 0x00; + } +} + void initPpu(){ ppu.dataByteBuffer = 0; ppu.expectingLsb = 0; @@ -270,11 +278,90 @@ void initPpu(){ ppu.dataByteBuffer = 0; ppu.mask.full = 0; ppu.status.full = 0; + sterlize_ppu(); } +static int cycle = 0; +static int scanline = 0; + +static byte NTbuf; +static byte ATbuf; +static byte bgLSBbuf; +static byte bgMSBbuf; + void ppuClock(){ //one tick of the PPU clock +#if 0 + if(cycle % 8){ + if(cycle > 0){ + if(cycle - 1 % 2){ + //High Byte + }else{ + //Low Byte + } + }else{ + //H-BLANK + } + } +#endif + if(scanline >= 0 && scanline <= 239){ + //visible area + if(scanline == -1 && cycle == 1) + ppu.status.vblank = 0; + + if((cycle >= 2 && cycle <= 257) || (cycle >= 321 && cycle <= 337)){ + switch((cycle - 1) % 8){ + + case 0: + //READ NameTable BYTE + NTbuf = ppuBus[resolveNameTableAddress(ppu.vReg.data)]; + break; + + + case 2: + //READ AttributeTable BYTE + ATbuf = ppuBus[resolveAttributeTableAddress(ppu.vReg.data)]; + break; + + + case 4: + //READ bg lsb + bgLSBbuf = ppuBus[(ppu.control.backgroundPatternTable << 12) + (word)(NTbuf << 4) + ppu.vReg.field.fineY + 0]; + break; + + + + case 6: + bgMSBbuf = ppuBus[(ppu.control.backgroundPatternTable << 12) + (word)(NTbuf << 4) + ppu.vReg.field.fineY + 8]; + break; + + case 7: + + break; + + default: + //In-between cycles + break; + } + } + } + + //SCANLINE over and reset counters + if(cycle >= 341){ + cycle -= 341; + scanline++; + } + + if(scanline == 241){ + ppu.control.nmiVerticalBlank = true; + ppu.status.vblank = true; + } + if(scanline >= 262){ + scanline = 0; + ppu.status.vblank = false; + ppu.control.nmiVerticalBlank = false; + } } \ No newline at end of file