Gameboy Development Forum

Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)

You are not logged in.

#1 2024-08-15 04:10:50

Finalspace
New member
Registered: 2024-08-15
Posts: 3

Why is the SCX/SCY register cleared by Super Mario Land

I wrote a game boy emulator in C99 that works and a lot of games can play just fine, including sound.
But there are a few issues and one issue that particular bugs me is that i want to show the background-map in my editor, while running the game - seeing the actual viewport.

I already implemented this and it works great for a lot of games (Super Mario Land 2, R-Type, Mega-Man to name a few).

But not for "Super Mario Land 1"! The Game somehow resets the SCX and SCY register to zero after the frame is rendered - so when i use SCX and SCY to compute the viewport rectangles, it will always be zero or has the correct value, but then gets reset on the next frame - so it flickers around.

Other emulators such as BGB works just fine and displays the background-map with the viewport properly.

My implementation of this stores the current SCX/SCY values into separate fields that are updated, after the frame is rendered.
A frame is rendered when the PPU is in mode VBlank and LY is >= 154:

Code:

static void fgb__PPUModeVerticalBlank(fgbGameboy *gameboy) {
    fgbPPU *ppu = &gameboy->ppu;
    fgbLCDRegister *lcd = &ppu->lcd;

    if (ppu->lineTicks >= FGB__PPU_HORIZONTAL_BLANK_DOTS) {
        fgb__PPUIncrementLine(gameboy);

        if (lcd->ly >= FGB__PPU_VERTICAL_BLANK_LINE_COUNT) {
            fgb__PPUSetMode(gameboy, lcd, fgbPPUMode_OAMSearch);

            fgb__PPUResetLine(gameboy);

            fgb__PPUStatusInterruptTest(gameboy, false);

            ppu->frameCount++;
            ppu->isFrameFinished = true;

            // Store scroll register for rendering the background-map viewport
            ppu->backgroundMap.scrollX = ppu->lcd.scx;
            ppu->backgroundMap.scrollY = ppu->lcd.scy;

            fgb__Breakpoint(gameboy, fgbBreakpointType_PPUFrameEnd);
        }

        ppu->lineTicks = 0;
    }
}

I assume that the problem is, that the registers are set by the game - but it should not should not.

So my question is, when are the game allowed to update the SCX/SCY register and when is it not allowed?

Or do i have to save the SCX/SCY registers much earlier?

My implementation for the SCX/SCY bus read/write is really simple:

Code:

static uint8_t fgb__PPULCDRegisterRead(uint16_t address) {
    switch (address) {
        ...
        case 0xFF42:
            return lcd->scy;
        case 0xFF43:
            return lcd->scx;
        ...
    }
}

static void fgb__PPULCDRegisterWrite(const uint16_t address, uint8_t value) {
    switch (address) {
        ...
        case 0xFF42:
            lcd->scy = value;
            break;
        case 0xFF43:
            lcd->scx = value;
            break;
        ...
    }
}

Offline

 

#2 2024-08-15 04:14:15

Finalspace
New member
Registered: 2024-08-15
Posts: 3

Re: Why is the SCX/SCY register cleared by Super Mario Land

Ignore it... writing this post actually fixed it for me, because i simply moved the "frame finished" to the mode HBlank when LY >= 144.

This works correctly roll

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson