Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

patch-20240310 #20

Merged
merged 2 commits into from
Mar 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 6 additions & 60 deletions nes/bus.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,8 @@ func (bus *CPUBus) read(addr uint16) byte {
return bus.ram[addr%0x800]

// NES PPU registers
case addr == 0x2000:
return bus.ppu.readController()
case addr == 0x2001:
return bus.ppu.readMask()
case addr == 0x2002:
return bus.ppu.readStatus()
case addr == 0x2003:
return bus.ppu.readOAMAddr()
case addr == 0x2004:
return bus.ppu.readOAMData()
case addr == 0x2005:
return bus.ppu.readScroll()
case addr == 0x2006:
return bus.ppu.readPPUAddr()
case addr == 0x2007:
return bus.ppu.readPPUData()

// Mirrors of $2000-2007 (repeats every 8 bytes)
case 0x2008 <= addr && addr <= 0x3FFF:
return bus.read(0x2000 + addr%0x08)
case 0x2000 <= addr && addr <= 0x3FFF:
return bus.ppu.ReadMMIORegister(addr)

// NES APU and I/O registers
case 0x4000 <= addr && addr <= 0x4017:
Expand Down Expand Up @@ -91,26 +73,8 @@ func (bus *CPUBus) write(addr uint16, val byte) {
bus.ram[addr%0x800] = val

// NES PPU registers
case addr == 0x2000:
bus.ppu.writeController(val)
case addr == 0x2001:
bus.ppu.writeMask(val)
case addr == 0x2002:
bus.ppu.writeStatus(val)
case addr == 0x2003:
bus.ppu.writeOAMAddr(val)
case addr == 0x2004:
bus.ppu.writeOAMData(val)
case addr == 0x2005:
bus.ppu.writeScroll(val)
case addr == 0x2006:
bus.ppu.writePPUAddr(val)
case addr == 0x2007:
bus.ppu.writePPUData(val)

// Mirrors of $2000-2007 (repeats every 8 bytes)
case 0x2008 <= addr && addr <= 0x3FFF:
bus.write(0x2000+addr%0x08, val)
case 0x2000 <= addr && addr <= 0x3FFF:
bus.ppu.WriteMMIORegister(addr, val)

// NES APU and I/O registers
case addr == 0x4000:
Expand Down Expand Up @@ -208,26 +172,8 @@ func (bus *CPUBus) Peek(addr uint16) byte {
return bus.ram[addr%0x800]

// NES PPU registers
case addr == 0x2000:
return bus.ppu.PeekController()
case addr == 0x2001:
return bus.ppu.PeekMask()
case addr == 0x2002:
return bus.ppu.PeekStatus()
case addr == 0x2003:
return bus.ppu.PeekOAMAddr()
case addr == 0x2004:
return bus.ppu.PeekOAMData()
case addr == 0x2005:
return bus.ppu.PeekScroll()
case addr == 0x2006:
return bus.ppu.PeekPPUAddr()
case addr == 0x2007:
return bus.ppu.PeekPPUData()

// Mirrors of $2000-2007 (repeats every 8 bytes)
case 0x2008 <= addr && addr <= 0x3FFF:
return bus.Peek(0x2000 + addr%0x08)
case 0x2000 <= addr && addr <= 0x3FFF:
return bus.ppu.PeekMMIORegister(addr)

// NES APU and I/O registers
case 0x4000 <= addr && addr <= 0x4017:
Expand Down
2 changes: 0 additions & 2 deletions nes/cassette.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ type iNESHeader struct {
type Cassette struct {
PRG []byte
CHR []byte
SRAM []byte
Mapper byte
Mirror MirroringType
}
Expand Down Expand Up @@ -96,7 +95,6 @@ func NewCassette(r io.Reader) (*Cassette, error) {
return &Cassette{
PRG: prgRom,
CHR: chrRom,
SRAM: make([]byte, 0x2000),
Mapper: mapper,
Mirror: mirroringType,
}, nil
Expand Down
2 changes: 2 additions & 0 deletions nes/mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ func NewMapperFromCassette(c *Cassette) Mapper {
switch c.Mapper {
case 0:
return newMapper0(c)
case 2:
return newMapper2(c)
case 3:
return newMapper3(c)
}
Expand Down
27 changes: 12 additions & 15 deletions nes/mapper0.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@ import "fmt"

type mapper0 struct {
*Cassette
prgBanks int
prgBank1 int
prgBank2 int
SRAM []byte
}

func newMapper0(c *Cassette) *mapper0 {
prgBanks := len(c.PRG) / 0x4000
prgBank1 := 0
prgBank2 := prgBanks - 1
return &mapper0{
Cassette: c,
prgBanks: prgBanks,
prgBank1: prgBank1,
prgBank2: prgBank2,
// > PRG RAM: 2 or 4 KiB, not bankswitched, only in Family Basic (but most emulators provide 8)
SRAM: make([]byte, 0x2000), // 8KiB
}
}

Expand All @@ -36,13 +30,16 @@ func (m *mapper0) Read(addr uint16) byte {
case 0x6000 <= addr && addr < 0x8000:
return m.SRAM[addr-0x6000]
case 0x8000 <= addr && addr < 0xC000:
index := m.prgBank1*0x4000 + int(addr-0x8000)
index := int(addr - 0x8000)
return m.PRG[index]
case 0xC000 <= addr && addr <= 0xFFFF:
index := m.prgBank2*0x4000 + int(addr-0xC000)
// > CPU $8000-$BFFF: First 16 KB of ROM.
// > CPU $C000-$FFFF: Last 16 KB of ROM (NROM-256) or mirror of $8000-$BFFF (NROM-128).
// len(m.PRG) = 16K or 32K
index := 0x4000*(len(m.PRG)/0x4000-1) + int(addr-0xC000)
return m.PRG[index]
default:
panic(fmt.Sprintf("Unable to reach Mapper0.Read(0x%04x)", addr))
panic(fmt.Sprintf("Unable to reach %s Read(0x%04x)", m, addr))
}
}

Expand All @@ -54,9 +51,9 @@ func (m *mapper0) Write(addr uint16, val byte) {
m.CHR[addr] = val
case 0x6000 <= addr && addr < 0x8000:
m.SRAM[addr-0x6000] = val
case 0x8000 <= addr:
m.prgBank1 = int(val) % m.prgBanks
case 0x8000 <= addr && addr <= 0xFFFF:
// nothing
default:
panic(fmt.Sprintf("Unable to reach Mapper0.Write(0x%04x) = 0x%02x", addr, val))
panic(fmt.Sprintf("Unable to reach %s Write(0x%04x) = 0x%02x", m, addr, val))
}
}
62 changes: 62 additions & 0 deletions nes/mapper2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package nes

import "fmt"

type mapper2 struct {
*Cassette
prgBank byte
}

func newMapper2(c *Cassette) *mapper2 {
return &mapper2{
Cassette: c,
prgBank: 0,
}
}

func (m *mapper2) String() string {
return "Mapper 2"
}

func (m *mapper2) Reset() {
// nothing
}

func (m *mapper2) Read(addr uint16) byte {
switch {
case 0x0000 <= addr && addr < 0x2000:
return m.CHR[addr]
case 0x6000 <= addr && addr < 0x8000:
// mapper2 dont'h have PRG RAM
return 0
case 0x8000 <= addr && addr < 0xC000:
// > CPU $8000-$BFFF: 16 KB switchable PRG ROM bank
index := 0x4000*int(m.prgBank) + int(addr-0x8000)
return m.PRG[index]
case 0xC000 <= addr && addr <= 0xFFFF:
// > CPU $C000-$FFFF: 16 KB PRG ROM bank, fixed to the last bank
index := 0x4000*(len(m.PRG)/0x4000-1) + int(addr-0xC000)
return m.PRG[index]
default:
panic(fmt.Sprintf("Unable to reach %s Read(0x%04x)", m, addr))
}
}

func (m *mapper2) Write(addr uint16, val byte) {
switch {
case 0x0000 <= addr && addr < 0x2000:
m.CHR[addr] = val
case 0x6000 <= addr && addr < 0x8000:
// mapper2 dont'h have PRG RAM
case 0x8000 <= addr && addr <= 0xFFFF:
// 7 bit 0
// ---- ----
// xxxx pPPP
// ||||
// ++++- Select 16 KB PRG ROM bank for CPU $8000-$BFFF
// (UNROM uses bits 2-0; UOROM uses bits 3-0)
m.prgBank = val & 0x0F
default:
panic(fmt.Sprintf("Unable to reach %s Write(0x%04x) = 0x%02x", m, addr, val))
}
}
44 changes: 25 additions & 19 deletions nes/mapper3.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@ import "fmt"

type mapper3 struct {
*Cassette
chrBank int
prgBank1 int
prgBank2 int
chrBank byte
sram []byte // for test
}

func newMapper3(c *Cassette) *mapper3 {
prgBanks := len(c.PRG) / 0x4000
prgBank2 := prgBanks - 1
return &mapper3{
Cassette: c,
chrBank: 0,
prgBank1: 0,
prgBank2: prgBank2,
sram: make([]byte, 0x2000), // for test
}
}

Expand All @@ -31,18 +27,20 @@ func (m *mapper3) Reset() {
func (m *mapper3) Read(addr uint16) byte {
switch {
case 0x0000 <= addr && addr < 0x2000:
index := m.chrBank*0x2000 + int(addr)
// > PPU $0000-$1FFF: 8 KB switchable CHR ROM bank
index := int(m.chrBank)*0x2000 + int(addr)
return m.CHR[index]
case 0x6000 <= addr && addr < 0x8000:
return m.SRAM[addr-0x6000]
case 0x8000 <= addr && addr < 0xC000:
index := m.prgBank1*0x4000 + int(addr-0x8000)
return m.PRG[index]
case 0xC000 <= addr && addr <= 0xFFFF:
index := m.prgBank2*0x4000 + int(addr-0xC000)
// mapper 3 don't have PRG RAM
// but, prepare RAM for automatic testing of ppu_read_buffer
return m.sram[addr-0x6000]
case 0x8000 <= addr && addr <= 0xFFFF:
// > PRG ROM size: 16 KiB or 32 KiB
// > PRG ROM bank size: Not bankswitched
index := int(addr-0x8000) % len(m.PRG)
return m.PRG[index]
default:
panic(fmt.Sprintf("Unable to reach Mapper3.Read(0x%04x)", addr))
panic(fmt.Sprintf("Unable to reach %s Read(0x%04x)", m, addr))
}
}

Expand All @@ -51,11 +49,19 @@ func (m *mapper3) Write(addr uint16, val byte) {
case 0x0000 <= addr && addr < 0x2000:
// read only (for ppu_read_buffer test)
case 0x6000 <= addr && addr < 0x8000:
m.SRAM[addr-0x6000] = val
case 0x8000 <= addr:
// mapper 3 don't have PRG RAM
// but, prepare RAM for automatic testing of ppu_read_buffer
m.sram[addr-0x6000] = val
case 0x8000 <= addr && addr <= 0xFFFF:
// https://www.nesdev.org/wiki/INES_Mapper_003#Bank_select_($8000-$FFFF)
m.chrBank = int(val & 0x3)
// 7 bit 0
// ---- ----
// cccc ccCC
// |||| ||||
// ++++-++++- Select 8 KB CHR ROM bank for PPU $0000-$1FFF
// > CNROM only implements the lowest 2 bits, capping it at 32 KiB CHR. Other boards may implement 4 or more bits for larger CHR.
m.chrBank = val
default:
panic(fmt.Sprintf("Unable to reach Mapper3.Write(0x%04x) = 0x%02x", addr, val))
panic(fmt.Sprintf("Unable to reach %s Write(0x%04x) = 0x%02x", m, addr, val))
}
}
Loading
Loading