mirror of
https://github.com/freewilll/apple2-go.git
synced 2025-01-14 18:29:44 +00:00
Added bank switched upper memory
This commit is contained in:
parent
a43fd7c08c
commit
f1dff51564
109
bank_switch_test.go
Normal file
109
bank_switch_test.go
Normal file
@ -0,0 +1,109 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"mos6502go/cpu"
|
||||
"mos6502go/keyboard"
|
||||
"mos6502go/mmu"
|
||||
"mos6502go/system"
|
||||
"mos6502go/video"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestBankSwitching(t *testing.T) {
|
||||
cpu.InitInstructionDecoder()
|
||||
mmu.InitRAM()
|
||||
mmu.InitApple2eROM()
|
||||
mmu.InitIO()
|
||||
cpu.Init()
|
||||
keyboard.Init()
|
||||
video.Init()
|
||||
system.Init()
|
||||
cpu.SetColdStartReset()
|
||||
cpu.Reset()
|
||||
|
||||
// Sanity test that what we expect from the apple //e ROM is correct
|
||||
assert.Equal(t, uint8(0x6f), mmu.ReadMemory(0xd000)) // read from ROM
|
||||
assert.Equal(t, uint8(0xc3), mmu.ReadMemory(0xffff)) // read from ROM
|
||||
|
||||
// Verify ROM & RAM settings at startup
|
||||
mmu.WipeRAM()
|
||||
assert.Equal(t, uint8(0xc3), mmu.ReadMemory(0xffff)) // read from ROM
|
||||
mmu.WriteMemory(0xffff, 0xff) // write to $ffff
|
||||
assert.Equal(t, uint8(0xc3), mmu.ReadMemory(0xffff)) // ROM value is the same
|
||||
assert.Equal(t, uint8(0xff), mmu.PhysicalMemory.MainMemory[0xffff]) // RAM has been updated
|
||||
mmu.WriteMemory(0xd000, 0xfe) // write to $d000
|
||||
assert.Equal(t, uint8(0x00), mmu.PhysicalMemory.MainMemory[0xc000]) // bank #1 RAM
|
||||
assert.Equal(t, uint8(0xfe), mmu.PhysicalMemory.MainMemory[0xd000]) // bank #2 RAM
|
||||
|
||||
// Switch bank to 1, write and check physical memory
|
||||
mmu.SetD000Bank(1)
|
||||
mmu.SetUpperReadMappedToROM(false)
|
||||
mmu.WriteMemory(0xd000, 0xfd) // write to $d000
|
||||
assert.Equal(t, uint8(0xfd), mmu.PhysicalMemory.MainMemory[0xc000]) // bank #1 RAM
|
||||
assert.Equal(t, uint8(0xfe), mmu.PhysicalMemory.MainMemory[0xd000]) // bank #2 RAM
|
||||
|
||||
// Enable RAM area for reading and check values
|
||||
mmu.SetUpperReadMappedToROM(false)
|
||||
assert.Equal(t, uint8(0xfd), mmu.ReadMemory(0xd000)) // read from bank #1 RAM
|
||||
mmu.SetD000Bank(2)
|
||||
assert.Equal(t, uint8(0xfe), mmu.ReadMemory(0xd000)) // read from bank #1 RAM
|
||||
|
||||
// Enable ROM area for reading and check values
|
||||
mmu.SetUpperReadMappedToROM(true)
|
||||
assert.Equal(t, uint8(0x6f), mmu.ReadMemory(0xd000)) // read from ROM
|
||||
assert.Equal(t, uint8(0xc3), mmu.ReadMemory(0xffff)) // read from ROM
|
||||
|
||||
// Set d000 RAM to bank 1, RAM to read only and attempt writes
|
||||
mmu.SetD000Bank(1)
|
||||
mmu.SetUpperRamReadOnly(true)
|
||||
assert.Equal(t, uint8(0xfd), mmu.PhysicalMemory.MainMemory[0xc000]) // bank #1 RAM
|
||||
assert.Equal(t, uint8(0xfe), mmu.PhysicalMemory.MainMemory[0xd000]) // bank #2 RAM
|
||||
mmu.WriteMemory(0xd000, 0x01) // attempt to write to read only RAM
|
||||
mmu.WriteMemory(0xffff, 0x02) // attempt to write to read only RAM
|
||||
assert.Equal(t, uint8(0xfd), mmu.PhysicalMemory.MainMemory[0xc000]) // bank #1 RAM is unchanged
|
||||
assert.Equal(t, uint8(0xfe), mmu.PhysicalMemory.MainMemory[0xd000]) // bank #2 RAM is unchanged
|
||||
assert.Equal(t, uint8(0xff), mmu.PhysicalMemory.MainMemory[0xffff]) // top of RAM is unchanged
|
||||
|
||||
// Set RAM to write and write to it
|
||||
mmu.SetUpperRamReadOnly(false)
|
||||
mmu.WriteMemory(0xd000, 0xfc) // write to RAM
|
||||
mmu.WriteMemory(0xffff, 0xfb) // write to RAM
|
||||
assert.Equal(t, uint8(0xfc), mmu.PhysicalMemory.MainMemory[0xc000]) // bank #1 RAM has been updated
|
||||
assert.Equal(t, uint8(0xfe), mmu.PhysicalMemory.MainMemory[0xd000]) // bank #2 RAM is untouched
|
||||
assert.Equal(t, uint8(0xfb), mmu.PhysicalMemory.MainMemory[0xffff]) // top of RAM has been updated
|
||||
|
||||
// Enable ROM area for reading and check values
|
||||
mmu.SetUpperReadMappedToROM(true)
|
||||
assert.Equal(t, uint8(0x6f), mmu.ReadMemory(0xd000)) // read from ROM
|
||||
assert.Equal(t, uint8(0xc3), mmu.ReadMemory(0xffff)) // read from ROM
|
||||
|
||||
testSwitches(t)
|
||||
}
|
||||
|
||||
func assertMemoryConfiguration(t *testing.T, address uint16, upperRamReadOnly bool, upperReadMappedToROM bool, d000Bank int) {
|
||||
mmu.WriteMemory(address, 0x00)
|
||||
// assert.Equal(t, upperRamReadOnly, mmu.UpperRamReadOnly)
|
||||
assert.Equal(t, upperReadMappedToROM, mmu.UpperReadMappedToROM)
|
||||
assert.Equal(t, d000Bank, mmu.D000Bank)
|
||||
}
|
||||
|
||||
func testSwitches(t *testing.T) {
|
||||
assertMemoryConfiguration(t, 0xc080, true, false, 2)
|
||||
assertMemoryConfiguration(t, 0xc081, false, true, 2)
|
||||
assertMemoryConfiguration(t, 0xc082, true, true, 2)
|
||||
assertMemoryConfiguration(t, 0xc083, false, false, 2)
|
||||
assertMemoryConfiguration(t, 0xc084, true, false, 2)
|
||||
assertMemoryConfiguration(t, 0xc085, false, true, 2)
|
||||
assertMemoryConfiguration(t, 0xc086, true, true, 2)
|
||||
assertMemoryConfiguration(t, 0xc087, false, false, 2)
|
||||
assertMemoryConfiguration(t, 0xc088, true, false, 1)
|
||||
assertMemoryConfiguration(t, 0xc089, false, true, 1)
|
||||
assertMemoryConfiguration(t, 0xc08a, true, true, 1)
|
||||
assertMemoryConfiguration(t, 0xc08b, false, false, 1)
|
||||
assertMemoryConfiguration(t, 0xc08c, true, false, 1)
|
||||
assertMemoryConfiguration(t, 0xc08d, false, true, 1)
|
||||
assertMemoryConfiguration(t, 0xc08e, true, true, 1)
|
||||
assertMemoryConfiguration(t, 0xc08f, false, false, 1)
|
||||
}
|
19
cpu/cpu.go
19
cpu/cpu.go
@ -94,14 +94,14 @@ func isN() bool {
|
||||
}
|
||||
|
||||
func push8(value uint8) {
|
||||
mmu.PageTable[mmu.StackPage][State.SP] = value
|
||||
mmu.WritePageTable[mmu.StackPage][State.SP] = value
|
||||
State.SP -= 1
|
||||
State.SP &= 0xff
|
||||
}
|
||||
|
||||
func push16(value uint16) {
|
||||
mmu.PageTable[mmu.StackPage][State.SP] = uint8(value >> 8)
|
||||
mmu.PageTable[mmu.StackPage][State.SP-1] = uint8(value & 0xff)
|
||||
mmu.WritePageTable[mmu.StackPage][State.SP] = uint8(value >> 8)
|
||||
mmu.WritePageTable[mmu.StackPage][State.SP-1] = uint8(value & 0xff)
|
||||
State.SP -= 2
|
||||
State.SP &= 0xff
|
||||
}
|
||||
@ -109,14 +109,14 @@ func push16(value uint16) {
|
||||
func pop8() uint8 {
|
||||
State.SP += 1
|
||||
State.SP &= 0xff
|
||||
return mmu.PageTable[mmu.StackPage][State.SP]
|
||||
return mmu.ReadPageTable[mmu.StackPage][State.SP]
|
||||
}
|
||||
|
||||
func pop16() uint16 {
|
||||
State.SP += 2
|
||||
State.SP &= 0xff
|
||||
msb := uint16(mmu.PageTable[mmu.StackPage][State.SP])
|
||||
lsb := uint16(mmu.PageTable[mmu.StackPage][State.SP-1])
|
||||
msb := uint16(mmu.ReadPageTable[mmu.StackPage][State.SP])
|
||||
lsb := uint16(mmu.ReadPageTable[mmu.StackPage][State.SP-1])
|
||||
return lsb + msb<<8
|
||||
}
|
||||
|
||||
@ -864,8 +864,11 @@ func SetColdStartReset() {
|
||||
}
|
||||
|
||||
func Reset() {
|
||||
mmu.InitROM()
|
||||
mmu.InitRAM()
|
||||
|
||||
bootVector := 0xfffc
|
||||
lsb := mmu.PageTable[bootVector>>8][bootVector&0xff] // TODO move readMemory to mmu
|
||||
msb := mmu.PageTable[(bootVector+1)>>8][(bootVector+1)&0xff]
|
||||
lsb := mmu.ReadPageTable[bootVector>>8][bootVector&0xff]
|
||||
msb := mmu.ReadPageTable[(bootVector+1)>>8][(bootVector+1)&0xff]
|
||||
State.PC = uint16(lsb) + uint16(msb)<<8
|
||||
}
|
||||
|
@ -68,7 +68,8 @@ func TestCPU(t *testing.T) {
|
||||
RomPretendingToBeRAM[i] = bytes[0xc000+i]
|
||||
}
|
||||
for i := 0x0; i < 0x40; i++ {
|
||||
mmu.PageTable[0xc0+i] = RomPretendingToBeRAM[i*0x100 : i*0x100+0x100]
|
||||
mmu.ReadPageTable[0xc0+i] = RomPretendingToBeRAM[i*0x100 : i*0x100+0x100]
|
||||
mmu.WritePageTable[0xc0+i] = RomPretendingToBeRAM[i*0x100 : i*0x100+0x100]
|
||||
}
|
||||
|
||||
keyboard.Init()
|
||||
|
14
cpu/debug.go
14
cpu/debug.go
@ -40,7 +40,7 @@ func printInstruction(instruction string, showRegisters bool) {
|
||||
}
|
||||
|
||||
func PrintInstruction(showRegisters bool) {
|
||||
opcodeValue := mmu.PageTable[(State.PC)>>8][(State.PC)&0xff]
|
||||
opcodeValue := mmu.ReadPageTable[(State.PC)>>8][(State.PC)&0xff]
|
||||
opcode := OpCodes[opcodeValue]
|
||||
mnemonic := opcode.Mnemonic
|
||||
size := opcode.AddressingMode.OperandSize
|
||||
@ -56,7 +56,7 @@ func PrintInstruction(showRegisters bool) {
|
||||
var suffix string
|
||||
|
||||
if opcode.AddressingMode.Mode == AmRelative {
|
||||
value = uint16(mmu.PageTable[(State.PC+1)>>8][(State.PC+1)&0xff])
|
||||
value = uint16(mmu.ReadPageTable[(State.PC+1)>>8][(State.PC+1)&0xff])
|
||||
var relativeAddress uint16
|
||||
if (value & 0x80) == 0 {
|
||||
relativeAddress = State.PC + 2 + uint16(value)
|
||||
@ -67,12 +67,12 @@ func PrintInstruction(showRegisters bool) {
|
||||
suffix = fmt.Sprintf(stringFormat, relativeAddress)
|
||||
opcodes = fmt.Sprintf("%02x %02x ", opcodeValue, value)
|
||||
} else if size == 1 {
|
||||
value = uint16(mmu.PageTable[(State.PC+1)>>8][(State.PC+1)&0xff])
|
||||
value = uint16(mmu.ReadPageTable[(State.PC+1)>>8][(State.PC+1)&0xff])
|
||||
suffix = fmt.Sprintf(stringFormat, value)
|
||||
opcodes = fmt.Sprintf("%02x %02x ", opcodeValue, value)
|
||||
} else if size == 2 {
|
||||
lsb := mmu.PageTable[(State.PC+1)>>8][(State.PC+1)&0xff]
|
||||
msb := mmu.PageTable[(State.PC+2)>>8][(State.PC+2)&0xff]
|
||||
lsb := mmu.ReadPageTable[(State.PC+1)>>8][(State.PC+1)&0xff]
|
||||
msb := mmu.ReadPageTable[(State.PC+2)>>8][(State.PC+2)&0xff]
|
||||
value = uint16(lsb) + uint16(msb)*0x100
|
||||
suffix = fmt.Sprintf(stringFormat, value)
|
||||
opcodes = fmt.Sprintf("%02x %02x %02x ", opcodeValue, lsb, msb)
|
||||
@ -82,7 +82,7 @@ func PrintInstruction(showRegisters bool) {
|
||||
}
|
||||
|
||||
func AdvanceInstruction() {
|
||||
opcodeValue := mmu.PageTable[(State.PC)>>8][(State.PC)&0xff]
|
||||
opcodeValue := mmu.ReadPageTable[(State.PC)>>8][(State.PC)&0xff]
|
||||
opcode := OpCodes[opcodeValue]
|
||||
size := opcode.AddressingMode.OperandSize + 1
|
||||
State.PC += uint16(size)
|
||||
@ -100,7 +100,7 @@ func DumpMemory(offset uint16) {
|
||||
}
|
||||
fmt.Printf("%04x ", offset+i)
|
||||
}
|
||||
fmt.Printf(" %02x", mmu.PageTable[(offset+i)>>8][(offset+i)&0xff])
|
||||
fmt.Printf(" %02x", mmu.ReadPageTable[(offset+i)>>8][(offset+i)&0xff])
|
||||
}
|
||||
fmt.Print("\n")
|
||||
}
|
||||
|
30
io_test.go
Normal file
30
io_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"mos6502go/cpu"
|
||||
"mos6502go/keyboard"
|
||||
"mos6502go/mmu"
|
||||
"mos6502go/system"
|
||||
"mos6502go/video"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIoBankSwitching(t *testing.T) {
|
||||
cpu.InitInstructionDecoder()
|
||||
mmu.InitRAM()
|
||||
mmu.InitApple2eROM()
|
||||
mmu.InitIO()
|
||||
cpu.Init()
|
||||
keyboard.Init()
|
||||
video.Init()
|
||||
system.Init()
|
||||
cpu.SetColdStartReset()
|
||||
cpu.Reset()
|
||||
|
||||
mmu.MapFirstHalfOfIO()
|
||||
assert.Equal(t, uint8(0xa2), mmu.ReadMemory(0xc600)) // read from Primary Slot 6 ROM
|
||||
mmu.MapSecondHalfOfIO()
|
||||
assert.Equal(t, uint8(0x8d), mmu.ReadMemory(0xc600)) // read from Primary Slot 6 ROM
|
||||
}
|
10
mmu/io.go
10
mmu/io.go
@ -67,6 +67,7 @@ const (
|
||||
|
||||
OPNAPPLE = 0xC061 // open apple (command) key data
|
||||
CLSAPPLE = 0xC062 // closed apple (option) key data
|
||||
STATEREG = 0xC068 // Has no effect on //e
|
||||
|
||||
PDLTRIG = 0xC070 // trigger paddles
|
||||
|
||||
@ -134,6 +135,12 @@ func driveIsreadSequencing() bool {
|
||||
// Handle soft switch addresses where both a read and a write has a side
|
||||
// effect and the return value is meaningless
|
||||
func readWrite(address uint16, isRead bool) bool {
|
||||
lsb := address & 0xff
|
||||
if lsb >= 0x80 && lsb < 0x90 {
|
||||
SetMemoryMode(uint8(lsb - 0x80))
|
||||
return true
|
||||
}
|
||||
|
||||
switch address {
|
||||
case CLR80VID:
|
||||
// 80 column card hasn't been implemented yet
|
||||
@ -162,6 +169,9 @@ func readWrite(address uint16, isRead bool) bool {
|
||||
case SETHIRES:
|
||||
VideoState.HiresMode = true
|
||||
return true
|
||||
case STATEREG:
|
||||
// Ignore not implemented memory management reg
|
||||
return true
|
||||
|
||||
// Drive stepper motor phase change
|
||||
case S6CLRDRVP0, S6SETDRVP0, S6CLRDRVP1, S6SETDRVP1, S6CLRDRVP2, S6SETDRVP2, S6CLRDRVP3, S6SETDRVP3:
|
||||
|
156
mmu/mmu.go
156
mmu/mmu.go
@ -10,30 +10,88 @@ const RomPath = "apple2e.rom"
|
||||
const StackPage = 1
|
||||
|
||||
var PhysicalMemory struct {
|
||||
MainMemory [0xc000]uint8
|
||||
MainMemory [0x10000]uint8
|
||||
UpperROM [0x3000]uint8
|
||||
RomC1 [0x1000]uint8
|
||||
RomC2 [0x1000]uint8
|
||||
}
|
||||
|
||||
var PageTable [0x100][]uint8
|
||||
var ReadPageTable [0x100][]uint8
|
||||
var WritePageTable [0x100][]uint8
|
||||
|
||||
var UsingExternalSlotRom bool
|
||||
// Memory mapping states
|
||||
var (
|
||||
D000Bank int // one maps to $c000, two maps to $d000
|
||||
UsingExternalSlotRom bool // Which IO ROM is being used
|
||||
UpperReadMappedToROM bool // Do reads go to the RAM or ROM
|
||||
UpperRamReadOnly bool // Is the upper RAM read only
|
||||
)
|
||||
|
||||
func MapFirstHalfOfIO() {
|
||||
UsingExternalSlotRom = false
|
||||
func ApplyMemoryConfiguration() {
|
||||
// Map main RAM for read/write
|
||||
for i := 0x0; i < 0xc0; i++ {
|
||||
ReadPageTable[i] = PhysicalMemory.MainMemory[i*0x100 : i*0x100+0x100]
|
||||
WritePageTable[i] = PhysicalMemory.MainMemory[i*0x100 : i*0x100+0x100]
|
||||
}
|
||||
|
||||
// Map $c000
|
||||
var ioRom *[0x1000]uint8
|
||||
if UsingExternalSlotRom {
|
||||
ioRom = &PhysicalMemory.RomC2
|
||||
} else {
|
||||
ioRom = &PhysicalMemory.RomC1
|
||||
}
|
||||
|
||||
for i := 0x1; i < 0x10; i++ {
|
||||
PageTable[i+0xc0] = PhysicalMemory.RomC1[i*0x100 : i*0x100+0x100]
|
||||
ReadPageTable[0xc0+i] = (*ioRom)[i*0x100 : i*0x100+0x100]
|
||||
WritePageTable[0xc0+i] = nil
|
||||
}
|
||||
|
||||
// Map $d000
|
||||
for i := 0xd0; i < 0xe0; i++ {
|
||||
base := i*0x100 + D000Bank*0x1000 - 0x2000
|
||||
if !UpperReadMappedToROM {
|
||||
ReadPageTable[i] = PhysicalMemory.MainMemory[base : base+0x100]
|
||||
}
|
||||
|
||||
if UpperRamReadOnly {
|
||||
WritePageTable[i] = nil
|
||||
} else {
|
||||
WritePageTable[i] = PhysicalMemory.MainMemory[base : base+0x100]
|
||||
}
|
||||
}
|
||||
|
||||
// Map 0xe00 to 0xffff
|
||||
for i := 0xe0; i < 0x100; i++ {
|
||||
base := i * 0x100
|
||||
if !UpperReadMappedToROM {
|
||||
ReadPageTable[i] = PhysicalMemory.MainMemory[base : base+0x100]
|
||||
}
|
||||
if UpperRamReadOnly {
|
||||
WritePageTable[i] = nil
|
||||
} else {
|
||||
WritePageTable[i] = PhysicalMemory.MainMemory[base : base+0x100]
|
||||
}
|
||||
}
|
||||
|
||||
if UpperReadMappedToROM {
|
||||
for i := 0x00; i < 0x30; i++ {
|
||||
ReadPageTable[i+0xd0] = PhysicalMemory.UpperROM[i*0x100 : i*0x100+0x100]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Map 0xc100-0xcfff for reading from RomC1
|
||||
func MapFirstHalfOfIO() {
|
||||
UsingExternalSlotRom = false
|
||||
ApplyMemoryConfiguration()
|
||||
}
|
||||
|
||||
// Map 0xc100-0xcfff for reading from RomC2
|
||||
func MapSecondHalfOfIO() {
|
||||
UsingExternalSlotRom = true
|
||||
|
||||
for i := 0x1; i < 0x10; i++ {
|
||||
PageTable[i+0xc0] = PhysicalMemory.RomC2[i*0x100 : i*0x100+0x100]
|
||||
}
|
||||
ApplyMemoryConfiguration()
|
||||
}
|
||||
|
||||
// emptySlot zeroes all RAM for a slot
|
||||
@ -44,7 +102,7 @@ func emptySlot(slot int) {
|
||||
}
|
||||
}
|
||||
|
||||
func readApple2eROM() {
|
||||
func loadApple2eROM() {
|
||||
bytes, err := ioutil.ReadFile(RomPath)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to read ROM: %s", err))
|
||||
@ -63,33 +121,75 @@ func readApple2eROM() {
|
||||
}
|
||||
|
||||
func InitApple2eROM() {
|
||||
readApple2eROM()
|
||||
loadApple2eROM()
|
||||
MapFirstHalfOfIO() // Map 0xc100-0xcfff for reading
|
||||
InitROM() // Map 0xd000-0xffff for reading
|
||||
}
|
||||
|
||||
// Map 0xc100-0xcfff
|
||||
MapFirstHalfOfIO()
|
||||
func InitROM() {
|
||||
UpperReadMappedToROM = true
|
||||
ApplyMemoryConfiguration()
|
||||
}
|
||||
|
||||
// Map 0xd000-0xffff
|
||||
for i := 0x0; i < 0x30; i++ {
|
||||
PageTable[i+0xd0] = PhysicalMemory.UpperROM[i*0x100 : i*0x100+0x100]
|
||||
}
|
||||
func SetUpperReadMappedToROM(value bool) {
|
||||
UpperReadMappedToROM = value
|
||||
ApplyMemoryConfiguration()
|
||||
}
|
||||
|
||||
func SetUpperRamReadOnly(value bool) {
|
||||
UpperRamReadOnly = value
|
||||
ApplyMemoryConfiguration()
|
||||
}
|
||||
|
||||
func SetD000Bank(value int) {
|
||||
D000Bank = value
|
||||
ApplyMemoryConfiguration()
|
||||
}
|
||||
|
||||
func InitRAM() {
|
||||
// Map main RAM
|
||||
for i := 0x0; i < 0xc0; i++ {
|
||||
PageTable[i] = PhysicalMemory.MainMemory[i*0x100 : i*0x100+0x100]
|
||||
UpperRamReadOnly = false
|
||||
D000Bank = 2
|
||||
ApplyMemoryConfiguration()
|
||||
}
|
||||
|
||||
func WipeRAM() {
|
||||
for i := 0; i < 0x10000; i++ {
|
||||
PhysicalMemory.MainMemory[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
func SetMemoryMode(mode uint8) {
|
||||
// mode corresponds to a read/write to $c080 with
|
||||
// $c080 mode=$00
|
||||
// $c08f mode=$0f
|
||||
|
||||
if (mode & 1) == 0 {
|
||||
UpperRamReadOnly = true
|
||||
} else {
|
||||
UpperRamReadOnly = false
|
||||
}
|
||||
|
||||
UsingExternalSlotRom = true
|
||||
if (((mode & 2) >> 1) ^ (mode & 1)) == 0 {
|
||||
UpperReadMappedToROM = false
|
||||
|
||||
return
|
||||
} else {
|
||||
UpperReadMappedToROM = true
|
||||
}
|
||||
|
||||
if (mode & 8) == 0 {
|
||||
D000Bank = 2
|
||||
} else {
|
||||
D000Bank = 1
|
||||
}
|
||||
|
||||
ApplyMemoryConfiguration()
|
||||
}
|
||||
|
||||
func ReadMemory(address uint16) uint8 {
|
||||
if (address >= 0xc000) && (address < 0xc100) {
|
||||
return ReadIO(address)
|
||||
} else {
|
||||
return PageTable[address>>8][address&0xff]
|
||||
return ReadPageTable[address>>8][address&0xff]
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,11 +202,15 @@ func WriteMemory(address uint16, value uint8) {
|
||||
if system.RunningInterruptTests && address == 0xbffc {
|
||||
oldValue := ReadMemory(address)
|
||||
system.WriteInterruptTestOpenCollector(address, oldValue, value)
|
||||
PageTable[uint8(address>>8)][uint8(address&0xff)] = value
|
||||
WritePageTable[uint8(address>>8)][uint8(address&0xff)] = value
|
||||
return
|
||||
}
|
||||
|
||||
PageTable[uint8(address>>8)][uint8(address&0xff)] = value
|
||||
memory := WritePageTable[address>>8]
|
||||
// If memory is nil, then it's read only. The write is ignored.
|
||||
if memory != nil {
|
||||
memory[uint8(address&0xff)] = value
|
||||
}
|
||||
|
||||
if system.RunningFunctionalTests && address == 0x200 {
|
||||
testNumber := ReadMemory(0x200)
|
||||
|
@ -122,7 +122,7 @@ func drawTextBlock(screen *ebiten.Image, start int, end int) error {
|
||||
base := 128*(y%8) + 40*(y/8)
|
||||
for x := 0; x < 40; x++ {
|
||||
offset := textVideoMemory + base + x
|
||||
value := mmu.PageTable[offset>>8][offset&0xff]
|
||||
value := mmu.ReadPageTable[offset>>8][offset&0xff]
|
||||
|
||||
if err := drawText(screen, x, y, value); err != nil {
|
||||
return err
|
||||
@ -138,7 +138,7 @@ func drawLoresBlock(screen *ebiten.Image, start int, end int) error {
|
||||
base := 128*(y%8) + 40*(y/8)
|
||||
for x := 0; x < 40; x++ {
|
||||
offset := textVideoMemory + base + x
|
||||
value := mmu.PageTable[offset>>8][offset&0xff]
|
||||
value := mmu.ReadPageTable[offset>>8][offset&0xff]
|
||||
if err := drawLores(screen, x, y, value); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -186,7 +186,7 @@ func drawHiresScreen(screen *ebiten.Image) error {
|
||||
|
||||
for x := 0; x < 40; x++ {
|
||||
offset := yOffset + x
|
||||
value := mmu.PageTable[offset>>8][offset&0xff]
|
||||
value := mmu.ReadPageTable[offset>>8][offset&0xff]
|
||||
value &= 0x7f
|
||||
|
||||
for bit := 0; bit < 7; bit++ {
|
||||
|
Loading…
x
Reference in New Issue
Block a user