bool DMA::doOAMTransfer() { int t_c = static_cast<int>(m_vecDMATransfers[OAMDMA].size()); if (t_c > 0) { ITexture* pTexture = getTexture(OAMDMA, 0); if (NULL == pTexture) { return false; } uint32_t* pTextureData; int iStride; if (false == pTexture->getBuffer(pTextureData, iStride)) { return false; } for (int iLoop = 0; iLoop < t_c; ++iLoop) { const DMATransfer& dmaTransfer = m_vecDMATransfers[OAMDMA][iLoop]; if (NULL == dmaTransfer.pSource) { continue; } else { if (-1 == dmaTransfer.iHeight) { doDMATransfer(pTexture, dmaTransfer.pSource, pTextureData, iStride, dmaTransfer.iStartTile, dmaTransfer.iWidth, OAMDMA); } else { doDMATransfer(pTexture, dmaTransfer.pSource, pTextureData, iStride, dmaTransfer.iStartTile, dmaTransfer.iWidth, dmaTransfer.iHeight, OAMDMA); } } } pTexture->releaseBuffer(); } m_vecDMATransfers[OAMDMA].clear(); return true; }
void writeByte(struct gameboy * gameboy, uint16_t address, uint8_t data) { //0000-8000 is read only if (address < CARTRIDGE_SIZE){ handleBankWrite(gameboy, address, data); } //anything written to echo RAM should be written to work RAM. else if ((address >= ECHO_RAM_START_UPPER) && (address < ECHO_RAM_END_UPPER)){ gameboy->memory.mem[address] = data; gameboy->memory.mem[address - ECHO_OFFSET] = data; } else if ((address >= ECHO_RAM_START_LOWER) && (address < ECHO_RAM_END_LOWER)){ gameboy->memory.mem[address] = data; gameboy->memory.mem[address + ECHO_OFFSET] = data; } else if ((address >= RESTRICTED_START) && (address < RESTRICTED_END)){ //printf("sp: %x\n", gameboy->cpu.sp); //printf("WriteMemory: address %x is within restricted memory %x - %x\n", address, RESTRICTED_START, RESTRICTED_END); // fprintf(stderr, "WriteMemory: address %x is within restricted memory %x - %x\n", address, RESTRICTED_START, RESTRICTED_END); //printDebugTrace(gameboy); } else if (address == TMC){ //the game is trying to change the timer controller int currentFreq = getTimerFrequency(gameboy); gameboy->memory.mem[TMC] = data; int newFreq = getTimerFrequency(gameboy); if (newFreq != currentFreq){ initialiseTimerCounter(gameboy); } } else if (address == DIV_REG){ //any writes to the divider register resets it to 0 gameboy->memory.mem[DIV_REG] = 0; } else if (address == DMA_ADDRESS){ doDMATransfer(gameboy, data); } else if (address == CONTROL_REG){ gameboy->screen.control = data; } else if (address == CURRENT_SCANLINE){ //printf("resetting scanline\n"); gameboy->screen.currentScanline = 0; } else if (address == STATUS_REG){ gameboy->screen.status = data; } else { gameboy->memory.mem[address] = data; } }
bool DMA::doBGTransfer() { int t_c = static_cast<int>(m_vecDMATransfers[BGDMA].size()); int iCurrentBG = -1; if (t_c > 0) { qsort(&m_vecDMATransfers[BGDMA][0], m_vecDMATransfers[BGDMA].size(), sizeof(DMATransfer*), dmaSort); ITexture* pTexture = NULL; uint32_t* pTextureData = NULL; int iStride; for (int iLoop = 0; iLoop < t_c; ++iLoop) { const DMATransfer& dmaTransfer = m_vecDMATransfers[BGDMA][iLoop]; if (dmaTransfer.iBG != iCurrentBG) { iCurrentBG = dmaTransfer.iBG; if (pTexture != NULL) { pTexture->releaseBuffer(); } pTexture = getTexture(BGDMA, dmaTransfer.iBG); if (NULL == pTexture) { return false; } if (false == pTexture->getBuffer(pTextureData, iStride)) { return false; } } ASSERT_LOG(pTexture != NULL && pTextureData != NULL, "Texture wasn't set"); if (NULL == dmaTransfer.pSource) { doVRAMClear(pTextureData, iStride, dmaTransfer.iStartTile, dmaTransfer.iWidth, dmaTransfer.iHeight, BGDMA); } else { if (-1 == dmaTransfer.iHeight) { doDMATransfer(pTexture, dmaTransfer.pSource, pTextureData, iStride, dmaTransfer.iStartTile, dmaTransfer.iWidth, BGDMA); } else { doDMATransfer(pTexture, dmaTransfer.pSource, pTextureData, iStride, dmaTransfer.iStartTile, dmaTransfer.iWidth, dmaTransfer.iHeight, BGDMA); } } } if (pTexture != NULL) { pTexture->releaseBuffer(); } } m_vecDMATransfers[BGDMA].clear(); return true; }