nesdev.com
http://forums.nesdev.com/

[PPU Reg] Do you see anything absolutely wrong in this code?
http://forums.nesdev.com/viewtopic.php?f=3&t=14914
Page 1 of 1

Author:  zerojnt [ Wed Oct 05, 2016 2:35 pm ]
Post subject:  [PPU Reg] Do you see anything absolutely wrong in this code?

Hi people.

You have been help-me a lot to write my own nes emu. It's just a dummy emulator with an educational purpose. Thank you. Yesterday I got an amazing milestone for me: PPU is working! When I finished to implement the cpu; I feel like: it's alive! But now I can really see that IT'S ALIVE :P

Look how it's going on:
Image

There are some bugs; it's true. Now I'm working comparing the debug trace of Nitendulator and the mine; it's working well. What I want to ask to you is; can you identify something stupidly wrong in the way that I implemented the PPU registers?

I'm not asking for code or a deep analysis, just for a fast check and "Oh my god; You need to re-read everything about XYZ.

Here the functions that Write in PPU REGISTERS:

Code:
func WRITE_PPUCTRL(IO *IOPorts, value byte) {

   if Bit0(value) == 0 && Bit1(value) == 0 {
      IO.PPUCTRL.BASE_NAMETABLE_ADDR = 0x2000
   }
   if Bit0(value) == 1 && Bit1(value) == 0 {
      IO.PPUCTRL.BASE_NAMETABLE_ADDR = 0x2400
   }
   if Bit0(value) == 0 && Bit1(value) == 1 {   
      IO.PPUCTRL.BASE_NAMETABLE_ADDR = 0x2800
   }
   if Bit0(value) == 1 && Bit1(value) == 1 {
      IO.PPUCTRL.BASE_NAMETABLE_ADDR = 0x2C00
   }
   
   if Bit2(value) == 0 {
      IO.PPUCTRL.VRAM_INCREMENT = 1
   } else {
      IO.PPUCTRL.VRAM_INCREMENT = 32
   }
   
   if Bit3(value) == 0 {
      IO.PPUCTRL.SPRITE_8_ADDR = 0x0000
   } else {
      IO.PPUCTRL.SPRITE_8_ADDR = 0x1000
   }
   
   if Bit4(value) == 0 {
      IO.PPUCTRL.BACKGROUND_ADDR = 0x0000
   } else {
      IO.PPUCTRL.BACKGROUND_ADDR = 0x1000
   }
   
   if Bit5(value) == 0 {
      IO.PPUCTRL.SPRITE_SIZE = 8
   } else {
      IO.PPUCTRL.SPRITE_SIZE = 16
   }
   
   if Bit6(value) == 0 {
      IO.PPUCTRL.MASTER_SLAVE_SWITCH = 0
   } else {
      IO.PPUCTRL.MASTER_SLAVE_SWITCH = 1
   }
   
   if Bit7(value) == 0 {
      IO.PPUCTRL.GEN_NMI = false
   } else {
   IO.PPUCTRL.GEN_NMI = true
   }
}

func WRITE_PPUMASK(IO *IOPorts, value byte) {

   if Bit0(value) == 0 {
      IO.PPUMASK.GREYSCALE = false
   } else {
      IO.PPUMASK.GREYSCALE = true
   }
   
   if Bit1(value) == 0 {
      IO.PPUMASK.SHOW_LEFTMOST_8_BACKGROUND = false
   } else {
      IO.PPUMASK.SHOW_LEFTMOST_8_BACKGROUND = true
   }
   
   if Bit2(value) == 0 {
      IO.PPUMASK.SHOW_LEFTMOST_8_SPRITE = false
   } else {
      IO.PPUMASK.SHOW_LEFTMOST_8_SPRITE = true
   }
   
   if Bit3(value) == 0 {
      IO.PPUMASK.SHOW_BACKGROUND = false
   } else {
      IO.PPUMASK.SHOW_BACKGROUND = true
   }
   
   if Bit4(value) == 0 {
      IO.PPUMASK.SHOW_SPRITE = false
   } else {
      IO.PPUMASK.SHOW_SPRITE = true
   }
   
   if Bit5(value) == 0 {
      IO.PPUMASK.RED_BOOST = false
   } else {
      IO.PPUMASK.RED_BOOST = true
   }
   
   if Bit6(value) == 0 {
      IO.PPUMASK.GREEN_BOOST = false
   } else {
      IO.PPUMASK.GREEN_BOOST = true
   }
   
   if Bit7(value) == 0 {
      IO.PPUMASK.BLUE_BOOST = false
   } else {
      IO.PPUMASK.BLUE_BOOST = true
   }
}

func WRITE_OAMADDR(IO *IOPorts, value byte) {
   IO.PPU_OAM_ADDRESS = value
}

func WRITE_OAMDATA(IO *IOPorts, value byte) {
      IO.PPU_OAM[IO.PPU_OAM_ADDRESS] = value
      IO.PPU_OAM_ADDRESS++
}

func WRITE_PPUSCROLL(IO *IOPorts, value byte) {

   if IO.PPUSCROLL.NEXT_WRITES_Y == true {
      IO.PPUSCROLL.Y = value      
   } else {
      IO.PPUSCROLL.X = value      
   }
   IO.PPUSCROLL.NEXT_WRITES_Y = !IO.PPUSCROLL.NEXT_WRITES_Y
}

