Loads ROM, shows APPLE ][ logo. Freezes on . Next to implement the soft switches in page
This commit is contained in:
parent
49f2436c7b
commit
1a6e9e006a
20
main.go
20
main.go
|
@ -1,21 +1,14 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
var s state
|
||||
s.memory.loadBinary("6502_65C02_functional_tests/bin_files/6502_functional_test.bin")
|
||||
var t textPages
|
||||
|
||||
s.registers.setPC(0x0400)
|
||||
s.memory.initWithRomAndText("../roms/APPLE2.ROM", &t)
|
||||
startAddress := s.memory.getWord(0xfffc)
|
||||
s.registers.setPC(startAddress)
|
||||
for true {
|
||||
testCase := s.memory.peek(0x0200)
|
||||
if testCase >= 240 {
|
||||
break
|
||||
}
|
||||
log := testCase > 43
|
||||
if log {
|
||||
fmt.Printf("[ %d ] ", testCase)
|
||||
}
|
||||
log := true
|
||||
pc := s.registers.getPC()
|
||||
executeInstruction(&s, log)
|
||||
if pc == s.registers.getPC() {
|
||||
|
@ -23,7 +16,6 @@ func main() {
|
|||
//s.memory.printPage(0x01)
|
||||
panic("No change in PC")
|
||||
}
|
||||
t.dumpIfDirty()
|
||||
}
|
||||
|
||||
fmt.Printf("Test completed\n")
|
||||
}
|
||||
|
|
82
memory.go
82
memory.go
|
@ -9,40 +9,56 @@ import (
|
|||
type memoryPage interface {
|
||||
peek(uint8) uint8
|
||||
poke(uint8, uint8)
|
||||
getData() *[256]uint8
|
||||
}
|
||||
|
||||
type ramPage [256]uint8
|
||||
type romPage [256]uint8
|
||||
type ramPage struct {
|
||||
data [256]uint8
|
||||
}
|
||||
|
||||
type memory [256]memoryPage
|
||||
type romPage struct {
|
||||
data [256]uint8
|
||||
}
|
||||
|
||||
type memory struct {
|
||||
data [256]memoryPage
|
||||
}
|
||||
|
||||
func (p *ramPage) peek(address uint8) uint8 {
|
||||
return p[address]
|
||||
return p.data[address]
|
||||
}
|
||||
|
||||
func (p *ramPage) poke(address uint8, value uint8) {
|
||||
p[address] = value
|
||||
p.data[address] = value
|
||||
}
|
||||
|
||||
func (p *ramPage) getData() *[256]uint8 {
|
||||
return &p.data
|
||||
}
|
||||
|
||||
func (p *romPage) peek(address uint8) uint8 {
|
||||
return p[address]
|
||||
return p.data[address]
|
||||
}
|
||||
|
||||
func (p *romPage) poke(address uint8, value uint8) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
func (p *romPage) getData() *[256]uint8 {
|
||||
return &p.data
|
||||
}
|
||||
|
||||
func (m *memory) peek(address uint16) uint8 {
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
return m[hi].peek(lo)
|
||||
return m.data[hi].peek(lo)
|
||||
}
|
||||
|
||||
func (m *memory) poke(address uint16, value uint8) {
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
//fmt.Println(hi)
|
||||
m[hi].poke(lo, value)
|
||||
m.data[hi].poke(lo, value)
|
||||
}
|
||||
|
||||
func (m *memory) getWord(address uint16) uint16 {
|
||||
|
@ -56,7 +72,53 @@ func (m *memory) getZeroPageWord(address uint8) uint16 {
|
|||
func (m *memory) initWithRam() {
|
||||
var ramPages [256]ramPage
|
||||
for i := 0; i < 256; i++ {
|
||||
m[i] = &ramPages[i]
|
||||
m.data[i] = &ramPages[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (m *memory) transformToRom(page uint8) {
|
||||
var romPage romPage
|
||||
ramPage := m.data[page]
|
||||
romPage.data = *ramPage.getData()
|
||||
m.data[page] = &romPage
|
||||
}
|
||||
|
||||
func (m *memory) initWithRomAndText(filename string, textPages *textPages) {
|
||||
// Valid for ROMs with size 20480 bytes = 20 KB = 80 pages
|
||||
// from $B000 to $F000
|
||||
// Load file
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
stats, statsErr := f.Stat()
|
||||
if statsErr != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
size := stats.Size()
|
||||
if size != 20480 {
|
||||
panic("Invalid ROM file size. It must be 20480 bytes")
|
||||
}
|
||||
bytes := make([]byte, size)
|
||||
|
||||
buf := bufio.NewReader(f)
|
||||
buf.Read(bytes)
|
||||
|
||||
m.initWithRam()
|
||||
for i, v := range bytes {
|
||||
m.poke(uint16(i)+0xB000, uint8(v))
|
||||
}
|
||||
|
||||
var i uint8
|
||||
for i = 217; i != 0; i++ {
|
||||
m.transformToRom(i)
|
||||
}
|
||||
|
||||
for j := 0; j < 4; j++ {
|
||||
m.data[4+i] = &textPages.pages[i]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +152,7 @@ func (m *memory) printPage(page uint8) {
|
|||
for i := 0; i < 16; i++ {
|
||||
fmt.Printf("%#04x: ", address)
|
||||
for j := 0; j < 16; j++ {
|
||||
fmt.Printf("%02x ", m[address])
|
||||
fmt.Printf("%02x ", m.data[address])
|
||||
address++
|
||||
}
|
||||
fmt.Printf("\n")
|
||||
|
|
47
textPages.go
47
textPages.go
|
@ -3,13 +3,12 @@ package main
|
|||
import "fmt"
|
||||
|
||||
type textPages struct {
|
||||
dirty bool
|
||||
pages *[4]textPage
|
||||
pages [4]textPage
|
||||
}
|
||||
|
||||
type textPage struct {
|
||||
textPages *textPages
|
||||
data [256]uint8
|
||||
dirty bool
|
||||
data [256]uint8
|
||||
}
|
||||
|
||||
func (p *textPage) peek(address uint8) uint8 {
|
||||
|
@ -19,40 +18,64 @@ func (p *textPage) peek(address uint8) uint8 {
|
|||
func (p *textPage) poke(address uint8, value uint8) {
|
||||
p.data[address] = value
|
||||
// Note: we could avoid setting dirty on the 16 blocks of 8 hidden bytes
|
||||
p.textPages.dirty = true
|
||||
p.dirty = true
|
||||
}
|
||||
|
||||
func (p *textPage) getData() *[256]uint8 {
|
||||
return &p.data
|
||||
}
|
||||
|
||||
func textMemoryByteToString(value uint8) string {
|
||||
value = value & 0x7F
|
||||
if value < ' ' {
|
||||
return " "
|
||||
}
|
||||
|
||||
return string(value)
|
||||
}
|
||||
|
||||
func textMemoryByteToStringHex(value uint8) string {
|
||||
return fmt.Sprintf("%02x ", value)
|
||||
}
|
||||
|
||||
func (tp *textPages) dump() {
|
||||
// See "Understand the Apple II", page 5-10
|
||||
// http://www.applelogic.org/files/UNDERSTANDINGTHEAII.pdf
|
||||
|
||||
fmt.Println("------------------------------------------")
|
||||
|
||||
var i, j, h uint8
|
||||
// Top, middle and botton screen
|
||||
for i = 0; i < 128; i = i + 40 {
|
||||
for i = 0; i < 120; i = i + 40 {
|
||||
// Memory pages
|
||||
for _, p := range tp.pages {
|
||||
// The two half pages
|
||||
for _, h = range []uint8{0, 128} {
|
||||
line := ""
|
||||
line := "|"
|
||||
for j = i + h; j < i+h+40; j++ {
|
||||
line += string(p.peek(j))
|
||||
line += textMemoryByteToString(p.peek(j))
|
||||
}
|
||||
fmt.Println(line)
|
||||
fmt.Println(line + "|")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("------------------------------------------")
|
||||
|
||||
}
|
||||
|
||||
func (tp *textPages) dumpIfDirty() {
|
||||
if !tp.dirty {
|
||||
return
|
||||
dirty := false
|
||||
for i := 0; i < 4; i++ {
|
||||
if tp.pages[i].dirty {
|
||||
dirty = true
|
||||
tp.pages[i].dirty = false
|
||||
}
|
||||
}
|
||||
|
||||
tp.dirty = false
|
||||
if !dirty {
|
||||
return
|
||||
}
|
||||
tp.dump()
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue