Gopher2600/disassembly/memory.go
JetSetIlly af1fc91bbb improved disassembly of non-4k bank sizes
clarified disassembly memory model

corrected decision making in blessSequence() function

there will still be instances when executed entries won't/can't be detected statically

fixes #14
2021-06-30 16:25:56 +01:00

90 lines
3 KiB
Go

// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package disassembly
import (
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
"github.com/jetsetilly/gopher2600/hardware/memory/memorymap"
)
// disasmMemory is a simplified memory model that allows the emulated CPU to
// read cartridge memory without touching the actual cartridge.
type disasmMemory struct {
// the bank which the cartridge starts on
startingBank int
// current bank to index the banks array
currentBank int
banks []mapper.BankContent
// the current origin for the mapped bank
origin uint16
}
func newDisasmMemory(startingBank int, copiedBanks []mapper.BankContent) *disasmMemory {
dismem := &disasmMemory{
startingBank: startingBank,
currentBank: startingBank,
banks: copiedBanks,
}
return dismem
}
func (dismem *disasmMemory) reset() {
dismem.currentBank = dismem.startingBank
dismem.origin = dismem.banks[dismem.currentBank].Origins[0]
}
func (dismem *disasmMemory) Read(address uint16) (uint8, error) {
// map address
address, area := memorymap.MapAddress(address, true)
if area == memorymap.Cartridge {
// bring address into range. if it's still outside of range return a
// zero byte (with no error)
//
// the alternative to this strategy is to use a mask based on the
// actual length of the bank. in most cases this will be the same as
// memorymap.CartridgeBits but some cartridge mappers use banks that
// are smaller than that:
//
// address = address & uint16(len(dismem.banks[0].Data)-1)
//
// the problem with this is that the Read() function will return a byte
// which may be misleading to the disassembler. using the strategy
// below a value of zero is returned.
//
// no error is returned, even though it might seem we should, because
// it would only cause the CPU to halt mid-instruction, which would
// only cause other complications.
address = (address - dismem.origin) & memorymap.CartridgeBits
if address >= uint16(len(dismem.banks[dismem.currentBank].Data)) {
return 0, nil
}
return dismem.banks[dismem.currentBank].Data[address], nil
}
// address outside of cartridge range return nothing
return 0, nil
}
func (dismem *disasmMemory) ReadZeroPage(address uint8) (uint8, error) {
return dismem.Read(uint16(address))
}
func (dismem *disasmMemory) Write(address uint16, data uint8) error {
return nil
}