#ifndef GBA_VIDEO_H #define GBA_VIDEO_H #include "gba-memory.h" #include enum { VIDEO_CYCLES_PER_PIXEL = 4, VIDEO_HORIZONTAL_PIXELS = 240, VIDEO_HBLANK_PIXELS = 68, VIDEO_HDRAW_LENGTH = 1006, VIDEO_HBLANK_LENGTH = 226, VIDEO_HORIZONTAL_LENGTH = 1232, VIDEO_VERTICAL_PIXELS = 160, VIDEO_VBLANK_PIXELS = 68, VIDEO_VERTICAL_TOTAL_PIXELS = 228, VIDEO_TOTAL_LENGTH = 280896, REG_DISPSTAT_MASK = 0xFF38, BASE_TILE = 0x00010000 }; enum ObjMode { OBJ_MODE_NORMAL = 0, OBJ_MODE_SEMITRANSPARENT = 1, OBJ_MODE_OBJWIN = 2 }; enum ObjShape { OBJ_SHAPE_SQUARE = 0, OBJ_SHAPE_HORIZONTAL = 1, OBJ_SHAPE_VERTICAL = 2 }; union GBAColor { struct { unsigned r : 5; unsigned g : 5; unsigned b : 5; }; uint16_t packed; }; struct GBAObj { unsigned y : 8; unsigned transformed : 1; unsigned disable : 1; enum ObjMode mode : 2; unsigned mosaic : 1; unsigned multipalette : 1; enum ObjShape shape : 2; int x : 9; int : 3; unsigned hflip : 1; unsigned vflip : 1; unsigned size : 2; unsigned tile : 10; unsigned priority : 2; unsigned palette : 4; int : 16; }; struct GBATransformedObj { unsigned y : 8; unsigned transformed : 1; unsigned doublesize : 1; enum ObjMode mode : 2; unsigned mosaic : 1; unsigned multipalette : 1; enum ObjShape shape : 2; int x : 9; unsigned matIndex : 5; unsigned size : 2; unsigned tile : 10; unsigned priority : 2; unsigned palette : 4; int : 16; }; union GBAOAM { struct GBAObj obj[128]; struct GBATransformedObj tobj[128]; struct GBAOAMMatrix { int : 16; int : 16; int : 16; int a : 16; int : 16; int : 16; int : 16; int b : 16; int : 16; int : 16; int : 16; int c : 16; int : 16; int : 16; int : 16; int d : 16; } mat[32]; uint16_t raw[512]; }; #define GBA_TEXT_MAP_TILE(MAP) ((MAP) & 0x03FF) #define GBA_TEXT_MAP_HFLIP(MAP) ((MAP) & 0x0400) #define GBA_TEXT_MAP_VFLIP(MAP) ((MAP) & 0x0800) #define GBA_TEXT_MAP_PALETTE(MAP) (((MAP) & 0xF000) >> 12) union GBARegisterDISPCNT { struct { unsigned mode : 3; unsigned cgb : 1; unsigned frameSelect : 1; unsigned hblankIntervalFree : 1; unsigned objCharacterMapping : 1; unsigned forcedBlank : 1; unsigned bg0Enable : 1; unsigned bg1Enable : 1; unsigned bg2Enable : 1; unsigned bg3Enable : 1; unsigned objEnable : 1; unsigned win0Enable : 1; unsigned win1Enable : 1; unsigned objwinEnable : 1; }; uint16_t packed; }; union GBARegisterDISPSTAT { struct { unsigned inVblank : 1; unsigned inHblank : 1; unsigned vcounter : 1; unsigned vblankIRQ : 1; unsigned hblankIRQ : 1; unsigned vcounterIRQ : 1; unsigned : 2; unsigned vcountSetting : 8; }; uint32_t packed; }; union GBARegisterBGCNT { struct { unsigned priority : 2; unsigned charBase : 2; unsigned : 2; unsigned mosaic : 1; unsigned multipalette : 1; unsigned screenBase : 5; unsigned overflow : 1; unsigned size : 2; }; uint16_t packed; }; struct GBAVideoRenderer { void (*init)(struct GBAVideoRenderer* renderer); void (*deinit)(struct GBAVideoRenderer* renderer); uint16_t (*writeVideoRegister)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value); void (*writePalette)(struct GBAVideoRenderer* renderer, uint32_t address, uint16_t value); void (*writeOAM)(struct GBAVideoRenderer* renderer, uint32_t oam); void (*drawScanline)(struct GBAVideoRenderer* renderer, int y); void (*finishFrame)(struct GBAVideoRenderer* renderer); uint16_t* palette; uint16_t* vram; union GBAOAM* oam; }; struct GBAVideo { struct GBA* p; struct GBAVideoRenderer* renderer; // DISPSTAT int inHblank; int inVblank; int vcounter; int vblankIRQ; int hblankIRQ; int vcounterIRQ; int vcountSetting; // VCOUNT int vcount; int32_t lastHblank; int32_t nextHblank; int32_t nextEvent; int32_t eventDiff; int32_t nextHblankIRQ; int32_t nextVblankIRQ; int32_t nextVcounterIRQ; uint16_t palette[SIZE_PALETTE_RAM >> 1]; uint16_t* vram; union GBAOAM oam; }; void GBAVideoInit(struct GBAVideo* video); void GBAVideoDeinit(struct GBAVideo* video); void GBAVideoAssociateRenderer(struct GBAVideo* video, struct GBAVideoRenderer* renderer); int32_t GBAVideoProcessEvents(struct GBAVideo* video, int32_t cycles); void GBAVideoWriteDISPSTAT(struct GBAVideo* video, uint16_t value); uint16_t GBAVideoReadDISPSTAT(struct GBAVideo* video); struct GBASerializedState; void GBAVideoSerialize(struct GBAVideo* video, struct GBASerializedState* state); void GBAVideoDeserialize(struct GBAVideo* video, struct GBASerializedState* state); #endif