logging functions called with real env instances from the hardware package

logger package will no longer create new log entires for environments
other than the main emulation (or the logging.Always shim)
This commit is contained in:
JetSetIlly 2024-04-30 16:16:29 +01:00
parent cd2a00d4ba
commit a196b21a93
37 changed files with 271 additions and 227 deletions

View file

@ -99,6 +99,11 @@ func (env *Environment) IsEmulation(label Label) bool {
return env.Label == label
}
// AllowLogging returns true if environment is permitted to create new log entries
func (env *Environment) AllowLogging() bool {
return env.IsEmulation(MainEmulation)
}
// stub implementation of the notification interface
type notificationStub struct{}

View file

@ -133,9 +133,10 @@ func (mc *CPU) Reset() {
mc.Interrupted = true
mc.Killed = false
// checking for env == nil because it's possible for NewCPU to be
// called with a nil environment (test package)
if mc.env != nil && mc.env.Prefs.RandomState.Get().(bool) {
// nil checks because it's possibel for NewCPU to be called with a nil
// environment (disassembly) or with nil Prefs instance in the environment
// (test package)
if mc.env != nil && mc.env.Prefs != nil && mc.env.Prefs.RandomState.Get().(bool) {
mc.PC.Load(uint16(mc.env.Random.NoRewind(0xffff)))
mc.A.Load(uint8(mc.env.Random.NoRewind(0xff)))
mc.X.Load(uint8(mc.env.Random.NoRewind(0xff)))
@ -1711,7 +1712,7 @@ func (mc *CPU) ExecuteInstruction(cycleCallback func() error) error {
case instructions.KIL:
if !mc.NoFlowControl {
mc.Killed = true
logger.Logf(logger.Allow, "CPU", "KIL instruction (%#04x)", mc.PC.Address())
logger.Logf(mc.env, "CPU", "KIL instruction (%#04x)", mc.PC.Address())
}
default:

View file

@ -19,6 +19,7 @@ import (
"fmt"
"testing"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/cpu"
rtest "github.com/jetsetilly/gopher2600/hardware/cpu/registers/test"
"github.com/jetsetilly/gopher2600/test"
@ -620,7 +621,7 @@ func testKIL(t *testing.T, mc *cpu.CPU, mem *testMem) {
func TestCPU(t *testing.T) {
mem := newTestMem()
mc := cpu.NewCPU(nil, mem)
mc := cpu.NewCPU(&environment.Environment{}, mem)
testStatusInstructions(t, mc, mem)
testRegsiterArithmetic(t, mc, mem)

View file

@ -55,18 +55,18 @@ func NewAce(env *environment.Environment, loader cartridgeloader.Loader) (mapper
yieldHook: coprocessor.StubCartYieldHook{},
}
cart.mem, err = newAceMemory(data, cart.env.Prefs.ARM)
cart.mem, err = newAceMemory(env, data, cart.env.Prefs.ARM)
if err != nil {
return nil, err
}
cart.arm = arm.NewARM(cart.mem.model, cart.env.Prefs.ARM, cart.mem, cart)
cart.arm = arm.NewARM(cart.env, cart.mem.model, cart.mem, cart)
cart.mem.Plumb(cart.arm)
logger.Logf(logger.Allow, "ACE", "ccm: %08x to %08x", cart.mem.ccmOrigin, cart.mem.ccmMemtop)
logger.Logf(logger.Allow, "ACE", "flash: %08x to %08x", cart.mem.downloadOrigin, cart.mem.downloadMemtop)
logger.Logf(logger.Allow, "ACE", "buffer: %08x to %08x", cart.mem.bufferOrigin, cart.mem.bufferMemtop)
logger.Logf(logger.Allow, "ACE", "gpio: %08x to %08x", cart.mem.gpioOrigin, cart.mem.gpioMemtop)
logger.Logf(env, "ACE", "ccm: %08x to %08x", cart.mem.ccmOrigin, cart.mem.ccmMemtop)
logger.Logf(env, "ACE", "flash: %08x to %08x", cart.mem.downloadOrigin, cart.mem.downloadMemtop)
logger.Logf(env, "ACE", "buffer: %08x to %08x", cart.mem.bufferOrigin, cart.mem.bufferMemtop)
logger.Logf(env, "ACE", "gpio: %08x to %08x", cart.mem.gpioOrigin, cart.mem.gpioMemtop)
return cart, nil
}
@ -104,7 +104,7 @@ func (cart *Ace) PlumbFromDifferentEmulation(env *environment.Environment) {
if cart.armState == nil {
panic("cannot plumb this ACE instance because the ARM state is nil")
}
cart.arm = arm.NewARM(cart.mem.model, cart.env.Prefs.ARM, cart.mem, cart)
cart.arm = arm.NewARM(cart.env, cart.mem.model, cart.mem, cart)
cart.mem.Plumb(cart.arm)
cart.arm.Plumb(cart.armState, cart.mem, cart)
cart.armState = nil

View file

@ -20,6 +20,7 @@ import (
"fmt"
"github.com/jetsetilly/gopher2600/coprocessor"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm/architecture"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
@ -51,6 +52,8 @@ const (
)
type aceMemory struct {
env *environment.Environment
header aceHeader
model architecture.Map
@ -117,7 +120,7 @@ func (mem *aceMemory) setDataMode(out bool) {
}
}
func newAceMemory(data []byte, armPrefs *preferences.ARMPreferences) (*aceMemory, error) {
func newAceMemory(env *environment.Environment, data []byte, armPrefs *preferences.ARMPreferences) (*aceMemory, error) {
mem := &aceMemory{
model: architecture.NewMap(architecture.PlusCart),
}
@ -129,41 +132,41 @@ func newAceMemory(data []byte, armPrefs *preferences.ARMPreferences) (*aceMemory
// read header
mem.header.version = string(data[:aceHeaderDriverName])
logger.Logf(logger.Allow, "ACE", "header: version name: %s", mem.header.version)
logger.Logf(mem.env, "ACE", "header: version name: %s", mem.header.version)
mem.header.driverName = string(data[aceHeaderDriverName:aceHeaderDriverVersion])
logger.Logf(logger.Allow, "ACE", "header: driver name: %s", mem.header.driverName)
logger.Logf(mem.env, "ACE", "header: driver name: %s", mem.header.driverName)
mem.header.driverVersion = (uint32(data[aceHeaderDriverVersion])) |
(uint32(data[aceHeaderDriverVersion+1]) << 8) |
(uint32(data[aceHeaderDriverVersion+2]) << 16) |
(uint32(data[aceHeaderDriverVersion+3]) << 24)
logger.Logf(logger.Allow, "ACE", "header: driver version: %08x", mem.header.driverVersion)
logger.Logf(mem.env, "ACE", "header: driver version: %08x", mem.header.driverVersion)
mem.header.romSize = (uint32(data[aceHeaderROMSize])) |
(uint32(data[aceHeaderROMSize+1]) << 8) |
(uint32(data[aceHeaderROMSize+2]) << 16) |
(uint32(data[aceHeaderROMSize+3]) << 24)
logger.Logf(logger.Allow, "ACE", "header: romsize: %08x", mem.header.romSize)
logger.Logf(mem.env, "ACE", "header: romsize: %08x", mem.header.romSize)
mem.header.checksum = (uint32(data[aceHeaderROMChecksum])) |
(uint32(data[aceHeaderROMChecksum+1]) << 8) |
(uint32(data[aceHeaderROMChecksum+2]) << 16) |
(uint32(data[aceHeaderROMChecksum+3]) << 24)
logger.Logf(logger.Allow, "ACE", "header: checksum: %08x", mem.header.checksum)
logger.Logf(mem.env, "ACE", "header: checksum: %08x", mem.header.checksum)
mem.header.entry = (uint32(data[aceHeaderEntryPoint])) |
(uint32(data[aceHeaderEntryPoint+1]) << 8) |
(uint32(data[aceHeaderEntryPoint+2]) << 16) |
(uint32(data[aceHeaderEntryPoint+3]) << 24)
logger.Logf(logger.Allow, "ACE", "header: entrypoint: %08x", mem.header.entry)
logger.Logf(mem.env, "ACE", "header: entrypoint: %08x", mem.header.entry)
mem.download = data[:]
switch mem.header.version {
case "ACE-PC00":
mem.downloadOrigin = 0x08020000
mem.header.entry = 0x1028
logger.Logf(logger.Allow, "ACE", "header: entrypoint adjusted to: %08x", mem.header.entry)
logger.Logf(mem.env, "ACE", "header: entrypoint adjusted to: %08x", mem.header.entry)
case "ACE-UF00":
mem.downloadOrigin = 0x08020000
case "ACE-2600":
@ -179,7 +182,7 @@ func newAceMemory(data []byte, armPrefs *preferences.ARMPreferences) (*aceMemory
mem.resetSP = mem.ccmMemtop - 3
// note the real entry point
logger.Logf(logger.Allow, "ACE", "actual entrypoint: %08x", mem.resetPC)
logger.Logf(mem.env, "ACE", "actual entrypoint: %08x", mem.resetPC)
// define the Thumb-2 bytecode for a function whose only purpose is to jump
// back to where it came from bytecode is for instruction "BX LR" with a
@ -194,7 +197,7 @@ func newAceMemory(data []byte, armPrefs *preferences.ARMPreferences) (*aceMemory
// the code location of the null function must not be on a 16bit boundary
if arm.IsAlignedTo16bits(nullFunctionAddress) {
logger.Logf(logger.Allow, "ACE", "correcting alignment at end of ARM program")
logger.Logf(mem.env, "ACE", "correcting alignment at end of ARM program")
mem.download = append(mem.download, 0x00)
mem.downloadMemtop++
nullFunctionAddress++
@ -213,7 +216,7 @@ func newAceMemory(data []byte, armPrefs *preferences.ARMPreferences) (*aceMemory
// setting the program counter
nullFunctionAddress |= 0x01
logger.Logf(logger.Allow, "ACE", "null function place at %08x", nullFunctionAddress)
logger.Logf(mem.env, "ACE", "null function place at %08x", nullFunctionAddress)
// choose size for the remainder of the flash memory and place at the flash
// origin value for architecture

View file

@ -17,10 +17,6 @@
// differences in cartridge and ARM archtectures.
package architecture
import (
"github.com/jetsetilly/gopher2600/logger"
)
// CartArchitecture defines the memory map for the ARM.
type CartArchitecture string
@ -113,7 +109,7 @@ func NewMap(cart CartArchitecture) Map {
switch mmap.CartArchitecture {
default:
logger.Logf(logger.Allow, "ARM Architecture", "unknown cartridge architecture (%s) defaulting to Harmony", cart)
// logger.Logf(env, "ARM Architecture", "unknown cartridge architecture (%s) defaulting to Harmony", cart)
mmap.CartArchitecture = Harmony
fallthrough
@ -175,9 +171,9 @@ func NewMap(cart CartArchitecture) Map {
mmap.ClkDiv = 0.5
}
logger.Logf(logger.Allow, "ARM Architecture", "using %s/%s", mmap.CartArchitecture, mmap.ARMArchitecture)
logger.Logf(logger.Allow, "ARM Architecture", "flash origin: %#08x", mmap.FlashOrigin)
logger.Logf(logger.Allow, "ARM Architecture", "sram origin: %#08x", mmap.SRAMOrigin)
// logger.Logf(env, "ARM Architecture", "using %s/%s", mmap.CartArchitecture, mmap.ARMArchitecture)
// logger.Logf(env, "ARM Architecture", "flash origin: %#08x", mmap.FlashOrigin)
// logger.Logf(env, "ARM Architecture", "sram origin: %#08x", mmap.SRAMOrigin)
return mmap
}

View file

@ -24,10 +24,10 @@ import (
"github.com/jetsetilly/gopher2600/coprocessor"
"github.com/jetsetilly/gopher2600/coprocessor/developer/faults"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm/architecture"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm/fpu"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm/peripherals"
"github.com/jetsetilly/gopher2600/hardware/preferences"
"github.com/jetsetilly/gopher2600/logger"
)
@ -198,10 +198,10 @@ func (s *ARMState) Snapshot() *ARMState {
// ARM implements the ARM7TDMI-S LPC2103 processor.
type ARM struct {
prefs *preferences.ARMPreferences
mmap architecture.Map
mem SharedMemory
hook CartridgeHook
env *environment.Environment
mmap architecture.Map
mem SharedMemory
hook CartridgeHook
// the binary interface for reading data returned by SharedMemory interface.
// defaults to LittleEndian
@ -286,9 +286,9 @@ type ARM struct {
}
// NewARM is the preferred method of initialisation for the ARM type.
func NewARM(mmap architecture.Map, prefs *preferences.ARMPreferences, mem SharedMemory, hook CartridgeHook) *ARM {
func NewARM(env *environment.Environment, mmap architecture.Map, mem SharedMemory, hook CartridgeHook) *ARM {
arm := &ARM{
prefs: prefs,
env: env,
mmap: mmap,
mem: mem,
hook: hook,
@ -319,8 +319,8 @@ func NewARM(mmap architecture.Map, prefs *preferences.ARMPreferences, mem Shared
panic(fmt.Sprintf("unhandled ARM architecture: cannot set %s", arm.mmap.ARMArchitecture))
}
arm.state.mam = newMam(arm.prefs, arm.mmap)
arm.state.rng = peripherals.NewRNG(arm.mmap)
arm.state.mam = newMam(arm.env, arm.mmap)
arm.state.rng = peripherals.NewRNG(arm.env, arm.mmap)
arm.state.timer = peripherals.NewTimer(arm.mmap)
arm.state.timer2 = peripherals.NewTimer2(arm.mmap)
@ -440,12 +440,12 @@ func (arm *ARM) resetRegisters() {
// prefsPulse ticker
func (arm *ARM) updatePrefs() {
// update clock value from preferences
arm.Clk = float32(arm.prefs.Clock.Get().(float64))
arm.Clk = float32(arm.env.Prefs.ARM.Clock.Get().(float64))
arm.state.mam.updatePrefs()
// set cycle counting functions
arm.immediateMode = arm.prefs.Immediate.Get().(bool)
arm.immediateMode = arm.env.Prefs.ARM.Immediate.Get().(bool)
if arm.immediateMode {
arm.Icycle = arm.iCycleStub
arm.Scycle = arm.sCycleStub
@ -456,8 +456,8 @@ func (arm *ARM) updatePrefs() {
arm.Ncycle = arm.nCycle
}
arm.abortOnMemoryFault = arm.prefs.AbortOnMemoryFault.Get().(bool)
arm.misalignedAccessIsFault = arm.prefs.MisalignedAccessIsFault.Get().(bool)
arm.abortOnMemoryFault = arm.env.Prefs.ARM.AbortOnMemoryFault.Get().(bool)
arm.misalignedAccessIsFault = arm.env.Prefs.ARM.MisalignedAccessIsFault.Get().(bool)
}
func (arm *ARM) String() string {
@ -516,14 +516,14 @@ func (arm *ARM) logYield() {
return
}
if arm.state.yield.Error != nil {
logger.Logf(logger.Allow, "ARM7", "%s: %s", arm.state.yield.Type.String(), arm.state.yield.Error.Error())
logger.Logf(arm.env, "ARM7", "%s: %s", arm.state.yield.Type.String(), arm.state.yield.Error.Error())
} else {
logger.Logf(logger.Allow, "ARM7", "%s: no specific error", arm.state.yield.Type.String())
logger.Logf(arm.env, "ARM7", "%s: no specific error", arm.state.yield.Type.String())
}
// extended memory logging
if arm.prefs.ExtendedMemoryFaultLogging.Get().(bool) == false {
if arm.env.Prefs.ARM.ExtendedMemoryFaultLogging.Get().(bool) == false {
return
}
@ -543,8 +543,8 @@ func (arm *ARM) logYield() {
entry := arm.decodeInstruction(df)
if entry != nil {
logger.Logf(logger.Allow, "ARM7", "%s", entry.String())
logger.Logf(logger.Allow, "ARM7", "%s", arm.disasmVerbose(*entry))
logger.Logf(arm.env, "ARM7", "%s", entry.String())
logger.Logf(arm.env, "ARM7", "%s", arm.disasmVerbose(*entry))
}
}
@ -898,13 +898,13 @@ func (arm *ARM) run() (coprocessor.CoProcYield, float32) {
// limit the number of cycles used by the ARM program
if arm.state.cyclesTotal >= cycleLimit {
logger.Logf(logger.Allow, "ARM7", "reached cycle limit of %d", cycleLimit)
logger.Logf(arm.env, "ARM7", "reached cycle limit of %d", cycleLimit)
panic("cycle limit")
}
} else {
iterations++
if iterations > instructionsLimit {
logger.Logf(logger.Allow, "ARM7", "reached instructions limit of %d", instructionsLimit)
logger.Logf(arm.env, "ARM7", "reached instructions limit of %d", instructionsLimit)
panic("instruction limit")
}
}

View file

@ -16,6 +16,7 @@
package arm
import (
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm/architecture"
"github.com/jetsetilly/gopher2600/hardware/preferences"
"github.com/jetsetilly/gopher2600/logger"
@ -24,8 +25,8 @@ import (
// MAM implements the memory addressing module as found in the LPC20000. Not
// fully implemented but good enough for most Harmony games
type mam struct {
prefs *preferences.ARMPreferences
mmap architecture.Map
env *environment.Environment
mmap architecture.Map
// valid values for mamcr are 0, 1 or 2 are valid. we can think of these
// respectively, as "disable", "partial" and "full"
@ -51,10 +52,10 @@ type mam struct {
prefectchAborted bool
}
func newMam(prefs *preferences.ARMPreferences, mmap architecture.Map) mam {
func newMam(env *environment.Environment, mmap architecture.Map) mam {
return mam{
prefs: prefs,
mmap: mmap,
env: env,
mmap: mmap,
}
}
@ -62,7 +63,7 @@ func (m *mam) Reset() {
}
func (m *mam) updatePrefs() {
m.pref = m.prefs.MAM.Get().(int)
m.pref = m.env.Prefs.ARM.MAM.Get().(int)
if m.pref == preferences.MAMDriver {
m.mamcr = m.mmap.PreferredMAMCR
m.mamtim = 4.0
@ -83,7 +84,7 @@ func (m *mam) Write(addr uint32, val uint32) bool {
if m.mamcr == 0 {
m.mamtim = val
} else {
logger.Logf(logger.Allow, "ARM7", "trying to write to MAMTIM while MAMCR is active")
logger.Logf(m.env, "ARM7", "trying to write to MAMTIM while MAMCR is active")
}
}
default:
@ -111,6 +112,6 @@ func (m *mam) Read(addr uint32) (uint32, bool) {
func (m *mam) setMAMCR(val architecture.MAMCR) {
m.mamcr = val
if m.mamcr > 2 {
logger.Logf(logger.Allow, "ARM7", "setting MAMCR to a value greater than 2 (%#08x)", m.mamcr)
logger.Logf(m.env, "ARM7", "setting MAMCR to a value greater than 2 (%#08x)", m.mamcr)
}
}

View file

@ -18,6 +18,7 @@ package peripherals
import (
"math/rand"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm/architecture"
"github.com/jetsetilly/gopher2600/logger"
)
@ -33,6 +34,7 @@ import (
// purposes it's probably okay. It basically returns a random 32bit number
// whenever the data register is read
type RNG struct {
env *environment.Environment
mmap architecture.Map
// control register value
@ -48,8 +50,9 @@ type RNG struct {
interruptEnabled bool
}
func NewRNG(mmap architecture.Map) RNG {
func NewRNG(env *environment.Environment, mmap architecture.Map) RNG {
return RNG{
env: env,
mmap: mmap,
}
}
@ -67,10 +70,10 @@ func (r *RNG) Write(addr uint32, val uint32) bool {
r.interruptEnabled = r.control&0b1000 == 0b1000
case r.mmap.RNGSR:
// status register
logger.Logf(logger.Allow, "ARM7", "ignoring write to RNG status register (value of %08x)", val)
logger.Logf(r.env, "ARM7", "ignoring write to RNG status register (value of %08x)", val)
case r.mmap.RNGDR:
// data register
logger.Logf(logger.Allow, "ARM7", "ignoring write to RNG data register (value of %08x)", val)
logger.Logf(r.env, "ARM7", "ignoring write to RNG data register (value of %08x)", val)
default:
return false
}

View file

@ -211,7 +211,7 @@ func (arm *ARM) decodeThumbMoveShiftedRegister(opcode uint16) decodeFunction {
}
if destReg == rPC {
logger.Log(logger.Allow, "ARM7", "shift and store in PC is not possible in thumb mode")
logger.Log(arm.env, "ARM7", "shift and store in PC is not possible in thumb mode")
}
// "7.6 Data Operations" in "ARM7TDMI-S Technical Reference Manual r4p3"
@ -763,7 +763,7 @@ func (arm *ARM) decodeThumbALUoperations(opcode uint16) decodeFunction {
// page 7-11 in "ARM7TDMI-S Technical Reference Manual r4p3"
if shift > 0 && destReg == rPC {
logger.Log(logger.Allow, "ARM7", "shift and store in PC is not possible in thumb mode")
logger.Log(arm.env, "ARM7", "shift and store in PC is not possible in thumb mode")
}
if mul {

View file

@ -230,7 +230,7 @@ func (arm *ARM) decodeThumb2ChangeProcessorState(opcode uint16) decodeFunction {
Operator: "CPSID",
}
}
logger.Logf(logger.Allow, "ARM7", "CPSID instruction does nothing")
logger.Logf(arm.env, "ARM7", "CPSID instruction does nothing")
return nil
}
}

View file

@ -208,7 +208,7 @@ func (cart *Cartridge) Attach(cartload cartridgeloader.Loader) error {
cart.coprocBus, cart.hasCoProcBus = cart.mapper.(coprocessor.CartCoProcBus)
if _, ok := cart.mapper.(*ejected); !ok {
logger.Logf(logger.Allow, "cartridge", "inserted %s", cart.mapper.ID())
logger.Logf(cart.env, "cartridge", "inserted %s", cart.mapper.ID())
}
}()
@ -326,7 +326,7 @@ func (cart *Cartridge) Attach(cartload cartridgeloader.Loader) error {
if superchip, ok := cart.mapper.(mapper.OptionalSuperchip); ok {
superchip.AddSuperchip(true)
} else {
logger.Logf(logger.Allow, "cartridge", "cannot add superchip to %s mapper", cart.ID())
logger.Logf(cart.env, "cartridge", "cannot add superchip to %s mapper", cart.ID())
}
} else if superchip, ok := cart.mapper.(mapper.OptionalSuperchip); ok {
superchip.AddSuperchip(false)
@ -345,17 +345,17 @@ func (cart *Cartridge) Attach(cartload cartridgeloader.Loader) error {
if err != nil {
if errors.Is(err, plusrom.NotAPlusROM) {
logger.Log(logger.Allow, "cartridge", err.Error())
logger.Log(cart.env, "cartridge", err.Error())
return nil
}
if errors.Is(err, plusrom.CannotAdoptROM) {
logger.Log(logger.Allow, "cartridge", err.Error())
logger.Log(cart.env, "cartridge", err.Error())
return nil
}
return fmt.Errorf("cartridge: %w", err)
}
logger.Logf(logger.Allow, "cartridge", "%s cartridge contained in PlusROM", cart.ID())
logger.Logf(cart.env, "cartridge", "%s cartridge contained in PlusROM", cart.ID())
// we've wrapped the main cartridge mapper inside the PlusROM
// mapper and we need to point the mapper field to the the new

View file

@ -132,7 +132,7 @@ func NewCDF(env *environment.Environment, loader cartridgeloader.Loader, version
//
// if bank0 has any ARM code then it will start at offset 0x08. first eight
// bytes are the ARM header
cart.arm = arm.NewARM(cart.version.mmap, cart.env.Prefs.ARM, cart.state.static, cart)
cart.arm = arm.NewARM(cart.env, cart.version.mmap, cart.state.static, cart)
return cart, nil
}
@ -180,7 +180,7 @@ func (cart *cdf) PlumbFromDifferentEmulation(env *environment.Environment) {
if cart.armState == nil {
panic("cannot plumb this ELF instance because the ARM state is nil")
}
cart.arm = arm.NewARM(cart.version.mmap, cart.env.Prefs.ARM, cart.state.static, cart)
cart.arm = arm.NewARM(cart.env, cart.version.mmap, cart.state.static, cart)
cart.arm.Plumb(cart.armState, cart.state.static, cart)
cart.armState = nil
cart.yieldHook = &coprocessor.StubCartYieldHook{}

View file

@ -117,7 +117,7 @@ func NewDPCplus(env *environment.Environment, loader cartridgeloader.Loader) (ma
//
// if bank0 has any ARM code then it will start at offset 0x08. first eight
// bytes are the ARM header
cart.arm = arm.NewARM(cart.version.mmap, env.Prefs.ARM, cart.state.static, cart)
cart.arm = arm.NewARM(cart.env, cart.version.mmap, cart.state.static, cart)
return cart, nil
}
@ -165,7 +165,7 @@ func (cart *dpcPlus) PlumbFromDifferentEmulation(env *environment.Environment) {
if cart.armState == nil {
panic("cannot plumb this ELF instance because the ARM state is nil")
}
cart.arm = arm.NewARM(cart.version.mmap, cart.env.Prefs.ARM, cart.state.static, cart)
cart.arm = arm.NewARM(cart.env, cart.version.mmap, cart.state.static, cart)
cart.arm.Plumb(cart.armState, cart.state.static, cart)
cart.armState = nil
cart.yieldHook = &coprocessor.StubCartYieldHook{}
@ -487,7 +487,7 @@ func (cart *dpcPlus) AccessVolatile(addr uint16, data uint8, poke bool) error {
case 1:
// copy rom to fetcher
if len(cart.state.parameters) != 4 {
logger.Logf(logger.Allow, "DPC+", "wrong number of parameters for function call [%02x]", data)
logger.Logf(cart.env, "DPC+", "wrong number of parameters for function call [%02x]", data)
break // switch data
}
@ -504,7 +504,7 @@ func (cart *dpcPlus) AccessVolatile(addr uint16, data uint8, poke bool) error {
case 2:
// copy value to fetcher
if len(cart.state.parameters) != 4 {
logger.Logf(logger.Allow, "DPC+", "wrong number of parameters for function call [%02x]", data)
logger.Logf(cart.env, "DPC+", "wrong number of parameters for function call [%02x]", data)
break // switch data
}

View file

@ -22,6 +22,7 @@ import (
"io"
"os"
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/coprocessor"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/arm"
@ -32,10 +33,9 @@ import (
// Elf implements the mapper.CartMapper interface.
type Elf struct {
env *environment.Environment
version string
pathToROM string
env *environment.Environment
loader cartridgeloader.Loader
version string
arm *arm.ARM
mem *elfMemory
@ -75,12 +75,12 @@ func (r *elfReaderAt) ReadAt(p []byte, start int64) (n int, err error) {
}
// NewElf is the preferred method of initialisation for the Elf type.
func NewElf(env *environment.Environment, pathToROM string, inACE bool) (mapper.CartMapper, error) {
func NewElf(env *environment.Environment, loader cartridgeloader.Loader, inACE bool) (mapper.CartMapper, error) {
r := &elfReaderAt{}
// open file in the normal way and read all data. close the file
// immediately once all data is rad
o, err := os.Open(pathToROM)
o, err := os.Open(loader.Filename)
if err != nil {
return nil, fmt.Errorf("ELF: %w", err)
}
@ -131,12 +131,12 @@ func NewElf(env *environment.Environment, pathToROM string, inACE bool) (mapper.
cart := &Elf{
env: env,
pathToROM: pathToROM,
loader: loader,
yieldHook: coprocessor.StubCartYieldHook{},
}
cart.mem = newElfMemory(env)
cart.arm = arm.NewARM(cart.mem.model, cart.env.Prefs.ARM, cart.mem, cart)
cart.mem = newElfMemory(cart.env)
cart.arm = arm.NewARM(cart.env, cart.mem.model, cart.mem, cart)
cart.mem.Plumb(cart.arm)
err = cart.mem.decode(ef)
if err != nil {
@ -191,7 +191,7 @@ func (cart *Elf) PlumbFromDifferentEmulation(env *environment.Environment) {
if cart.armState == nil {
panic("cannot plumb this ELF instance because the ARM state is nil")
}
cart.arm = arm.NewARM(cart.mem.model, cart.env.Prefs.ARM, cart.mem, cart)
cart.arm = arm.NewARM(cart.env, cart.mem.model, cart.mem, cart)
cart.arm.Plumb(cart.armState, cart.mem, cart)
cart.armState = nil
cart.mem.Plumb(cart.arm)

View file

@ -214,13 +214,13 @@ func (mem *elfMemory) decode(ef *elf.File) error {
section.memtop += section.trailingBytes - 1
}
logger.Logf(logger.Allow, "ELF", "%s: %08x to %08x (%d) [%d trailing bytes]",
logger.Logf(mem.env, "ELF", "%s: %08x to %08x (%d) [%d trailing bytes]",
section.name, section.origin, section.memtop, len(section.data), section.trailingBytes)
if section.readOnly() {
logger.Logf(logger.Allow, "ELF", "%s: is readonly", section.name)
logger.Logf(mem.env, "ELF", "%s: is readonly", section.name)
}
if section.executable() {
logger.Logf(logger.Allow, "ELF", "%s: is executable", section.name)
logger.Logf(mem.env, "ELF", "%s: is executable", section.name)
}
}
@ -271,10 +271,10 @@ func (mem *elfMemory) decode(ef *elf.File) error {
// value will be out of range according to the MapAddress check (2) the
// offset value can go beyond the end of the .debug_macro data slice
if secBeingRelocated.name == ".debug_macro" {
logger.Logf(logger.Allow, "ELF", "not relocating %s", secBeingRelocated.name)
logger.Logf(mem.env, "ELF", "not relocating %s", secBeingRelocated.name)
continue
} else {
logger.Logf(logger.Allow, "ELF", "relocating %s", secBeingRelocated.name)
logger.Logf(mem.env, "ELF", "relocating %s", secBeingRelocated.name)
}
// relocation data. we walk over the data and extract the relocation
@ -507,7 +507,7 @@ func (mem *elfMemory) decode(ef *elf.File) error {
if sym.Section == elf.SHN_UNDEF {
// for R_ARM_ABS32 type symbols we create a stub function and use it to
// generate a memory fault when it's accessed
logger.Logf(logger.Allow, "ELF", "using stub for %s (will cause memory fault when called)", sym.Name)
logger.Logf(mem.env, "ELF", "using stub for %s (will cause memory fault when called)", sym.Name)
tgt, err = mem.relocateStrongArmFunction(strongArmFunctionSpec{
function: func(mem *elfMemory) {
mem.arm.MemoryFault(sym.Name, faults.UndefinedSymbol)
@ -548,7 +548,7 @@ func (mem *elfMemory) decode(ef *elf.File) error {
if name == "" {
name = "anonymous"
}
logger.Logf(logger.Allow, "ELF", "relocate %s (%08x) => %08x", name, secBeingRelocated.origin+offset, tgt)
logger.Logf(mem.env, "ELF", "relocate %s (%08x) => %08x", name, secBeingRelocated.origin+offset, tgt)
case elf.R_ARM_THM_PC22:
// this value is labelled R_ARM_THM_CALL in objdump output
@ -606,7 +606,7 @@ func (mem *elfMemory) decode(ef *elf.File) error {
if name == "" {
name = "anonymous"
}
logger.Logf(logger.Allow, "ELF", "relocate %s (%08x) => opcode %08x", name, secBeingRelocated.origin+offset, opcode)
logger.Logf(mem.env, "ELF", "relocate %s (%08x) => opcode %08x", name, secBeingRelocated.origin+offset, opcode)
default:
return fmt.Errorf("ELF: unhandled ARM relocation type (%v)", relType)
@ -618,7 +618,7 @@ func (mem *elfMemory) decode(ef *elf.File) error {
mem.strongArmMemtop -= 1
// strongarm address information
logger.Logf(logger.Allow, "ELF", "strongarm: %08x to %08x (%d)",
logger.Logf(mem.env, "ELF", "strongarm: %08x to %08x (%d)",
mem.strongArmOrigin, mem.strongArmMemtop, len(mem.strongArmProgram))
// SRAM creation
@ -660,7 +660,7 @@ func (mem *elfMemory) runInitialisation(arm *arm.ARM) error {
}
mem.resetPC &= 0xfffffffe
logger.Logf(logger.Allow, "ELF", "running %s at %08x", sec.name, mem.resetPC)
logger.Logf(mem.env, "ELF", "running %s at %08x", sec.name, mem.resetPC)
_, _ = arm.Run()
}
}
@ -814,7 +814,7 @@ func (mem *elfMemory) MapAddress(addr uint32, write bool) (*[]byte, uint32) {
func (mem *elfMemory) mapAddress(addr uint32, write bool) (*[]byte, uint32) {
if addr >= mem.gpio.dataOrigin && addr <= mem.gpio.dataMemtop {
if mem.stream.active {
logger.Log(logger.Allow, "ELF", "disabling byte streaming")
logger.Log(mem.env, "ELF", "disabling byte streaming")
mem.stream.active = false
}
if !write && addr == mem.gpio.dataOrigin|ADDR_IDR {

View file

@ -121,7 +121,7 @@ func (cart *atari) ROMDump(filename string) error {
defer func() {
err := f.Close()
if err != nil {
logger.Logf(logger.Allow, "%s", cart.mappingID, err.Error())
logger.Logf(cart.env, "%s", cart.mappingID, err.Error())
}
}()

View file

@ -73,10 +73,10 @@ func newCommaVid(env *environment.Environment, loader cartridgeloader.Loader) (m
if len(data) < 2048 {
// place undersized binaries at the end of memory
copy(cart.bankData[4096-len(data):], data)
logger.Logf(logger.Allow, "CV", "placing undersized commavid data at end of cartridge memory")
logger.Logf(env, "CV", "placing undersized commavid data at end of cartridge memory")
} else if len(data) == 2048 {
copy(cart.bankData[2048:], data[:2048])
logger.Logf(logger.Allow, "CV", "placing 2k commavid data at end of cartridge memory")
logger.Logf(env, "CV", "placing 2k commavid data at end of cartridge memory")
} else {
return nil, fmt.Errorf("CV: unhandled size for commavid cartridges (%d)", len(data))
}

View file

@ -71,7 +71,7 @@ func newUA(env *environment.Environment, loader cartridgeloader.Loader) (mapper.
// only one cartridge dump is known to have swapped hotspots
if fmt.Sprintf("%0x", sha1.Sum(data)) == "6d4a94c2348bbd8e9c73b73d8f3389196d42fd54" {
cart.swappedHotspots = true
logger.Logf(logger.Allow, "UA", "swapping hotspot address for this cartridge (Sorcerer's Apprentice)")
logger.Logf(env, "UA", "swapping hotspot address for this cartridge (Sorcerer's Apprentice)")
}
return cart, nil

View file

@ -415,7 +415,7 @@ func (cart *Moviecart) processAddress(addr uint16) {
defer func() {
if r := recover(); r != nil {
cart.state.streamFail = true
logger.Logf(logger.Allow, "MVC", "serious data error in moviecart stream")
logger.Logf(cart.env, "MVC", "serious data error in moviecart stream")
}
}()
@ -443,7 +443,7 @@ func (cart *Moviecart) processAddress(addr uint16) {
err := cart.env.Notifications.Notify(notifications.NotifyMovieCartStarted)
if err != nil {
logger.Logf(logger.Allow, "moviecart", err.Error())
logger.Logf(cart.env, "moviecart", err.Error())
}
} else if cart.state.totalCycles > titleCycles {
@ -971,12 +971,12 @@ func (cart *Moviecart) nextField() {
dataOffset := cart.state.streamChunk * chunkSize
_, err := cart.data.Seek(int64(dataOffset), io.SeekStart)
if err != nil {
logger.Logf(logger.Allow, "MVC", "error seeking field: %v", err)
logger.Logf(cart.env, "MVC", "error seeking field: %v", err)
}
n, err := cart.data.Read(cart.state.streamBuffer[cart.state.streamIndex])
if err != nil {
if !errors.Is(err, io.EOF) {
logger.Logf(logger.Allow, "MVC", "error reading field: %v", err)
logger.Logf(cart.env, "MVC", "error reading field: %v", err)
}
}
cart.state.endOfStream = n < fieldSize
@ -994,11 +994,11 @@ func (cart *Moviecart) nextField() {
dataOffset := cart.state.streamChunk * chunkSize
_, err := cart.data.Seek(int64(dataOffset), io.SeekStart)
if err != nil {
logger.Logf(logger.Allow, "MVC", "error reading field: %v", err)
logger.Logf(cart.env, "MVC", "error reading field: %v", err)
}
_, err = cart.data.Read(cart.state.streamBuffer[fld])
if err != nil {
logger.Logf(logger.Allow, "MVC", "error reading field: %v", err)
logger.Logf(cart.env, "MVC", "error reading field: %v", err)
}
}
}
@ -1008,7 +1008,7 @@ func (cart *Moviecart) nextField() {
cart.state.streamBuffer[cart.state.streamIndex][1] != 'V' ||
cart.state.streamBuffer[cart.state.streamIndex][2] != 'C' ||
cart.state.streamBuffer[cart.state.streamIndex][3] != 0x00 {
logger.Logf(logger.Allow, "MVC", "unrecognised version string in chunk %d", cart.state.streamChunk)
logger.Logf(cart.env, "MVC", "unrecognised version string in chunk %d", cart.state.streamChunk)
return
}

View file

@ -115,11 +115,11 @@ func (n *network) transmit() {
n.sendLock.Lock()
defer n.sendLock.Unlock()
logger.Logf(logger.Allow, "plusrom [net]", "sending to %s", addr.String())
logger.Logf(n.env, "plusrom [net]", "sending to %s", addr.String())
req, err := http.NewRequest("POST", addr.String(), &send)
if err != nil {
logger.Log(logger.Allow, "plusrom [net]", err.Error())
logger.Log(n.env, "plusrom [net]", err.Error())
return
}
@ -146,7 +146,7 @@ func (n *network) transmit() {
n.env.Prefs.PlusROM.Nick.String(),
)
req.Header.Set("PlusROM-Info", id)
logger.Logf(logger.Allow, "plusrom [net]", "PlusROM-Info: %s", id)
logger.Logf(n.env, "plusrom [net]", "PlusROM-Info: %s", id)
// -----------------------------------------------
// PlusCart firmware earlier han v2.1.1
@ -158,7 +158,7 @@ func (n *network) transmit() {
//
// id := fmt.Sprintf("%s WE%s", n.env.Prefs.PlusROM.Nick.String(), n.env.Prefs.PlusROM.ID.String())
// req.Header.Set("PlusStore-ID", id)
// logger.Logf(logger.Allow, "plusrom [net]", "PlusStore-ID: %s", id)
// logger.Logf(env, "plusrom [net]", "PlusStore-ID: %s", id)
// -----------------------------------------------
// whether to log HTTP transactions taken from the global preferences
@ -167,13 +167,13 @@ func (n *network) transmit() {
// log of complete request
if httpLogging {
s, _ := httputil.DumpRequest(req, true)
logger.Logf(logger.Allow, "plusrom [net]", "request: %q", s)
logger.Logf(n.env, "plusrom [net]", "request: %q", s)
}
// send response over network
resp, err := http.DefaultClient.Do(req)
if err != nil {
logger.Log(logger.Allow, "plusrom [net]", err.Error())
logger.Log(n.env, "plusrom [net]", err.Error())
return
}
defer resp.Body.Close()
@ -181,20 +181,20 @@ func (n *network) transmit() {
// log of complete response
if httpLogging {
s, _ := httputil.DumpResponse(resp, true)
logger.Logf(logger.Allow, "plusrom [net]", "response: %q", s)
logger.Logf(n.env, "plusrom [net]", "response: %q", s)
}
// pass response to main goroutine
var r bytes.Buffer
_, err = r.ReadFrom(resp.Body)
if err != nil {
logger.Logf(logger.Allow, "plusrom [net]", "response: %v", err)
logger.Logf(n.env, "plusrom [net]", "response: %v", err)
}
n.respChan <- r
}(sendBuffer, n.ai)
// log send buffer
logger.Log(logger.Allow, "plusrom [net] sent", fmt.Sprintf("% 02x", n.send.Buffer[:n.send.SendLen]))
logger.Log(n.env, "plusrom [net] sent", fmt.Sprintf("% 02x", n.send.Buffer[:n.send.SendLen]))
// a copy of the sendBuffer has been passed to the new goroutine so we
// can now clear the references buffer
@ -206,16 +206,16 @@ func (n *network) transmit() {
func (n *network) getResponse() {
select {
case r := <-n.respChan:
logger.Logf(logger.Allow, "plusrom [net]", "received %d bytes", r.Len())
logger.Logf(n.env, "plusrom [net]", "received %d bytes", r.Len())
l, err := r.ReadByte()
if err != nil {
logger.Log(logger.Allow, "plusrom", err.Error())
logger.Log(n.env, "plusrom", err.Error())
return
}
if int(l) != r.Len() {
logger.Log(logger.Allow, "plusrom [net]", "unexpected length received")
logger.Log(n.env, "plusrom [net]", "unexpected length received")
}
// from http://pluscart.firmaplus.de/pico/?PlusROM
@ -228,12 +228,12 @@ func (n *network) getResponse() {
// header of the response.
_, err = n.recvBuffer.ReadFrom(&r)
if err != nil {
logger.Log(logger.Allow, "plusrom", err.Error())
logger.Log(n.env, "plusrom", err.Error())
return
}
if n.recvBuffer.Len() > recvBufferCap {
logger.Log(logger.Allow, "plusrom", "receive buffer is full")
logger.Log(n.env, "plusrom", "receive buffer is full")
n.recvBuffer.Truncate(recvBufferCap)
}
@ -257,7 +257,7 @@ func (n *network) recv() uint8 {
b, err := n.recvBuffer.ReadByte()
if err != nil {
logger.Log(logger.Allow, "plusrom", err.Error())
logger.Log(n.env, "plusrom", err.Error())
}
return b
}

View file

@ -137,7 +137,7 @@ func NewPlusROM(env *environment.Environment, child mapper.CartMapper) (mapper.C
}
// log success
logger.Logf(logger.Allow, "plusrom", "will connect to %s", cart.net.ai.String())
logger.Logf(env, "plusrom", "will connect to %s", cart.net.ai.String())
if cart.env.Prefs.PlusROM.NewInstallation {
err := cart.env.Notifications.Notify(notifications.NotifyPlusROMNewInstall)

View file

@ -20,6 +20,7 @@ import (
"os"
"path/filepath"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/logger"
"github.com/jetsetilly/gopher2600/resources"
)
@ -39,7 +40,7 @@ const biosLogTag = "supercharger: bios"
// - current working directory
// - the same directory as the tape/bin file
// - the emulator's resource path
func loadBIOS(path string) ([]uint8, error) {
func loadBIOS(env *environment.Environment, path string) ([]uint8, error) {
// current working directory
for _, b := range biosFile {
d, err := _loadBIOS(b)
@ -52,7 +53,7 @@ func loadBIOS(path string) ([]uint8, error) {
return nil, fmt.Errorf("bios: file (%s) is not 2k", b)
}
logger.Logf(logger.Allow, biosLogTag, "using %s (from current working directory)", b)
logger.Logf(env, biosLogTag, "using %s (from current working directory)", b)
return d, nil
}
@ -69,7 +70,7 @@ func loadBIOS(path string) ([]uint8, error) {
return nil, fmt.Errorf("bios: file (%s) is not 2k", p)
}
logger.Logf(logger.Allow, biosLogTag, "using %s (from the same path as the game ROM)", p)
logger.Logf(env, biosLogTag, "using %s (from the same path as the game ROM)", p)
return d, nil
}
@ -90,7 +91,7 @@ func loadBIOS(path string) ([]uint8, error) {
return nil, fmt.Errorf("bios: file (%s) is not 2k", p)
}
logger.Logf(logger.Allow, biosLogTag, "using %s (from the resource path)", p)
logger.Logf(env, biosLogTag, "using %s (from the resource path)", p)
return d, nil
}

View file

@ -20,6 +20,7 @@ import (
"io"
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/cpu"
"github.com/jetsetilly/gopher2600/hardware/memory/vcs"
"github.com/jetsetilly/gopher2600/hardware/riot/timer"
@ -39,6 +40,7 @@ import (
// From: Eckhard Stolberg
// Date: Fri, 08 Jan 1999.
type FastLoad struct {
env *environment.Environment
cart *Supercharger
// fastload binaries have a header which controls how the binary is read
@ -83,12 +85,13 @@ type fastloadBlock struct {
}
// newFastLoad is the preferred method of initialisation for the FastLoad type.
func newFastLoad(cart *Supercharger, loader cartridgeloader.Loader) (tape, error) {
func newFastLoad(env *environment.Environment, cart *Supercharger, loader cartridgeloader.Loader) (tape, error) {
if loader.Size()%fastLoadBlockLen != 0 {
return nil, fmt.Errorf("fastload: wrong number of bytes in cartridge data")
}
fl := &FastLoad{
env: env,
cart: cart,
}
@ -112,13 +115,13 @@ func newFastLoad(cart *Supercharger, loader cartridgeloader.Loader) (tape, error
fl.blocks[i].progressSpeed = (uint16(gameHeader[7]) << 8) | uint16(gameHeader[6])
fl.blocks[i].pageTable = gameHeader[0x10:0x28]
logger.Logf(logger.Allow, "supercharger: fastload", "block %d: start address: %#04x", i, fl.blocks[i].startAddress)
logger.Logf(logger.Allow, "supercharger: fastload", "block %d: config byte: %#08b", i, fl.blocks[i].configByte)
logger.Logf(logger.Allow, "supercharger: fastload", "block %d: num pages: %d", i, fl.blocks[i].numPages)
logger.Logf(logger.Allow, "supercharger: fastload", "block %d: checksum: %#02x", i, fl.blocks[i].checksum)
logger.Logf(logger.Allow, "supercharger: fastload", "block %d: multiload: %#02x", i, fl.blocks[i].multiload)
logger.Logf(logger.Allow, "supercharger: fastload", "block %d: progress speed: %#02x", i, fl.blocks[i].progressSpeed)
logger.Logf(logger.Allow, "supercharger: fastload", "block %d: page-table: %v", i, fl.blocks[i].pageTable)
logger.Logf(fl.env, "supercharger: fastload", "block %d: start address: %#04x", i, fl.blocks[i].startAddress)
logger.Logf(fl.env, "supercharger: fastload", "block %d: config byte: %#08b", i, fl.blocks[i].configByte)
logger.Logf(fl.env, "supercharger: fastload", "block %d: num pages: %d", i, fl.blocks[i].numPages)
logger.Logf(fl.env, "supercharger: fastload", "block %d: checksum: %#02x", i, fl.blocks[i].checksum)
logger.Logf(fl.env, "supercharger: fastload", "block %d: multiload: %#02x", i, fl.blocks[i].multiload)
logger.Logf(fl.env, "supercharger: fastload", "block %d: progress speed: %#02x", i, fl.blocks[i].progressSpeed)
logger.Logf(fl.env, "supercharger: fastload", "block %d: page-table: %v", i, fl.blocks[i].pageTable)
}
@ -168,7 +171,7 @@ func (fl *FastLoad) Fastload(mc *cpu.CPU, ram *vcs.RAM, tmr *timer.Timer) error
fl.blockIdx = 0
}
if fl.blockIdx == startBlockIdx {
logger.Logf(logger.Allow, "supercharger: fastload", "cannot find multiload %d", m)
logger.Logf(fl.env, "supercharger: fastload", "cannot find multiload %d", m)
fl.blockIdx = 0
break // for loop
}
@ -176,7 +179,7 @@ func (fl *FastLoad) Fastload(mc *cpu.CPU, ram *vcs.RAM, tmr *timer.Timer) error
// log loading of multiload for non-zero multiload values
if m != 0 {
logger.Logf(logger.Allow, "supercharger: fastload", "loading multiload %d", fl.blocks[fl.blockIdx].multiload)
logger.Logf(fl.env, "supercharger: fastload", "loading multiload %d", fl.blocks[fl.blockIdx].multiload)
}
// copy data to RAM banks

View file

@ -20,6 +20,7 @@ import (
"math"
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
"github.com/jetsetilly/gopher2600/logger"
"github.com/jetsetilly/gopher2600/notifications"
@ -56,6 +57,7 @@ const soundloadLogTag = "supercharger: soundload"
// Compared to FastLoad this method is more 'authentic' and uses the BIOS
// correctly.
type SoundLoad struct {
env *environment.Environment
cart *Supercharger
// sound data and format information
@ -86,15 +88,16 @@ type SoundLoad struct {
}
// newSoundLoad is the preferred method of initialisation for the SoundLoad type.
func newSoundLoad(cart *Supercharger, loader cartridgeloader.Loader) (tape, error) {
func newSoundLoad(env *environment.Environment, cart *Supercharger, loader cartridgeloader.Loader) (tape, error) {
tap := &SoundLoad{
env: env,
cart: cart,
}
var err error
// get PCM data from data loaded from file
tap.pcm, err = getPCM(loader)
tap.pcm, err = getPCM(env, loader)
if err != nil {
return nil, fmt.Errorf("soundload: %w", err)
}
@ -105,13 +108,13 @@ func newSoundLoad(cart *Supercharger, loader cartridgeloader.Loader) (tape, erro
// the length of time of each sample in microseconds
timePerSample := 1000000.0 / tap.pcm.sampleRate
logger.Logf(logger.Allow, soundloadLogTag, "time per sample: %.02fus", timePerSample)
logger.Logf(tap.env, soundloadLogTag, "time per sample: %.02fus", timePerSample)
// number of samples in a cycle for it to be interpreted as a zero or a one
// values taken from "Atari 2600 Mappers" document by Kevin Horton
logger.Log(logger.Allow, soundloadLogTag, fmt.Sprintf("min/opt/max samples for zero-bit: %d/%d/%d",
logger.Log(tap.env, soundloadLogTag, fmt.Sprintf("min/opt/max samples for zero-bit: %d/%d/%d",
int(158.0/timePerSample), int(227.0/timePerSample), int(317.0/timePerSample)))
logger.Log(logger.Allow, soundloadLogTag, fmt.Sprintf("min/opt/max samples for one-bit: %d/%d/%d",
logger.Log(tap.env, soundloadLogTag, fmt.Sprintf("min/opt/max samples for one-bit: %d/%d/%d",
int(317.0/timePerSample), int(340.0/timePerSample), int(2450.0/timePerSample)))
// calculate tape regulator speed. 1190000 is the frequency at which step() is called (1.19MHz)
@ -120,7 +123,7 @@ func newSoundLoad(cart *Supercharger, loader cartridgeloader.Loader) (tape, erro
// different but it doesn't appear to have any effect on loading success so
// we won't complicate the code by allowing the regulator to change
tap.regulator = int(math.Round(1190000.0 / tap.pcm.sampleRate))
logger.Logf(logger.Allow, soundloadLogTag, "tape regulator: %d", tap.regulator)
logger.Logf(tap.env, soundloadLogTag, "tape regulator: %d", tap.regulator)
// threshold value is the average value in the PCM data
var total float32
@ -152,7 +155,7 @@ func (tap *SoundLoad) load() (uint8, error) {
tap.cart.env.Notifications.Notify(notifications.NotifySuperchargerSoundloadStarted)
tap.playing = true
tap.playDelay = 0
logger.Log(logger.Allow, soundloadLogTag, "tape playing")
logger.Log(tap.env, soundloadLogTag, "tape playing")
}
if tap.pcm.data[tap.idx] > tap.threshold {
@ -202,7 +205,7 @@ func (tap *SoundLoad) Rewind() {
// rewinding happens instantaneously
tap.cart.env.Notifications.Notify(notifications.NotifySuperchargerSoundloadRewind)
tap.idx = 0
logger.Log(logger.Allow, soundloadLogTag, "tape rewound")
logger.Log(tap.env, soundloadLogTag, "tape rewound")
tap.stepLimiter = 0
}

View file

@ -25,6 +25,7 @@ import (
"github.com/hajimehoshi/go-mp3"
"github.com/jetsetilly/gopher2600/cartridgeloader"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/logger"
)
@ -37,7 +38,7 @@ type pcmData struct {
data []float32
}
func getPCM(cl cartridgeloader.Loader) (pcmData, error) {
func getPCM(env *environment.Environment, cl cartridgeloader.Loader) (pcmData, error) {
p := pcmData{
data: make([]float32, 0),
}
@ -53,7 +54,7 @@ func getPCM(cl cartridgeloader.Loader) (pcmData, error) {
return p, fmt.Errorf("wav: not a valid wav file")
}
logger.Log(logger.Allow, soundloadLogTag, "loading from wav file")
logger.Log(env, soundloadLogTag, "loading from wav file")
// load all data at once
buf, err := dec.FullPCMBuffer()
@ -84,7 +85,7 @@ func getPCM(cl cartridgeloader.Loader) (pcmData, error) {
return p, fmt.Errorf("mp3: %w", err)
}
logger.Log(logger.Allow, soundloadLogTag, "loading from mp3 file")
logger.Log(env, soundloadLogTag, "loading from mp3 file")
err = nil
chunk := make([]byte, 4096)
@ -125,8 +126,8 @@ func getPCM(cl cartridgeloader.Loader) (pcmData, error) {
p.totalTime = float64(len(p.data)) / p.sampleRate
}
logger.Logf(logger.Allow, soundloadLogTag, "sample rate: %0.2fHz", p.sampleRate)
logger.Logf(logger.Allow, soundloadLogTag, "total time: %.02fs", p.totalTime)
logger.Logf(env, soundloadLogTag, "sample rate: %0.2fHz", p.sampleRate)
logger.Logf(env, soundloadLogTag, "total time: %.02fs", p.totalTime)
return p, nil
}

View file

@ -72,16 +72,16 @@ func NewSupercharger(env *environment.Environment, cartload cartridgeloader.Load
var err error
// load bios and activate
cart.bios, err = loadBIOS(filepath.Dir(cartload.Filename))
cart.bios, err = loadBIOS(env, filepath.Dir(cartload.Filename))
if err != nil {
return nil, fmt.Errorf("supercharger: %w", err)
}
// set up tape
if cartload.IsSoundData {
cart.state.tape, err = newSoundLoad(cart, cartload)
cart.state.tape, err = newSoundLoad(env, cart, cartload)
} else {
cart.state.tape, err = newFastLoad(cart, cartload)
cart.state.tape, err = newFastLoad(env, cart, cartload)
}
if err != nil {
return nil, fmt.Errorf("supercharger: %w", err)

View file

@ -106,7 +106,7 @@ func NewAtariVox(env *environment.Environment, port plugging.PortID, bus ports.P
}
vox.activateFestival()
logger.Logf(logger.Allow, "atarivox", "attached [%v]", vox.port)
logger.Logf(env, "atarivox", "attached [%v]", vox.port)
// attach savekey to same port
vox.SaveKey = savekey.NewSaveKey(env, port, bus)
@ -127,9 +127,9 @@ func (vox *AtariVox) activateFestival() {
if vox.env.Prefs.AtariVox.FestivalEnabled.Get().(bool) {
var err error
vox.Engine, err = atarivoxengines.NewFestival(vox.env.Prefs.AtariVox.FestivalBinary.Get().(string))
vox.Engine, err = atarivoxengines.NewFestival(vox.env)
if err != nil {
logger.Logf(logger.Allow, "atarivox", err.Error())
logger.Logf(vox.env, "atarivox", err.Error())
}
}
}
@ -294,7 +294,7 @@ func (vox *AtariVox) Step() {
if vox.SpeakJetDATA.Lo() {
vox.State = AtariVoxData
} else {
logger.Log(logger.Allow, "atarivox", "unexpected start bit of 1. should be 0")
logger.Log(vox.env, "atarivox", "unexpected start bit of 1. should be 0")
vox.State = AtariVoxStopped
}
case AtariVoxData:
@ -308,7 +308,7 @@ func (vox *AtariVox) Step() {
vox.Engine.SpeakJet(vox.Bits)
}
} else {
logger.Log(logger.Allow, "atarivox", "unexpected end bit of 0. should be 1")
logger.Log(vox.env, "atarivox", "unexpected end bit of 0. should be 1")
vox.State = AtariVoxStopped
}
}

View file

@ -21,6 +21,7 @@ import (
"os/exec"
"strings"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/logger"
)
@ -34,15 +35,18 @@ const (
)
type phonemes struct {
env *environment.Environment
strings.Builder
}
func (p *phonemes) WriteString(s string) (int, error) {
logger.Logf(logger.Allow, "festival", "phoneme: %s", s)
logger.Logf(p.env, "festival", "phoneme: %s", s)
return p.Builder.WriteString(s)
}
type festival struct {
env *environment.Environment
stdin io.WriteCloser
stdout io.ReadCloser
@ -61,13 +65,18 @@ type festival struct {
// NewFestival creats a new festival instance and starts a new festival process
// which we'll communicate with via a stdin pipe.
func NewFestival(executablePath string) (AtariVoxEngine, error) {
func NewFestival(env *environment.Environment) (AtariVoxEngine, error) {
fest := &festival{
env: env,
phonemes: phonemes{
env: env,
},
quit: make(chan bool, 1),
say: make(chan string, 1),
cmd: make(chan string, 1),
}
executablePath := env.Prefs.AtariVox.FestivalBinary.Get().(string)
cmd := exec.Command(executablePath)
var err error
@ -88,19 +97,18 @@ func NewFestival(executablePath string) (AtariVoxEngine, error) {
}
go func() {
for {
select {
case <-fest.quit:
err = cmd.Process.Kill()
if err != nil {
logger.Logf(logger.Allow, "festival", err.Error())
logger.Logf(fest.env, "festival", err.Error())
}
_ = cmd.Wait()
return
case text := <-fest.say:
logger.Logf(logger.Allow, "festival", "say: %s", text)
logger.Logf(fest.env, "festival", "say: %s", text)
sayphones := fmt.Sprintf("(SayPhones '(%s))", text)
fest.stdin.Write([]byte(sayphones))
@ -145,68 +153,68 @@ func (fest *festival) SpeakJet(b uint8) {
return
case speed:
fest.speed = b
logger.Logf(logger.Allow, "festival", "speed: %d", fest.speed)
logger.Logf(fest.env, "festival", "speed: %d", fest.speed)
fest.cmd <- fmt.Sprintf("(set! FP_duration %d)", fest.speed)
fest.nextSpeakJetByte = none
return
case pitch:
fest.pitch = b
logger.Logf(logger.Allow, "festival", "pitch: %d", fest.pitch)
logger.Logf(fest.env, "festival", "pitch: %d", fest.pitch)
fest.cmd <- fmt.Sprintf("(set! FP_F0 %d)", fest.pitch)
fest.nextSpeakJetByte = none
return
}
if b >= 215 && b <= 254 {
logger.Logf(logger.Allow, "festival", "sound effect: %d", b)
logger.Logf(fest.env, "festival", "sound effect: %d", b)
return
}
switch b {
default:
logger.Logf(logger.Allow, "festival", "unsupported byte (%d)", b)
logger.Logf(fest.env, "festival", "unsupported byte (%d)", b)
return
case 31: // Reset
logger.Logf(logger.Allow, "festival", "reset")
logger.Logf(fest.env, "festival", "reset")
fest.reset()
return
case 0: // pause 0ms
return
case 1: // pause 100ms
logger.Logf(logger.Allow, "festival", "pause: 100ms: not implemented")
logger.Logf(fest.env, "festival", "pause: 100ms: not implemented")
return
case 2: // pause 200ms
logger.Logf(logger.Allow, "festival", "pause: 200ms: not implemented")
logger.Logf(fest.env, "festival", "pause: 200ms: not implemented")
return
case 3: // pause 700ms
logger.Logf(logger.Allow, "festival", "pause: 700ms: not implemented")
logger.Logf(fest.env, "festival", "pause: 700ms: not implemented")
return
case 4: // pause 30ms
logger.Logf(logger.Allow, "festival", "pause: 30ms: not implemented")
logger.Logf(fest.env, "festival", "pause: 30ms: not implemented")
return
case 5: // pause 60ms
logger.Logf(logger.Allow, "festival", "pause: 60ms: not implemented")
logger.Logf(fest.env, "festival", "pause: 60ms: not implemented")
return
case 6: // pause 90ms
logger.Logf(logger.Allow, "festival", "pause: 90ms: not implemented")
logger.Logf(fest.env, "festival", "pause: 90ms: not implemented")
return
case 7: // Fast
logger.Logf(logger.Allow, "festival", "fast: not implemented")
logger.Logf(fest.env, "festival", "fast: not implemented")
return
case 8: // Slow
logger.Logf(logger.Allow, "festival", "slow: not implemented")
logger.Logf(fest.env, "festival", "slow: not implemented")
return
case 14: // Stress
logger.Logf(logger.Allow, "festival", "stress: not implemented")
logger.Logf(fest.env, "festival", "stress: not implemented")
return
case 15: // Relax
logger.Logf(logger.Allow, "festival", "relax: not implemented")
logger.Logf(fest.env, "festival", "relax: not implemented")
return
case 20: // volume
logger.Logf(logger.Allow, "festival", "volume: not implemented")
logger.Logf(fest.env, "festival", "volume: not implemented")
fest.nextSpeakJetByte = unsupported
return
case 21: // speed
@ -218,30 +226,30 @@ func (fest *festival) SpeakJet(b uint8) {
fest.nextSpeakJetByte = pitch
return
case 23: // bend
logger.Logf(logger.Allow, "festival", "bend: not implemented")
logger.Logf(fest.env, "festival", "bend: not implemented")
return
case 24: // PortCtr
logger.Logf(logger.Allow, "festival", "port ctr: not implemented")
logger.Logf(fest.env, "festival", "port ctr: not implemented")
fest.nextSpeakJetByte = unsupported
return
case 25: // Port
logger.Logf(logger.Allow, "festival", "port: not implemented")
logger.Logf(fest.env, "festival", "port: not implemented")
fest.nextSpeakJetByte = unsupported
return
case 26: // Repeat
logger.Logf(logger.Allow, "festival", "repeat: not implemented")
logger.Logf(fest.env, "festival", "repeat: not implemented")
fest.nextSpeakJetByte = unsupported
return
case 28: // Call Phrase
logger.Logf(logger.Allow, "festival", "call phrase: not implemented")
logger.Logf(fest.env, "festival", "call phrase: not implemented")
fest.nextSpeakJetByte = unsupported
return
case 29: // Goto Phrase
logger.Logf(logger.Allow, "festival", "goto phrase: not implemented")
logger.Logf(fest.env, "festival", "goto phrase: not implemented")
fest.nextSpeakJetByte = unsupported
return
case 30: // Delay
logger.Logf(logger.Allow, "festival", "delay: not implemented")
logger.Logf(fest.env, "festival", "delay: not implemented")
fest.nextSpeakJetByte = unsupported
return

View file

@ -18,6 +18,7 @@ package savekey
import (
"os"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/logger"
"github.com/jetsetilly/gopher2600/resources"
)
@ -28,6 +29,8 @@ const eepromSize = 65536
// EEPROM represents the non-volatile memory in the SaveKey peripheral.
type EEPROM struct {
env *environment.Environment
// the next address an i2c read/write operation will access
Address uint16
@ -41,8 +44,9 @@ type EEPROM struct {
// NewEeprom is the preferred metho of initialisation for the EEPROM type. This
// function will initialise the memory and Read() any existing data from disk.
func newEeprom() *EEPROM {
func newEeprom(env *environment.Environment) *EEPROM {
ee := &EEPROM{
env: env,
Data: make([]uint8, eepromSize),
DiskData: make([]uint8, eepromSize),
}
@ -71,13 +75,13 @@ func (ee *EEPROM) snapshot() *EEPROM {
func (ee *EEPROM) Read() {
fn, err := resources.JoinPath(saveKeyPath)
if err != nil {
logger.Logf(logger.Allow, "savekey", "could not load eeprom file (%s)", err)
logger.Logf(ee.env, "savekey", "could not load eeprom file (%s)", err)
return
}
f, err := os.Open(fn)
if err != nil {
logger.Logf(logger.Allow, "savekey", "could not load eeprom file (%s)", err)
logger.Logf(ee.env, "savekey", "could not load eeprom file (%s)", err)
return
}
defer f.Close()
@ -86,57 +90,57 @@ func (ee *EEPROM) Read() {
// windows version (when running under wine) does not handle that
fs, err := os.Stat(fn)
if err != nil {
logger.Logf(logger.Allow, "savekey", "could not load eeprom file (%s)", err)
logger.Logf(ee.env, "savekey", "could not load eeprom file (%s)", err)
return
}
if fs.Size() != int64(len(ee.Data)) {
logger.Logf(logger.Allow, "savekey", "eeprom file is of incorrect length. %d should be 65536 ", fs.Size())
logger.Logf(ee.env, "savekey", "eeprom file is of incorrect length. %d should be 65536 ", fs.Size())
}
_, err = f.Read(ee.Data)
if err != nil {
logger.Logf(logger.Allow, "savekey", "could not load eeprom file (%s)", err)
logger.Logf(ee.env, "savekey", "could not load eeprom file (%s)", err)
return
}
// copy of data read from disk
copy(ee.DiskData, ee.Data)
logger.Logf(logger.Allow, "savekey", "eeprom file loaded from %s", fn)
logger.Logf(ee.env, "savekey", "eeprom file loaded from %s", fn)
}
// Write EEPROM data to disk.
func (ee *EEPROM) Write() {
fn, err := resources.JoinPath(saveKeyPath)
if err != nil {
logger.Logf(logger.Allow, "savekey", "could not write eeprom file (%s)", err)
logger.Logf(ee.env, "savekey", "could not write eeprom file (%s)", err)
return
}
f, err := os.Create(fn)
if err != nil {
logger.Logf(logger.Allow, "savekey", "could not write eeprom file (%s)", err)
logger.Logf(ee.env, "savekey", "could not write eeprom file (%s)", err)
return
}
defer func() {
err := f.Close()
if err != nil {
logger.Logf(logger.Allow, "savekey", "could not close eeprom file (%s)", err)
logger.Logf(ee.env, "savekey", "could not close eeprom file (%s)", err)
}
}()
n, err := f.Write(ee.Data)
if err != nil {
logger.Logf(logger.Allow, "savekey", "could not write eeprom file (%s)", err)
logger.Logf(ee.env, "savekey", "could not write eeprom file (%s)", err)
return
}
if n != len(ee.Data) {
logger.Logf(logger.Allow, "savekey", "eeprom file has not been truncated during write. %d should be 65536", n)
logger.Logf(ee.env, "savekey", "eeprom file has not been truncated during write. %d should be 65536", n)
return
}
logger.Logf(logger.Allow, "savekey", "eeprom file saved to %s", fn)
logger.Logf(ee.env, "savekey", "eeprom file saved to %s", fn)
// copy of data that's just bee written to disk
copy(ee.DiskData, ee.Data)

View file

@ -52,6 +52,8 @@ const (
// SaveKey represents the SaveKey peripheral. It implements the Peripheral
// interface.
type SaveKey struct {
env *environment.Environment
port plugging.PortID
bus ports.PeripheralBus
@ -96,16 +98,17 @@ func NewSaveKey(env *environment.Environment, port plugging.PortID, bus ports.Pe
}
sk := &SaveKey{
env: env,
port: port,
bus: bus,
SDA: i2c.NewTrace(),
SCL: i2c.NewTrace(),
State: SaveKeyStopped,
EEPROM: newEeprom(),
EEPROM: newEeprom(env),
}
sk.bus.WriteSWCHx(sk.port, 0xf0)
logger.Logf(logger.Allow, "savekey", "attached [%v]", sk.port)
logger.Logf(sk.env, "savekey", "attached [%v]", sk.port)
return sk
}
@ -254,7 +257,7 @@ func (sk *SaveKey) Step() {
// check for stop signal before anything else
if sk.State != SaveKeyStopped && sk.SCL.Hi() && sk.SDA.Rising() {
logger.Log(logger.Allow, "savekey", "stopped message")
logger.Log(sk.env, "savekey", "stopped message")
sk.State = SaveKeyStopped
sk.EEPROM.Write()
return
@ -281,7 +284,7 @@ func (sk *SaveKey) Step() {
switch sk.State {
case SaveKeyStopped:
if sk.SDA.Lo() {
logger.Log(logger.Allow, "savekey", "starting message")
logger.Log(sk.env, "savekey", "starting message")
sk.resetBits()
sk.State = SaveKeyStarting
}
@ -290,18 +293,18 @@ func (sk *SaveKey) Step() {
if sk.recvBit(sk.SDA.Falling()) {
switch sk.Bits {
case readSig:
logger.Log(logger.Allow, "savekey", "reading message")
logger.Log(sk.env, "savekey", "reading message")
sk.resetBits()
sk.State = SaveKeyData
sk.Dir = Reading
sk.Ack = true
case writeSig:
logger.Log(logger.Allow, "savekey", "writing message")
logger.Log(sk.env, "savekey", "writing message")
sk.State = SaveKeyAddressHi
sk.Dir = Writing
sk.Ack = true
default:
logger.Log(logger.Allow, "savekey", "unrecognised message")
logger.Log(sk.env, "savekey", "unrecognised message")
sk.State = SaveKeyStopped
}
}
@ -321,9 +324,9 @@ func (sk *SaveKey) Step() {
switch sk.Dir {
case Reading:
logger.Logf(logger.Allow, "savekey", "reading from address %#04x", sk.EEPROM.Address)
logger.Logf(sk.env, "savekey", "reading from address %#04x", sk.EEPROM.Address)
case Writing:
logger.Logf(logger.Allow, "savekey", "writing to address %#04x", sk.EEPROM.Address)
logger.Logf(sk.env, "savekey", "writing to address %#04x", sk.EEPROM.Address)
}
}
@ -340,9 +343,9 @@ func (sk *SaveKey) Step() {
if end {
if unicode.IsPrint(rune(sk.Bits)) {
logger.Logf(logger.Allow, "savekey", "read byte %#02x [%c]", sk.Bits, sk.Bits)
logger.Logf(sk.env, "savekey", "read byte %#02x [%c]", sk.Bits, sk.Bits)
} else {
logger.Logf(logger.Allow, "savekey", "read byte %#02x", sk.Bits)
logger.Logf(sk.env, "savekey", "read byte %#02x", sk.Bits)
}
sk.Ack = true
}
@ -350,9 +353,9 @@ func (sk *SaveKey) Step() {
case Writing:
if sk.recvBit(sk.SDA.Falling()) {
if unicode.IsPrint(rune(sk.Bits)) {
logger.Logf(logger.Allow, "savekey", "written byte %#02x [%c]", sk.Bits, sk.Bits)
logger.Logf(sk.env, "savekey", "written byte %#02x [%c]", sk.Bits, sk.Bits)
} else {
logger.Logf(logger.Allow, "savekey", "written byte %#02x", sk.Bits)
logger.Logf(sk.env, "savekey", "written byte %#02x", sk.Bits)
}
sk.EEPROM.put(sk.Bits)
sk.Ack = true

View file

@ -90,6 +90,7 @@ func newPlusROMpreferences() (*PlusROMPreferences, error) {
}
if !p.validateID() {
// using logger.Allow because we don't mind a non-main emulation creating this log entry.
logger.Log(logger.Allow, "plusrom preferences", "existing ID invalid. generating new ID and saving")
err = p.ID.Set(p.generateID())

View file

@ -73,7 +73,7 @@ func (riot *RIOT) Step(reg chipbus.ChangedRegister) {
if update {
update = riot.Ports.Update(reg)
if update {
logger.Logf(logger.Allow, "riot", "memory altered to no affect (%04x=%02x)", reg.Address, reg.Value)
logger.Logf(riot.env, "riot", "memory altered to no affect (%04x=%02x)", reg.Address, reg.Value)
}
}

View file

@ -20,6 +20,7 @@ import (
"strings"
"github.com/jetsetilly/gopher2600/debugger/govern"
"github.com/jetsetilly/gopher2600/environment"
"github.com/jetsetilly/gopher2600/hardware/television/coords"
"github.com/jetsetilly/gopher2600/hardware/television/signal"
"github.com/jetsetilly/gopher2600/hardware/television/specification"
@ -124,6 +125,8 @@ func (s *State) GetCoords() coords.TelevisionCoords {
// Television is a Television implementation of the Television interface. In all
// honesty, it's most likely the only implementation required.
type Television struct {
env *environment.Environment
// vcs will be nil unless AttachVCS() has been called
vcs VCSReturnChannel
@ -288,7 +291,8 @@ func (tv *Television) Plumb(vcs VCSReturnChannel, state *State) {
}
// AttachVCS attaches an implementation of the VCSReturnChannel.
func (tv *Television) AttachVCS(vcs VCSReturnChannel) {
func (tv *Television) AttachVCS(env *environment.Environment, vcs VCSReturnChannel) {
tv.env = env
tv.vcs = vcs
// notify the newly attached console of the current TV spec
@ -472,7 +476,7 @@ func (tv *Television) Signal(sig signal.SignalAttributes) {
if !tv.state.vsyncActive {
err := tv.newFrame(false)
if err != nil {
logger.Log(logger.Allow, "TV", err.Error())
logger.Log(tv.env, "TV", err.Error())
}
} else {
tv.state.scanline = specification.AbsoluteMaxScanlines - 1
@ -481,7 +485,7 @@ func (tv *Television) Signal(sig signal.SignalAttributes) {
// if we're not at end of screen then indicate new scanline
err := tv.newScanline()
if err != nil {
logger.Log(logger.Allow, "TV", err.Error())
logger.Log(tv.env, "TV", err.Error())
}
}
}
@ -529,7 +533,7 @@ func (tv *Television) Signal(sig signal.SignalAttributes) {
} else {
err := tv.newFrame(true)
if err != nil {
logger.Log(logger.Allow, "TV", err.Error())
logger.Log(tv.env, "TV", err.Error())
}
}
}
@ -585,7 +589,7 @@ func (tv *Television) Signal(sig signal.SignalAttributes) {
if tv.currentSignalIdx >= len(tv.signals) {
err := tv.renderSignals()
if err != nil {
logger.Log(logger.Allow, "TV", err.Error())
logger.Log(tv.env, "TV", err.Error())
}
}
}

View file

@ -601,7 +601,7 @@ func (tia *TIA) Step(reg chipbus.ChangedRegister, ct int) {
if tia.env.Prefs.Revision.Live.LateCOLUPF.Load().(bool) {
update = tia.Video.UpdatePlayfieldColor(reg)
if update {
logger.Logf(logger.Allow, "tia", "memory altered to no affect (%04x=%02x)", reg.Address, reg.Value)
logger.Logf(tia.env, "tia", "memory altered to no affect (%04x=%02x)", reg.Address, reg.Value)
}
}
}

View file

@ -120,7 +120,7 @@ func NewVCS(tv *television.Television, notify notifications.Notify, prefs *prefe
return nil, err
}
vcs.TV.AttachVCS(vcs)
vcs.TV.AttachVCS(env, vcs)
return vcs, nil
}
@ -245,25 +245,25 @@ func (vcs *VCS) SetClockSpeed(spec specification.Spec) {
case specification.SpecNTSC.ID:
if vcs.Clock != ntscClock {
vcs.Clock = ntscClock
logger.Log(logger.Allow, "vcs", "switching to NTSC clock")
logger.Log(vcs.Env, "vcs", "switching to NTSC clock")
}
case specification.SpecPAL.ID:
if vcs.Clock != palClock {
vcs.Clock = palClock
logger.Log(logger.Allow, "vcs", "switching to PAL clock")
logger.Log(vcs.Env, "vcs", "switching to PAL clock")
}
case specification.SpecPALM.ID:
if vcs.Clock != palMClock {
vcs.Clock = palMClock
logger.Log(logger.Allow, "vcs", "switching to PAL-M clock")
logger.Log(vcs.Env, "vcs", "switching to PAL-M clock")
}
case specification.SpecSECAM.ID:
if vcs.Clock != secamClock {
vcs.Clock = secamClock
logger.Log(logger.Allow, "vcs", "switching to SECAM clock")
logger.Log(vcs.Env, "vcs", "switching to SECAM clock")
}
default:
logger.Logf(logger.Allow, "vcs", "cannot set clock for unknown TV specification (%s)", spec.ID)
logger.Logf(vcs.Env, "vcs", "cannot set clock for unknown TV specification (%s)", spec.ID)
}
}

View file

@ -25,8 +25,14 @@ type Permission interface {
AllowLogging() bool
}
type allow struct{}
func (_ allow) AllowLogging() bool {
return true
}
// Allow indicates that the logging request should be allowed
var Allow Permission = nil
var Allow Permission = allow{}
// only allowing one central log for the entire application. there's no need to
// allow more than one log.