func NewPPU() *PPU { p := new(PPU) p.Memory = cpu.NewMemory() for i := 0; i < 4; i++ { p.Nametables[i] = NewNametable() nametable := p.Nametables[i] lower := cpu.Address(i * 0x400) upper := cpu.Address((i+1)*0x400 - 1) p.Memory.Mount(nametable, 0x2000+lower, 0x2000+upper) p.Memory.Mount(nametable, 0x3000+lower, 0x3000+upper) } p.Memory.Mount(NewVRAM(), 0x3f00, 0x3fff) // 256 pixels per scanline, and 240 scanlines, each pixel with three RGB // components p.Display = make([]byte, 256*3*240) p.Frame = 0 p.Scanline = PRERENDER_SCANLINE return p }
func TestNormalizeMirrorsPaletteIndexes(t *testing.T) { ram := new(VRAM) assert.Equal(t, ram.normalize(0x0020), cpu.Address(0x0000)) assert.Equal(t, ram.normalize(0x0040), cpu.Address(0x0000)) assert.Equal(t, ram.normalize(0x0060), cpu.Address(0x0000)) assert.Equal(t, ram.normalize(0x00ff), cpu.Address(0x001f)) }
func (p *PPU) WriteVRAMAddr(val byte) { if p.AddressLatch { p.VRAMAddr = cpu.Address(val)<<8 | (0x00ff & p.VRAMAddr) } else { p.VRAMAddr = cpu.Address(val) | (0xff00 & p.VRAMAddr) } p.AddressLatch = !p.AddressLatch }
func run(filename string) { var file *os.File var err error if file, err = os.Open(filename); err != nil { log.Fatal(err) return } var rom *nes.ROM rom, err = nes.ReadROM(file) if err != nil { log.Fatal(err) return } var machine = nes.NewMachine() machine.Insert(rom) machine.CPU.Debug = false machine.CPU.Reset() // First step until the tests start. for machine.CPU.Memory.Read(0x6000) != 0x80 { machine.CPU.Step() } machine.CPU.Cycle = func() { for i := 0; i < 3; i++ { machine.PPU.Step() } } parts := strings.Split(filename, string(filepath.Separator)) fmt.Printf("Running %s tests...\n", parts[len(parts)-1]) // Next step until the tests are finished. for machine.CPU.Memory.Read(0x6000) > 0x7f { machine.CPU.Step() if machine.CPU.Memory.Read(0x6000) == 0x81 { panic("Need to press reset, but isn't implemented") } } var output = "" for i := 0; machine.CPU.Memory.Read(cpu.Address(0x6004+i)) != 0x00; i++ { char := machine.CPU.Memory.Read(cpu.Address(0x6004 + i)) output += fmt.Sprintf("%c", char) } if strings.Contains(output, "Passed") { fmt.Printf("Results: OK\n") } else { fmt.Printf("Results: FAIL\n") fmt.Printf("====\n%s====\n", output) } }
func TestPPUDATAReadIncrementsVRAMAddrCorrectly(t *testing.T) { p := NewPPU() p.Memory.Mount(NewPatterntable(make([]byte, 0x1000)), 0x0000, 0x0fff) p.VRAMAddr = cpu.Address(0x0000) p.Ctrl.VRAMAddressInc = VRAM_INC_ACROSS p.Read(PPUDATA) assert.Equal(t, p.VRAMAddr, cpu.Address(0x0001)) p.VRAMAddr = cpu.Address(0x0000) p.Ctrl.VRAMAddressInc = VRAM_INC_DOWN p.Read(PPUDATA) assert.Equal(t, p.VRAMAddr, cpu.Address(0x0020)) }
func TestPPUReadAt2007ReadsData(t *testing.T) { p := NewPPU() p.Memory.Mount(NewPatterntable(make([]byte, 0x1000)), 0x0000, 0x0fff) p.VRAMAddr = cpu.Address(0x0000) p.Memory.Write(0xbe, p.VRAMAddr) assert.Equal(t, p.Read(PPUDATA), byte(0xbe)) }
func TestPPUWritePPUAddr(t *testing.T) { p := NewPPU() p.AddressLatch = true p.Write(0xbe, PPUADDR) p.Write(0xef, PPUADDR) assert.Equal(t, p.VRAMAddr, cpu.Address(0xbeef)) }
func TestWriteVRAMAddr(t *testing.T) { p := NewPPU() p.AddressLatch = true p.WriteVRAMAddr(0xbe) p.WriteVRAMAddr(0xef) assert.Equal(t, p.VRAMAddr, cpu.Address(0xbeef)) }
func TestPPUWritePPUData(t *testing.T) { p := NewPPU() p.VRAMAddr = 0x0000 p.Memory.Mount(NewPatterntable(make([]byte, 0x1000)), 0x0000, 0x0fff) p.Write(0xbe, PPUDATA) assert.Equal(t, p.Memory.Read(0x0000), byte(0xbe)) assert.Equal(t, p.VRAMAddr, cpu.Address(0x0001)) }
func (n *Nametable) Attribute(x int, y int) uint8 { offset := cpu.Address(y/4*8 + x/4 + 0x3c0) attribs := n.Read(offset) xt := (x / 2) % 2 yt := (y / 2) % 2 bit_index := (yt * 2) + xt return (attribs >> uint(bit_index*2)) & 0x3 }
func (m *Machine) Insert(rom *ROM) { first := rom.Mapper.Patterntable(0) var err = m.PPU.Memory.Mount(first, 0x0000, 0x0fff) if err != nil { panic(err) } m.PPU.Patterntables[0] = first second := rom.Mapper.Patterntable(1) err = m.PPU.Memory.Mount(second, 0x1000, 0x1fff) if err != nil { panic(err) } m.PPU.Patterntables[1] = second err = m.CPU.Memory.Mount(rom.Mapper.Program(), 0x8000, 0xffff) if err != nil { panic(err) } m.CPU.PC = cpu.Address(m.CPU.Memory.Read(0xFFFC)) | (cpu.Address(m.CPU.Memory.Read(0xFFFD)) << 8) }
func TestNormalizeMirrorsPPURegisters(t *testing.T) { p := NewPPU() assert.Equal(t, p.normalize(0x0008), cpu.Address(0x0000)) assert.Equal(t, p.normalize(0x1456), cpu.Address(0x0006)) }
func (n *Nametable) TileIndex(x int, y int) uint8 { offset := cpu.Address(x + y*32) return n.Read(offset) }