func WRITE_PPUADDR(IO *IOPorts, value byte) {

   if IO.PPU_MEMORY_STEP == 0 {
      // Records the lower byte
      IO.PPU_MEMORY_HIGHER = value
      IO.PPU_MEMORY_STEP = 1
   } else {
      // Record the Higher Byte
      IO.PPU_MEMORY_LOWER = (value << 2) >> 2
      IO.PPU_MEMORY_STEP = 0
      IO.VRAM_ADDRESS = LE(IO.PPU_MEMORY_LOWER, IO.PPU_MEMORY_HIGHER)
   }
}

func WRITE_PPUDATA(IO *IOPorts, cart *cartridge.Cartridge, value byte) {
   
   
   IO.PPU_RAM[ mapper.PPU(IO.VRAM_ADDRESS) ] = value
   IO.VRAM_ADDRESS += IO.PPUCTRL.VRAM_INCREMENT
}

func WRITE_OAMDMA(IO *IOPorts, cart *cartridge.Cartridge, value byte) {
   
   var cpuaddr uint16 = uint16(value) << 8
   for i:=0; i<256; i++ {
      prgrom, finaladdr := mapper.MemoryMapper(cart, cpuaddr)
      var data byte
      if prgrom == true {
         data = cart.PRG[finaladdr]
      } else {
         data = IO.CPU_RAM[finaladdr]
      }
      
      IO.PPU_OAM[IO.PPU_OAM_ADDRESS] = data
      IO.PPU_OAM_ADDRESS++
      cpuaddr++
   }
}


My functions to READ PPU REGISTERS:

Code:
func READ_PPUSTATUS(IO *IOPorts) byte {

   var result byte = 0
   result = SetBit(result, 0, Bit0(IO.PPUSTATUS.WRITTEN))
   result = SetBit(result, 1, Bit1(IO.PPUSTATUS.WRITTEN))
   result = SetBit(result, 2, Bit2(IO.PPUSTATUS.WRITTEN))
   result = SetBit(result, 3, Bit3(IO.PPUSTATUS.WRITTEN))
   result = SetBit(result, 4, Bit4(IO.PPUSTATUS.WRITTEN))
   
   if IO.PPUSTATUS.SPRITE_OVERFLOW == true {
      result = SetBit(result, 5,1)
   }
   
   if IO.PPUSTATUS.SPRITE_0_BIT == true {
      result = SetBit(result, 6,1)
   }
      
   if IO.PPUSTATUS.NMI_OCCURRED == true {
      result = SetBit(result, 7,1)
   }
   IO.PPUSTATUS.NMI_OCCURRED = false
   
   IO.PPUSCROLL.X = 0
   IO.PPUSTATUS.SPRITE_0_BIT = false
   IO.PPUSCROLL.Y = 0
   IO.VRAM_ADDRESS = 0
   
   return result   
}

func READ_OAMDATA(IO *IOPorts) byte {

      var result byte = IO.PPU_OAM[IO.PPU_OAM_ADDRESS]
      IO.PPU_OAM_ADDRESS++
      return result
}

func READ_PPUDATA(IO *IOPorts, cart *cartridge.Cartridge) byte {

   

   var newaddr uint16 = mapper.PPU (IO.VRAM_ADDRESS)


   var request byte = IO.PPU_RAM[ newaddr ]
   var result byte = IO.PREVIOUS_READ
   
   if newaddr < 0x3F00 {
      IO.PREVIOUS_READ = request
   } else {
      IO.PREVIOUS_READ = IO.PPU_RAM[ newaddr - 0x1000 ]
      result = request
   }
   
   //fmt.Printf("rnd [%x] = %x \n", newaddr, result)   
   IO.VRAM_ADDRESS += IO.PPUCTRL.VRAM_INCREMENT

   return result
}


Is there anything BIZARRE? O_O

(I made a lot of things not optimised; sometimes cause I want to keep it's very readable. Sometimes cause I don't know how to do something better :P

(it's an open source project; Now I'm working on PPU branch: https://github.com/jonathandasilvasanto ... rc/zerojnt )

Thank you!

Author:  Dwedit [ Wed Oct 05, 2016 2:56 pm ]
Post subject:  Re: [PPU Reg] Do you see anything absolutely wrong in this c

The nametable bits of PPUCTRL ($2000) directly affect two bits of loopy_t, there is no actual nametable selection status that you would store into your class.
Likewise, the scroll registers ($2005) also affect Loopy_T only, there's no scroll values or anything to store into your class.

Read this:
http://wiki.nesdev.com/w/index.php/PPU_ ... _registers

Author:  Quietust [ Wed Oct 05, 2016 4:32 pm ]
Post subject:  Re: [PPU Reg] Do you see anything absolutely wrong in this c

Also, "IO.PPUSCROLL.NEXT_WRITES_Y" and "IO.PPU_MEMORY_STEP" are the same register, and reading from $2002 needs to clear it.

Author:  zerojnt [ Wed Oct 05, 2016 10:19 pm ]
Post subject:  Re: [PPU Reg] Do you see anything absolutely wrong in this c

Wow! Great! Thank you guys!

This weekend I'm going to re-read everthing that I find about PPU. Now I'm skiping the raster process and I'm showing directly to the screen the background and the sprites according by NAMETABLE and OAM; but I'm looking forward to start to make the things right. :)

Thx!

Author:  fred [ Thu Oct 06, 2016 1:13 pm ]
Post subject:  Re: [PPU Reg] Do you see anything absolutely wrong in this c

Getting the ppu to finally start cooperating is a great feeling lol. Nice work!

Page 1 of 1 All times are UTC - 7 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/