void updateGraphicsTest(struct gameboy * gameboy) { //fill a frame buffer with some simple pixel data and see if it draws correctly setLCDStatus(gameboy); uint8_t previousMode = getCurrentMode(gameboy); requestAnyNewModeInterrupts(gameboy, previousMode); if (isLCDEnabled(gameboy)){ gameboy->screen.scanlineCounter += gameboy->cpu.previousInstruction.cycles; } else { return; } if (gameboy->screen.scanlineCounter >= SCANLINE_CYCLE_TIME){ gameboy->screen.currentScanline++; gameboy->screen.scanlineCounter = 0; if (gameboy->screen.currentScanline == Y){ requestInterrupt(gameboy, int_vblank); //printf("start vblank\n"); } else if (gameboy->screen.currentScanline > (Y + NO_OF_INVISIBLE_SCANLINES)){ gameboy->screen.currentScanline = 0; //printf("resetting scanline\n"); } else if (gameboy->screen.currentScanline < Y){ // printf("drawing scanline %d\n", gameboy->screen.currentScanline); drawScanline(gameboy); } else { //printf("In vblank\n"); } } }
void Video::updateGraphics(const int &cycles, CPU &cpuTemp) { setLCDStatus(cpuTemp); if (isLCDEnabled()) _scanLineCounter -= cycles; else return; if (_scanLineCounter <= 0) { // time to move onto next scanline _memory->directModification(LY, _memory->read(LY) + 1); BYTE currentline = _memory->read(LY); _scanLineCounter = 456; // we have entered vertical blank period if (currentline == 144) cpuTemp.requestInterrupt(VBlank); // if gone past scanline 153 reset to 0 else if (currentline > 153) _memory->directModification(LY, 0x00); // draw the current scanline else if (currentline < 144) drawScanLine(); } }
void updateGraphics(struct gameboy * gameboy) { int cycles = gameboy->cpu.previousInstruction.cycles; uint8_t previousMode = getCurrentMode(gameboy); setLCDStatus(gameboy); requestAnyNewModeInterrupts(gameboy, previousMode); doCoincidenceFlag(gameboy); if (isLCDEnabled(gameboy)){ gameboy->screen.scanlineCounter += cycles; doScanline(gameboy); } }
void setLCDStatus(struct gameboy * gameboy) { //it take 456 clock cycles to draw 1 scanline //LCD status is in mode 2 for the first 80 (search sprite attrs) //Mode 3 is set for the next 172 (transfer to LCD driver) //The remaining 204 are for mode 0 (hBlank) //When the status mode is changed to 0, 1 or 2, an interrupt request occurs //Check bit 3, 4, or 5 to see if mode interrupt 0, 1 or 2 is enabled //when the lcd mode is disabled, the status mode must be set to 1 if (!isLCDEnabled(gameboy)){ //starting a new scan line sets the lcd status to 2 //printf("LCD isn't enabled - starting new scanline\n"); startNewScanline(gameboy); } else { // printf("LCD is enabled\n"); if (isInVBlankBounds(gameboy)){ //printf("Handle vblank\n"); handleVBlank(gameboy); } else if (isInSpriteAttributeBounds(gameboy)){ //printf("Handle OAM\n"); handleSpriteSearch(gameboy); } else if (isInDriverTransferBounds(gameboy)){ //printf("handle transfer\n"); handleTransferToLCDDriver(gameboy); } else { //printf("handle hblank\n"); handleHBlank(gameboy); } } }
void Video::setLCDStatus(CPU &cpuTemp) { BYTE status = _memory->read(0xFF41); if (!isLCDEnabled()) { // set the mode to 1 during lcd disabled and reset scanline _scanLineCounter = 456; _memory->directModification(LY, 0x00); status &= 0xFC; status = bitSet(status, 0); _memory->write(0xFF41, status); return; } BYTE currentline = _memory->read(LY); BYTE currentmode = status & 0x03; BYTE mode = 0x00; bool reqInt = false; // If is greater we are in VBLank period if (currentline >= 144) { mode = 0x01; status = bitSet(status, 0); status = bitReset(status, 1); reqInt = testBit(status, 4); } // Else, we are drawing scanlines in panel else { int mode2bounds = 456 - 80; int mode3bounds = mode2bounds - 172; // mode 2 if (_scanLineCounter >= mode2bounds) { mode = 0x02; status = bitSet(status, 1); status = bitReset(status, 0); reqInt = testBit(status, 5); } // mode 3 else if (_scanLineCounter >= mode3bounds) { mode = 0x03; status = bitSet(status, 1); status = bitSet(status, 0); } // mode 0 else { mode = 0x00; status = bitReset(status, 1); status = bitReset(status, 0); reqInt = testBit(status, 3); } } // just entered a new mode so request interupt if (reqInt && (mode != currentmode)) cpuTemp.requestInterrupt(LCD); // check the conincidence flag if (_memory->read(LY) == _memory->read(LYC)) { status = bitSet(status, 2); if (testBit(status, 6)) cpuTemp.requestInterrupt(LCD); } else { status = bitReset(status, 2); } _memory->write(0xFF41, status); }