ref: b70aae808d4ac2c7296b02e75cc52fc78809b886
dir: /snes/ppu.h/
#ifndef PPU_H
#define PPU_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
typedef struct Ppu Ppu;
#include "snes.h"
#include "../types.h"
typedef struct BgLayer {
uint16_t hScroll;
uint16_t vScroll;
bool tilemapWider;
bool tilemapHigher;
uint16_t tilemapAdr;
uint16_t tileAdr;
bool bigTiles_always_zero;
bool mosaicEnabled;
} BgLayer;
typedef struct Layer {
bool screenEnabled[2]; // 0 = main, 1 = sub
bool screenWindowed[2]; // 0 = main, 1 = sub
} Layer;
typedef struct WindowLayer {
bool window1enabled;
bool window2enabled;
bool window1inversed;
bool window2inversed;
uint8_t maskLogic_always_zero;
} WindowLayer;
enum {
kPpuXPixels = 256 + kPpuExtraLeftRight * 2,
};
typedef struct PpuPixelPrioBufs {
uint8_t pixel[kPpuXPixels];
uint8_t prio[kPpuXPixels];
} PpuPixelPrioBufs;
enum {
kPpuRenderFlags_NewRenderer = 1,
// Render mode7 upsampled by 4x4
kPpuRenderFlags_4x4Mode7 = 2,
// Use 240 height instead of 224
kPpuRenderFlags_Height240 = 4,
};
struct Ppu {
bool lineHasSprites;
uint8_t lastBrightnessMult;
uint8_t lastMosaicModulo;
uint8_t renderFlags;
uint32_t renderPitch;
uint8_t *renderBuffer;
uint8_t extraLeftCur, extraRightCur, extraLeftRight, extraBottomCur;
float mode7PerspectiveLow, mode7PerspectiveHigh;
Snes* snes;
// store 31 extra entries to remove the need for clamp
uint8_t brightnessMult[32 + 31];
uint8_t brightnessMultHalf[32 * 2];
PpuPixelPrioBufs bgBuffers[2];
// vram access
uint16_t vram[0x8000];
uint16_t vramPointer;
bool vramIncrementOnHigh;
uint16_t vramIncrement;
uint8_t vramRemapMode;
uint16_t vramReadBuffer;
// cgram access
uint16_t cgram[0x100];
uint8_t cgramPointer;
bool cgramSecondWrite;
uint8_t cgramBuffer;
// oam access
uint16_t oam[0x100];
uint8_t highOam[0x20];
uint8_t oamAdr;
uint8_t oamAdrWritten;
bool oamInHigh;
bool oamInHighWritten;
bool oamSecondWrite;
uint8_t oamBuffer;
// object/sprites
bool objPriority;
uint16_t objTileAdr1;
uint16_t objTileAdr2;
uint8_t objSize;
PpuPixelPrioBufs objBuffer;
bool timeOver;
bool rangeOver;
bool objInterlace_always_zero;
// background layers
BgLayer bgLayer[4];
uint8_t scrollPrev;
uint8_t scrollPrev2;
uint8_t mosaicSize;
uint8_t mosaicStartLine;
// layers
Layer layer[5];
// mode 7
int16_t m7matrix[8]; // a, b, c, d, x, y, h, v
uint8_t m7prev;
bool m7largeField;
bool m7charFill;
bool m7xFlip;
bool m7yFlip;
bool m7extBg_always_zero;
// mode 7 internal
int32_t m7startX;
int32_t m7startY;
// windows
WindowLayer windowLayer[6];
uint8_t window1left;
uint8_t window1right;
uint8_t window2left;
uint8_t window2right;
// color math
uint8_t clipMode;
uint8_t preventMathMode;
bool addSubscreen;
bool subtractColor;
bool halfColor;
bool mathEnabled[6];
uint8_t fixedColorR;
uint8_t fixedColorG;
uint8_t fixedColorB;
// settings
bool forcedBlank;
uint8_t brightness;
uint8_t mode;
bool bg3priority;
bool evenFrame;
bool pseudoHires_always_zero;
bool overscan_always_zero;
bool frameOverscan_always_zero; // if we are overscanning this frame (determined at 0,225)
bool interlace_always_zero;
bool frameInterlace_always_zero; // if we are interlacing this frame (determined at start vblank)
bool directColor_always_zero;
// latching
uint16_t hCount;
uint16_t vCount;
bool hCountSecond;
bool vCountSecond;
bool countersLatched;
uint8_t ppu1openBus;
uint8_t ppu2openBus;
uint8_t mosaicModulo[kPpuXPixels];
uint32_t colorMapRgb[256];
};
Ppu* ppu_init(Snes* snes);
void ppu_free(Ppu* ppu);
void ppu_reset(Ppu* ppu);
void ppu_handleVblank(Ppu* ppu);
void ppu_runLine(Ppu* ppu, int line);
uint8_t ppu_read(Ppu* ppu, uint8_t adr);
void ppu_write(Ppu* ppu, uint8_t adr, uint8_t val);
void ppu_saveload(Ppu *ppu, SaveLoadFunc *func, void *ctx);
bool PpuBeginDrawing(Ppu *ppu, uint8_t *buffer, size_t pitch, uint32_t render_flags);
void PpuSetMode7PerspectiveCorrection(Ppu *ppu, int low, int high);
void PpuSetExtraSideSpace(Ppu *ppu, int left, int right, int bottom);
#endif