mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-12-21 02:32:06 +00:00
Abstract Memory with FlatMemory and PagedMemory implementations
This commit is contained in:
parent
49ea32b84d
commit
922ae7839e
@ -6,16 +6,25 @@ import "go6502/core6502"
|
||||
func Run(romFile string, log bool) {
|
||||
|
||||
// Setup the Apple ][ address space
|
||||
var s core6502.State
|
||||
s.Mem.InitWithRAM()
|
||||
s.Mem.LoadRom(romFile)
|
||||
var m core6502.PagedMemory
|
||||
m.InitWithRAM()
|
||||
m.LoadRom(romFile)
|
||||
var io ioC0Page
|
||||
s.Mem.SetPage(0xc0, &io)
|
||||
m.SetPage(0xc0, &io)
|
||||
var t textPages
|
||||
for j := 0; j < 4; j++ {
|
||||
s.Mem.SetPage(uint8(4+j), &(t.pages[j]))
|
||||
m.SetPage(uint8(4+j), &(t.pages[j]))
|
||||
}
|
||||
|
||||
for j := uint8(0xc1); j < 0xd0; j++ {
|
||||
var p tracePage
|
||||
p.page = j
|
||||
m.SetPage(j, &p)
|
||||
}
|
||||
|
||||
var s core6502.State
|
||||
s.Mem = &m
|
||||
|
||||
var fe ansiConsoleFrontend
|
||||
io.setKeyboardProvider(&fe)
|
||||
go fe.textModeGoRoutine(&t)
|
||||
|
18
apple2/tracePage.go
Normal file
18
apple2/tracePage.go
Normal file
@ -0,0 +1,18 @@
|
||||
package apple2
|
||||
|
||||
import "fmt"
|
||||
|
||||
type tracePage struct {
|
||||
page uint8
|
||||
}
|
||||
|
||||
func (p *tracePage) Peek(address uint8) uint8 {
|
||||
fmt.Printf("Read on address 0x%02x%02x\n", p.page, address)
|
||||
panic(address)
|
||||
return 0xcc
|
||||
}
|
||||
|
||||
func (p *tracePage) Poke(address uint8, value uint8) {
|
||||
fmt.Printf("Write on address 0x%02x%02x\n", p.page, address)
|
||||
panic(address)
|
||||
}
|
@ -10,8 +10,10 @@ func TestFunctional(t *testing.T) {
|
||||
//t.SkipNow()
|
||||
|
||||
var s State
|
||||
var m FlatMemory
|
||||
s.Mem = &m
|
||||
// Test suite from https://github.com/Klaus2m5/6502_65C02_functional_tests
|
||||
s.Mem.loadBinary("testdata/6502_functional_test.bin")
|
||||
m.loadBinary("testdata/6502_functional_test.bin")
|
||||
|
||||
s.Reg.setPC(0x0400)
|
||||
for true {
|
||||
@ -26,9 +28,7 @@ func TestFunctional(t *testing.T) {
|
||||
pc := s.Reg.getPC()
|
||||
ExecuteInstruction(&s, log)
|
||||
if pc == s.Reg.getPC() {
|
||||
//s.memory.printPage(0x00)
|
||||
//s.memory.printPage(0x01)
|
||||
t.Errorf("Failuse in test %v.", testCase)
|
||||
t.Errorf("Failure in test %v.", testCase)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,11 @@ const (
|
||||
modeIndirectIndexedY
|
||||
)
|
||||
|
||||
const (
|
||||
vectorReset uint16 = 0xfffc
|
||||
vectorBreak uint16 = 0xfffe
|
||||
)
|
||||
|
||||
// https://www.masswerk.at/6502/6502_instruction_set.html
|
||||
// http://www.emulator101.com/reference/6502-reference.html
|
||||
// https://www.csh.rit.edu/~moffitt/docs/6502.html#FLAGS
|
||||
@ -69,12 +74,12 @@ func resolve(s *State, line []uint8, opcode opcode) (value uint8, address uint16
|
||||
address = getWordInLine(line) + uint16(s.Reg.getY())
|
||||
case modeIndexedIndirectX:
|
||||
addressAddress := uint8(line[1] + s.Reg.getX())
|
||||
address = s.Mem.getZeroPageWord(addressAddress)
|
||||
address = getZeroPageWord(s.Mem, addressAddress)
|
||||
case modeIndirect:
|
||||
addressAddress := getWordInLine(line)
|
||||
address = s.Mem.getWord(addressAddress)
|
||||
address = getWord(s.Mem, addressAddress)
|
||||
case modeIndirectIndexedY:
|
||||
address = s.Mem.getZeroPageWord(line[1]) +
|
||||
address = getZeroPageWord(s.Mem, line[1]) +
|
||||
uint16(s.Reg.getY())
|
||||
}
|
||||
|
||||
@ -342,7 +347,7 @@ func opBRK(s *State, line []uint8, opcode opcode) {
|
||||
pushWord(s, s.Reg.getPC()+1)
|
||||
pushByte(s, s.Reg.getP()|(flagB+flag5))
|
||||
s.Reg.setFlag(flagI)
|
||||
s.Reg.setPC(s.Mem.getWord(0xFFFE))
|
||||
s.Reg.setPC(getWord(s.Mem, vectorBreak))
|
||||
}
|
||||
|
||||
var opcodes = [256]opcode{
|
||||
@ -550,7 +555,7 @@ func ExecuteInstruction(s *State, log bool) {
|
||||
|
||||
// Reset resets the processor state. Moves the program counter to the vector in 0cfffc.
|
||||
func Reset(s *State) {
|
||||
startAddress := s.Mem.getWord(0xfffc)
|
||||
startAddress := getWord(s.Mem, vectorReset)
|
||||
s.Reg.setPC(startAddress)
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import (
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
var s State
|
||||
s.Mem.InitWithRAM()
|
||||
s.Mem = new(FlatMemory)
|
||||
|
||||
executeLine(&s, []uint8{0xA9, 0x42})
|
||||
if s.Reg.getA() != 0x42 {
|
||||
@ -89,7 +89,7 @@ func TestLoad(t *testing.T) {
|
||||
|
||||
func TestStore(t *testing.T) {
|
||||
var s State
|
||||
s.Mem.InitWithRAM()
|
||||
s.Mem = new(FlatMemory)
|
||||
s.Reg.setA(0x10)
|
||||
s.Reg.setX(0x40)
|
||||
s.Reg.setY(0x80)
|
||||
@ -401,7 +401,7 @@ func TestCompare(t *testing.T) {
|
||||
}
|
||||
func TestBit(t *testing.T) {
|
||||
var s State
|
||||
s.Mem.InitWithRAM()
|
||||
s.Mem = new(FlatMemory)
|
||||
|
||||
s.Reg.setA(0x0F)
|
||||
s.Mem.Poke(0x0040, 0xF0)
|
||||
@ -450,7 +450,7 @@ func TestBranch(t *testing.T) {
|
||||
|
||||
func TestStack(t *testing.T) {
|
||||
var s State
|
||||
s.Mem.InitWithRAM()
|
||||
s.Mem = new(FlatMemory)
|
||||
|
||||
s.Reg.setSP(0xF0)
|
||||
s.Reg.setA(0xA0)
|
||||
|
@ -2,50 +2,39 @@ package core6502
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// MemoryPage is a data page of 256 bytes
|
||||
type MemoryPage interface {
|
||||
Peek(uint8) uint8
|
||||
Poke(uint8, uint8)
|
||||
}
|
||||
|
||||
// Memory represents the addressable space of the processor
|
||||
type Memory struct {
|
||||
data [256]MemoryPage
|
||||
type Memory interface {
|
||||
Peek(address uint16) uint8
|
||||
Poke(address uint16, value uint8)
|
||||
}
|
||||
|
||||
// Peek returns the data on the given address
|
||||
func (m *Memory) Peek(address uint16) uint8 {
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
return m.data[hi].Peek(lo)
|
||||
}
|
||||
|
||||
// Poke sets the data at the given address
|
||||
func (m *Memory) Poke(address uint16, value uint8) {
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
//fmt.Println(hi)
|
||||
m.data[hi].Poke(lo, value)
|
||||
}
|
||||
|
||||
// SetPage assigns a MemoryPage implementation on the page given
|
||||
func (m *Memory) SetPage(index uint8, page MemoryPage) {
|
||||
m.data[index] = page
|
||||
}
|
||||
|
||||
func (m *Memory) getWord(address uint16) uint16 {
|
||||
func getWord(m Memory, address uint16) uint16 {
|
||||
return uint16(m.Peek(address)) + 0x100*uint16(m.Peek(address+1))
|
||||
}
|
||||
|
||||
func (m *Memory) getZeroPageWord(address uint8) uint16 {
|
||||
func getZeroPageWord(m Memory, address uint8) uint16 {
|
||||
return uint16(m.Peek(uint16(address))) + 0x100*uint16(m.Peek(uint16(address+1)))
|
||||
}
|
||||
|
||||
func (m *Memory) loadBinary(filename string) {
|
||||
// FlatMemory puts RAM on the 64Kb addeessable by the processor
|
||||
type FlatMemory struct {
|
||||
data [65536]uint8
|
||||
}
|
||||
|
||||
// Peek returns the data on the given address
|
||||
func (m *FlatMemory) Peek(address uint16) uint8 {
|
||||
return m.data[address]
|
||||
}
|
||||
|
||||
// Poke sets the data at the given address
|
||||
func (m *FlatMemory) Poke(address uint16, value uint8) {
|
||||
m.data[address] = value
|
||||
}
|
||||
|
||||
func (m *FlatMemory) loadBinary(filename string) {
|
||||
// Load file
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
@ -64,20 +53,7 @@ func (m *Memory) loadBinary(filename string) {
|
||||
buf := bufio.NewReader(f)
|
||||
buf.Read(bytes)
|
||||
|
||||
m.InitWithRAM()
|
||||
for i, v := range bytes {
|
||||
m.Poke(uint16(i), uint8(v))
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Memory) printPage(page uint8) {
|
||||
address := uint16(page) * 0x100
|
||||
for i := 0; i < 16; i++ {
|
||||
fmt.Printf("%#04x: ", address)
|
||||
for j := 0; j < 16; j++ {
|
||||
fmt.Printf("%02x ", m.data[address])
|
||||
address++
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
}
|
||||
|
32
core6502/pagedMemory.go
Normal file
32
core6502/pagedMemory.go
Normal file
@ -0,0 +1,32 @@
|
||||
package core6502
|
||||
|
||||
// MemoryPage is a data page of 256 bytes
|
||||
type MemoryPage interface {
|
||||
Peek(uint8) uint8
|
||||
Poke(uint8, uint8)
|
||||
}
|
||||
|
||||
// PagedMemory represents the addressable space of the processor
|
||||
type PagedMemory struct {
|
||||
data [256]MemoryPage
|
||||
}
|
||||
|
||||
// Peek returns the data on the given address
|
||||
func (m *PagedMemory) Peek(address uint16) uint8 {
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
return m.data[hi].Peek(lo)
|
||||
}
|
||||
|
||||
// Poke sets the data at the given address
|
||||
func (m *PagedMemory) Poke(address uint16, value uint8) {
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
//fmt.Println(hi)
|
||||
m.data[hi].Poke(lo, value)
|
||||
}
|
||||
|
||||
// SetPage assigns a MemoryPage implementation on the page given
|
||||
func (m *PagedMemory) SetPage(index uint8, page MemoryPage) {
|
||||
m.data[index] = page
|
||||
}
|
@ -2,6 +2,7 @@ package core6502
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
@ -34,14 +35,14 @@ func (p *romPage) burn(address uint8, value uint8) {
|
||||
}
|
||||
|
||||
// InitWithRAM adds RAM memory to all the memory pages
|
||||
func (m *Memory) InitWithRAM() {
|
||||
func (m *PagedMemory) InitWithRAM() {
|
||||
var ramPages [256]ramPage
|
||||
for i := 0; i < 256; i++ {
|
||||
m.SetPage(uint8(i), &ramPages[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Memory) transformToRom(page uint8) {
|
||||
func (m *PagedMemory) transformToRom(page uint8) {
|
||||
var romPage romPage
|
||||
address := uint16(page) << 8
|
||||
for i := 0; i < 256; i++ {
|
||||
@ -52,7 +53,7 @@ func (m *Memory) transformToRom(page uint8) {
|
||||
}
|
||||
|
||||
// LoadRom loads a binary file to the top of the memory and makes those pages read only.
|
||||
func (m *Memory) LoadRom(filename string) {
|
||||
func (m *PagedMemory) LoadRom(filename string) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -71,6 +72,8 @@ func (m *Memory) LoadRom(filename string) {
|
||||
buf.Read(bytes)
|
||||
|
||||
romStart := uint16(0xFFFF - size + 1)
|
||||
fmt.Printf("ROM start in in 0x%04x\n", romStart)
|
||||
|
||||
for i, v := range bytes {
|
||||
m.Poke(uint16(i)+romStart, uint8(v))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user