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
|
package main
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var s state
|
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 {
|
for true {
|
||||||
testCase := s.memory.peek(0x0200)
|
log := true
|
||||||
if testCase >= 240 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
log := testCase > 43
|
|
||||||
if log {
|
|
||||||
fmt.Printf("[ %d ] ", testCase)
|
|
||||||
}
|
|
||||||
pc := s.registers.getPC()
|
pc := s.registers.getPC()
|
||||||
executeInstruction(&s, log)
|
executeInstruction(&s, log)
|
||||||
if pc == s.registers.getPC() {
|
if pc == s.registers.getPC() {
|
||||||
|
@ -23,7 +16,6 @@ func main() {
|
||||||
//s.memory.printPage(0x01)
|
//s.memory.printPage(0x01)
|
||||||
panic("No change in PC")
|
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 {
|
type memoryPage interface {
|
||||||
peek(uint8) uint8
|
peek(uint8) uint8
|
||||||
poke(uint8, uint8)
|
poke(uint8, uint8)
|
||||||
|
getData() *[256]uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
type ramPage [256]uint8
|
type ramPage struct {
|
||||||
type romPage [256]uint8
|
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 {
|
func (p *ramPage) peek(address uint8) uint8 {
|
||||||
return p[address]
|
return p.data[address]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ramPage) poke(address uint8, value uint8) {
|
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 {
|
func (p *romPage) peek(address uint8) uint8 {
|
||||||
return p[address]
|
return p.data[address]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *romPage) poke(address uint8, value uint8) {
|
func (p *romPage) poke(address uint8, value uint8) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *romPage) getData() *[256]uint8 {
|
||||||
|
return &p.data
|
||||||
|
}
|
||||||
|
|
||||||
func (m *memory) peek(address uint16) uint8 {
|
func (m *memory) peek(address uint16) uint8 {
|
||||||
hi := uint8(address >> 8)
|
hi := uint8(address >> 8)
|
||||||
lo := uint8(address)
|
lo := uint8(address)
|
||||||
return m[hi].peek(lo)
|
return m.data[hi].peek(lo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memory) poke(address uint16, value uint8) {
|
func (m *memory) poke(address uint16, value uint8) {
|
||||||
hi := uint8(address >> 8)
|
hi := uint8(address >> 8)
|
||||||
lo := uint8(address)
|
lo := uint8(address)
|
||||||
//fmt.Println(hi)
|
//fmt.Println(hi)
|
||||||
m[hi].poke(lo, value)
|
m.data[hi].poke(lo, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *memory) getWord(address uint16) uint16 {
|
func (m *memory) getWord(address uint16) uint16 {
|
||||||
|
@ -56,7 +72,53 @@ func (m *memory) getZeroPageWord(address uint8) uint16 {
|
||||||
func (m *memory) initWithRam() {
|
func (m *memory) initWithRam() {
|
||||||
var ramPages [256]ramPage
|
var ramPages [256]ramPage
|
||||||
for i := 0; i < 256; i++ {
|
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++ {
|
for i := 0; i < 16; i++ {
|
||||||
fmt.Printf("%#04x: ", address)
|
fmt.Printf("%#04x: ", address)
|
||||||
for j := 0; j < 16; j++ {
|
for j := 0; j < 16; j++ {
|
||||||
fmt.Printf("%02x ", m[address])
|
fmt.Printf("%02x ", m.data[address])
|
||||||
address++
|
address++
|
||||||
}
|
}
|
||||||
fmt.Printf("\n")
|
fmt.Printf("\n")
|
||||||
|
|
47
textPages.go
47
textPages.go
|
@ -3,13 +3,12 @@ package main
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type textPages struct {
|
type textPages struct {
|
||||||
dirty bool
|
pages [4]textPage
|
||||||
pages *[4]textPage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type textPage struct {
|
type textPage struct {
|
||||||
textPages *textPages
|
dirty bool
|
||||||
data [256]uint8
|
data [256]uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *textPage) peek(address uint8) 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) {
|
func (p *textPage) poke(address uint8, value uint8) {
|
||||||
p.data[address] = value
|
p.data[address] = value
|
||||||
// Note: we could avoid setting dirty on the 16 blocks of 8 hidden bytes
|
// 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 {
|
func textMemoryByteToString(value uint8) string {
|
||||||
|
value = value & 0x7F
|
||||||
|
if value < ' ' {
|
||||||
|
return " "
|
||||||
|
}
|
||||||
|
|
||||||
return string(value)
|
return string(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func textMemoryByteToStringHex(value uint8) string {
|
||||||
|
return fmt.Sprintf("%02x ", value)
|
||||||
|
}
|
||||||
|
|
||||||
func (tp *textPages) dump() {
|
func (tp *textPages) dump() {
|
||||||
// See "Understand the Apple II", page 5-10
|
// See "Understand the Apple II", page 5-10
|
||||||
// http://www.applelogic.org/files/UNDERSTANDINGTHEAII.pdf
|
// http://www.applelogic.org/files/UNDERSTANDINGTHEAII.pdf
|
||||||
|
|
||||||
|
fmt.Println("------------------------------------------")
|
||||||
|
|
||||||
var i, j, h uint8
|
var i, j, h uint8
|
||||||
// Top, middle and botton screen
|
// Top, middle and botton screen
|
||||||
for i = 0; i < 128; i = i + 40 {
|
for i = 0; i < 120; i = i + 40 {
|
||||||
// Memory pages
|
// Memory pages
|
||||||
for _, p := range tp.pages {
|
for _, p := range tp.pages {
|
||||||
// The two half pages
|
// The two half pages
|
||||||
for _, h = range []uint8{0, 128} {
|
for _, h = range []uint8{0, 128} {
|
||||||
line := ""
|
line := "|"
|
||||||
for j = i + h; j < i+h+40; j++ {
|
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() {
|
func (tp *textPages) dumpIfDirty() {
|
||||||
if !tp.dirty {
|
dirty := false
|
||||||
return
|
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()
|
tp.dump()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue