Add some RAM and a stack
This commit is contained in:
parent
1bae615b39
commit
82d3898216
42
gb/bus.go
42
gb/bus.go
@ -4,12 +4,27 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 0x0000 - 0x3FFF : ROM Bank 0
|
||||
// 0x4000 - 0x7FFF : ROM Bank 1 - Switchable
|
||||
// 0x8000 - 0x97FF : CHR RAM
|
||||
// 0x9800 - 0x9BFF : BG Map 1
|
||||
// 0x9C00 - 0x9FFF : BG Map 2
|
||||
// 0xA000 - 0xBFFF : Cartridge RAM
|
||||
// 0xC000 - 0xCFFF : RAM Bank 0
|
||||
// 0xD000 - 0xDFFF : RAM Bank 1-7 - switchable - Color only
|
||||
// 0xE000 - 0xFDFF : Reserved - Echo RAM
|
||||
// 0xFE00 - 0xFE9F : Object Attribute Memory
|
||||
// 0xFEA0 - 0xFEFF : Reserved - Unusable
|
||||
// 0xFF00 - 0xFF7F : I/O Registers
|
||||
// 0xFF80 - 0xFFFE : Zero Page
|
||||
|
||||
type Bus struct {
|
||||
Cart *Cartridge
|
||||
RAM *RAM
|
||||
}
|
||||
|
||||
func NewBus(cart *Cartridge) *Bus {
|
||||
bus := Bus{Cart: cart}
|
||||
bus := Bus{Cart: cart, RAM: NewRAM()}
|
||||
|
||||
return &bus
|
||||
}
|
||||
@ -23,12 +38,21 @@ func (bus *Bus) Read(address uint16) byte {
|
||||
return 0
|
||||
}
|
||||
return value
|
||||
} else if address < 0xE000 {
|
||||
return bus.RAM.WRAMRead(address)
|
||||
} else {
|
||||
fmt.Printf("Reading from bus address %X not implemented!\n", address)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func (bus *Bus) Read16(address uint16) uint16 {
|
||||
lo := bus.Read(address)
|
||||
hi := bus.Read(address + 1)
|
||||
|
||||
return uint16(lo) | uint16(hi)<<8
|
||||
}
|
||||
|
||||
func (bus *Bus) Write(address uint16, value byte) error {
|
||||
if address < 0x8000 {
|
||||
// ROM data
|
||||
@ -37,7 +61,23 @@ func (bus *Bus) Write(address uint16, value byte) error {
|
||||
return fmt.Errorf("Error writing to bus address %X: %s", address, err)
|
||||
}
|
||||
return nil
|
||||
} else if address < 0xE000 {
|
||||
bus.RAM.WRAMWrite(address, value)
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("Writing to bus address %X not implemented!", address)
|
||||
}
|
||||
}
|
||||
|
||||
func (bus *Bus) Write16(address uint16, value uint16) error {
|
||||
err := bus.Write(address+1, byte((value>>8)&0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = bus.Write(address, byte(value&0xFF))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
24
gb/cpu.go
24
gb/cpu.go
@ -110,3 +110,27 @@ func (cpu *CPU) ToggleFlag(flag CPUFlags) {
|
||||
func (cpu *CPU) IsFlagSet(flag CPUFlags) bool {
|
||||
return cpu.Regs.F&flag != 0
|
||||
}
|
||||
|
||||
func (cpu *CPU) StackPush(data byte) {
|
||||
cpu.Regs.SP--
|
||||
cpu.Bus.Write(cpu.Regs.SP, data)
|
||||
}
|
||||
|
||||
func (cpu *CPU) StackPush16(data uint16) {
|
||||
cpu.StackPush(byte((data >> 8) & 0xFF))
|
||||
cpu.StackPush(byte(data & 0xFF))
|
||||
}
|
||||
|
||||
func (cpu *CPU) StackPop() byte {
|
||||
val := cpu.Bus.Read(cpu.Regs.SP)
|
||||
cpu.Regs.SP++
|
||||
|
||||
return val
|
||||
}
|
||||
|
||||
func (cpu *CPU) StackPop16() uint16 {
|
||||
lo := cpu.StackPop()
|
||||
hi := cpu.StackPop()
|
||||
|
||||
return uint16(hi)<<8 | uint16(lo)
|
||||
}
|
||||
|
||||
55
gb/ram.go
Normal file
55
gb/ram.go
Normal file
@ -0,0 +1,55 @@
|
||||
package gb
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type RAM struct {
|
||||
WRAM [0x2000]byte
|
||||
HRAM [0x80]byte
|
||||
}
|
||||
|
||||
func NewRAM() *RAM {
|
||||
ram := RAM{}
|
||||
|
||||
return &ram
|
||||
}
|
||||
|
||||
func (ram *RAM) WRAMRead(address uint16) byte {
|
||||
// TODO(m): Understand this line
|
||||
address -= 0xC000
|
||||
|
||||
if address >= 0x2000 {
|
||||
fmt.Printf("Reading from WRAM: invalid address %X", address+0xC000)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return ram.WRAM[address]
|
||||
}
|
||||
|
||||
func (ram *RAM) WRAMWrite(address uint16, value byte) {
|
||||
// TODO(m): Understand this line
|
||||
address -= 0xC000
|
||||
|
||||
if address >= 0x2000 {
|
||||
fmt.Printf("Writing to WRAM: invalid address %X", address)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
ram.WRAM[address] = value
|
||||
}
|
||||
|
||||
func (ram *RAM) HRAMRead(address uint16) byte {
|
||||
// TODO(m): Understand this line
|
||||
address -= 0xFF80
|
||||
|
||||
return ram.HRAM[address]
|
||||
}
|
||||
|
||||
func (ram *RAM) HRAMWrite(address uint16, value byte) {
|
||||
// TODO(m): Understand this line
|
||||
address -= 0xFF80
|
||||
|
||||
ram.HRAM[address] = value
|
||||
}
|
||||
59
gb/stack_test.go
Normal file
59
gb/stack_test.go
Normal file
@ -0,0 +1,59 @@
|
||||
package gb
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStackPush(t *testing.T) {
|
||||
cpu := createCPU([]byte{0x00, 0x00, 0x00})
|
||||
|
||||
cpu.StackPush(0xDE)
|
||||
|
||||
// Should decrement the stack pointer
|
||||
assert.Equal(t, cpu.Regs.SP, uint16(0xDFFE))
|
||||
|
||||
// Should write the value to the stack
|
||||
assert.Equal(t, cpu.Bus.Read(cpu.Regs.SP), byte(0xDE))
|
||||
}
|
||||
|
||||
func TestStackPush16(t *testing.T) {
|
||||
cpu := createCPU([]byte{0x00, 0x00, 0x00})
|
||||
|
||||
cpu.StackPush16(0xDEAD)
|
||||
|
||||
// Should decrement the stack pointer twice
|
||||
assert.Equal(t, cpu.Regs.SP, uint16(0xDFFD))
|
||||
|
||||
// Should write the value to the stack
|
||||
assert.Equal(t, cpu.Bus.Read16(cpu.Regs.SP), uint16(0xDEAD))
|
||||
}
|
||||
|
||||
func TestStackPop(t *testing.T) {
|
||||
cpu := createCPU([]byte{0x00, 0x00, 0x00})
|
||||
|
||||
cpu.StackPush(0xDE)
|
||||
|
||||
val := cpu.StackPop()
|
||||
|
||||
// Should increment the stack pointer
|
||||
assert.Equal(t, cpu.Regs.SP, uint16(0xDFFF))
|
||||
|
||||
// Should return the byte value
|
||||
assert.Equal(t, val, byte(0xDE))
|
||||
}
|
||||
|
||||
func TestStackPop16(t *testing.T) {
|
||||
cpu := createCPU([]byte{0x00, 0x00, 0x00})
|
||||
|
||||
cpu.StackPush16(0xBEEF)
|
||||
|
||||
val := cpu.StackPop16()
|
||||
|
||||
// Should increment the stack pointer
|
||||
assert.Equal(t, cpu.Regs.SP, uint16(0xDFFF))
|
||||
|
||||
// Should return the 16 bit value
|
||||
assert.Equal(t, val, uint16(0xBEEF))
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user