It is currently Wed Apr 24, 2019 7:05 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Thu Dec 27, 2018 1:01 am 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 38
Location: Australia
Hi,

I was implementing sprite priority and testing Balloon Fight and found that the sprite for the Balloon in the title screen is behind the background. So it didn't show up in my emulator.

So I implemented transparency for backgrounds the same as I had in sprites. ie anything at palette addresses 3F00, 3F04, 3F08, 3F12 are considered transparent and show what is at palette 0. This showed the balloon, but the background changed from black to grey. Infact for the 3 different games I tested all the backgrounds went grey. This seems a logical outcome as the color at palette index 0 (3F00) is grey.

Am I on the right track here?

The last part of my getBackgroundPixel() method

Code:
        let attributeIndex = UInt8((shiftRegisterPaletteA >> shift) & 0x03)
        let address = UInt16(pattern | attributeIndex << 2)

        // Every 4th palette index maps to background color
        if address % 4 == 0
        {
            return 0
        }

        let paletteIndex = mapper!.readByte( atLocation:UInt16(0x3F00) + address)
        return Int(paletteIndex)
    }


And my drawPixel() method:

Code:
    private func drawPixel()
    {
        guard case 1...256 = cycle else { return }

        let x = cycle - 1
        let y = scanline

        let backgroundPixel = getBackgroundPixel()
        let (sprite, spritePixel, spriteZero) = getSpritePixel()

        var pixel = 0

        if spritePixel != 0 && backgroundPixel == 0
        {
            pixel = spritePixel
        }
        else if spritePixel == 0 && backgroundPixel != 0
        {
            pixel = backgroundPixel
        }
        else
        {
            if spriteZero == true
            {
                spriteZeroHit = true
            }
            pixel = sprite?.behind == true ? backgroundPixel : spritePixel
        }

        let color = Palette.color( atIndex:pixel)

        pixelBuffer.setPixel( x:x, y:y, r:color[0], g:color[1], b:color[2])
    }



Attachment:
Galaga Grey.png
Galaga Grey.png [ 266.76 KiB | Viewed 3615 times ]

Attachment:
BalloonFightGrey.png
BalloonFightGrey.png [ 16.58 KiB | Viewed 3609 times ]

Attachment:
DonkeyKongGrey.png
DonkeyKongGrey.png [ 17.68 KiB | Viewed 3609 times ]


Last edited by iOSBrett on Thu Dec 27, 2018 1:14 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Thu Dec 27, 2018 1:13 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8270
Location: Seattle
Simple stupid guess:
Are you displaying color 0, or the contents of index 0 of the palette?

(edit: reads source) yup, that's what you're doing:
iOSBrett wrote:
let attributeIndex = UInt8((shiftRegisterPaletteA >> shift) & 0x03)
let address = UInt16(pattern | attributeIndex << 2)

// Every 4th palette index maps to background color
if address % 4 == 0
{
return 0 ← note that here you're returning the index into the palette but immediately return
}

let paletteIndex = mapper!.readByte( atLocation:UInt16(0x3F00) + address) ←and here you dereference the index into the palette to get the corresponding hardware color
return Int(paletteIndex) ← which is what you return here
}


Top
 Profile  
 
PostPosted: Thu Dec 27, 2018 4:44 am 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 38
Location: Australia
@lidnariq I am intentionally doing that though, my code is wrong because my understanding of this part is wrong.

I am returning zero because my understanding is that anything in addresses 3F00, 3F04, 3F08, and 3F12 is a transparent pixel and is supposed to be drawn in the background color below a sprite with priority of 0. So returning 0 from this method tells my drawPixel() method that there is no background pixel and just draw the background color. Doing this allows me to see the balloon in the title screen of balloon fight. If I take this out then the background color is displayed correctly as black, but the balloon is not displayed.

Should I be returning the palette index (regardless of the address%4 test) to my drawPixel method and also a flag to say this address is a transparent pixel and display a sprite in front of it? This will work, but is that how the PPU is supposed to work?


Top
 Profile  
 
PostPosted: Thu Dec 27, 2018 4:59 am 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 38
Location: Australia
It does work, so I think this is what I am supposed to be doing, thanks @lidnariq


Top
 Profile  
 
PostPosted: Thu Dec 27, 2018 11:29 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 8270
Location: Seattle
iOSBrett wrote:
I am returning zero because my understanding is that anything in addresses 3F00, 3F04, 3F08, and 3F12 is a transparent pixel and is supposed to be drawn in the background color below a sprite with priority of 0. So returning 0 from this method tells my drawPixel() method that there is no background pixel and just draw the background color. Doing this allows me to see the balloon in the title screen of balloon fight. If I take this out then the background color is displayed correctly as black, but the balloon is not displayed.
My point is that the "return value"—even though you're just working with UInts here instead of really super strict pedantic types—isn't the same for the two return statements.

In the first return statement you're returning "0", and you mean "the 0th element in the array containing the software palette". Call that a "SoftwarePaletteIndex_t", if you'll forgive the C-ness.
In the second return statement you're returning "mapper!.readByte( atLocation:UInt16(0x3F00) + address)" which means "the hardware color corresponding for the SoftwarePaletteIndex_t at offset "address". Call this a "HardwareColor_t".

Wrong type, wrong result.


Top
 Profile  
 
PostPosted: Thu Dec 27, 2018 7:16 pm 
Offline
User avatar

Joined: Wed Apr 18, 2018 1:09 am
Posts: 38
Location: Australia
From reading the wiki I thought that I wasn't supposed to be reading from the addresses at 3F00, 3F04, 3F08, 3F12 and using background color instead. But re-reading that again, it does not include 3F00. Instead I should be reading from 3F00 when reading from 3F04, 3F08, and 3F12. Bingo!!! Just as I was writing that I realise the mistake in my understanding, and surprise surprise it was what you were trying to tell me from the start @lidnariq.

My return code in getBackgroundPixel() now looks like this and works without any kind of hack in my drawPixel code. Return type is a tupple, index into hardware palette and transparency.

Code:
        let attributeIndex = UInt8((shiftRegisterPaletteA >> shift) & 0x03)
        let index = UInt16(pattern | attributeIndex << 2)

        // Every 4th palette index maps to background color
        if index % 4 == 0
        {
            let paletteIndex = mapper!.readByte( atLocation:UInt16(0x3F00))
            return (Int(paletteIndex), index % 4 == 0)
        }

        let paletteIndex = mapper!.readByte( atLocation:UInt16(0x3F00) + index)
        return (Int(paletteIndex), index % 4 == 0)
    }


Sorry that took so long trying to get that through my thick skull!!!! Just wait until I start with the questions around why my 8x16 sprites don't work.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group