Trace Apple Pascal BIOS calls
This commit is contained in:
parent
c3c1a262fc
commit
902437419e
|
@ -54,6 +54,12 @@ Portable emulator of an Apple II+ or //e. Written in Go.
|
||||||
- RGB for Super High Resolution and RGB card
|
- RGB for Super High Resolution and RGB card
|
||||||
- ANSI Console, avoiding the SDL2 dependency
|
- ANSI Console, avoiding the SDL2 dependency
|
||||||
- Debug mode: shows four panels with actual screen, page1, page2 and extra info dependant of the video mode
|
- Debug mode: shows four panels with actual screen, page1, page2 and extra info dependant of the video mode
|
||||||
|
- Tracing capabilities:
|
||||||
|
- CPU execution disassembled
|
||||||
|
- Softswitch reads and writes
|
||||||
|
- ProDOS MLI calls
|
||||||
|
- Apple Pascal BIOS calls
|
||||||
|
- Smartport commands
|
||||||
- Other features:
|
- Other features:
|
||||||
- Sound
|
- Sound
|
||||||
- Joystick support. Up to two joysticks or four paddles
|
- Joystick support. Up to two joysticks or four paddles
|
||||||
|
@ -62,7 +68,6 @@ Portable emulator of an Apple II+ or //e. Written in Go.
|
||||||
- Fast disk mode to set max speed while using the disks
|
- Fast disk mode to set max speed while using the disks
|
||||||
- Single file executable with embedded ROMs and DOS 3.3
|
- Single file executable with embedded ROMs and DOS 3.3
|
||||||
- Pause (thanks a2geek)
|
- Pause (thanks a2geek)
|
||||||
- ProDOS MLI calls tracing
|
|
||||||
- Passes the [A2AUDIT 1.06](https://github.com/zellyn/a2audit) tests as II+, //e, and //e Enhanced.
|
- Passes the [A2AUDIT 1.06](https://github.com/zellyn/a2audit) tests as II+, //e, and //e Enhanced.
|
||||||
|
|
||||||
By default the following configuration is launched:
|
By default the following configuration is launched:
|
||||||
|
@ -226,6 +231,8 @@ Only valid on SDL mode
|
||||||
dump to the console the hd/smartport commands
|
dump to the console the hd/smartport commands
|
||||||
-traceMLI
|
-traceMLI
|
||||||
dump to the console the calls to ProDOS machine language interface calls to $BF00
|
dump to the console the calls to ProDOS machine language interface calls to $BF00
|
||||||
|
-tracePascal
|
||||||
|
dump to the console the calls to the Apple Pascal BIOS
|
||||||
-traceSS
|
-traceSS
|
||||||
dump to the console the sofswitches calls
|
dump to the console the sofswitches calls
|
||||||
-traceSSReg
|
-traceSSReg
|
||||||
|
|
24
apple2.go
24
apple2.go
|
@ -24,10 +24,14 @@ type Apple2 struct {
|
||||||
profile bool
|
profile bool
|
||||||
showSpeed bool
|
showSpeed bool
|
||||||
paused bool
|
paused bool
|
||||||
traceMLI *traceProDOS
|
tracers []executionTracer
|
||||||
forceCaps bool
|
forceCaps bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type executionTracer interface {
|
||||||
|
inspect()
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// CPUClockMhz is the actual Apple II clock speed
|
// CPUClockMhz is the actual Apple II clock speed
|
||||||
CPUClockMhz = 14.318 / 14
|
CPUClockMhz = 14.318 / 14
|
||||||
|
@ -211,8 +215,10 @@ func (a *Apple2) releaseFastMode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Apple2) executionTrace() {
|
func (a *Apple2) executionTrace() {
|
||||||
if a.traceMLI != nil {
|
if a.tracers != nil {
|
||||||
a.traceMLI.inspect()
|
for _, v := range a.tracers {
|
||||||
|
v.inspect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,15 +229,17 @@ func (a *Apple2) dumpDebugInfo() {
|
||||||
0x37: "CSWH",
|
0x37: "CSWH",
|
||||||
0x38: "KSWL",
|
0x38: "KSWL",
|
||||||
0x39: "KSWH",
|
0x39: "KSWH",
|
||||||
|
0xe2: "ACJVAFLDL", // Apple Pascal
|
||||||
|
0xe3: "ACJVAFLDH", // Apple Pascal
|
||||||
|
0xec: "JVBFOLDL", // Apple Pascal
|
||||||
|
0xed: "JVBFOLDH", // Apple Pascal
|
||||||
|
0xee: "JVAFOLDL", // Apple Pascal
|
||||||
|
0xef: "JVAFOLDH", // Apple Pascal
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("Page zero values:\n")
|
fmt.Printf("Page zero values:\n")
|
||||||
for _, k := range []int{0x36, 0x37, 0x38, 0x39} {
|
for _, k := range []int{0x36, 0x37, 0x38, 0x39, 0xe2, 0xe3, 0xec, 0xed, 0xee, 0xef} {
|
||||||
d := a.mmu.physicalMainRAM.data[k]
|
d := a.mmu.physicalMainRAM.data[k]
|
||||||
fmt.Printf(" %v(0x%x): 0x%02x\n", pageZeroSymbols[k], k, d)
|
fmt.Printf(" %v(0x%x): 0x%02x\n", pageZeroSymbols[k], k, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.traceMLI != nil {
|
|
||||||
a.traceMLI.dumpDevices()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,9 @@ func newApple2() *Apple2 {
|
||||||
return &a
|
return &a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Apple2) setup(clockMhz float64, fastMode bool, traceMLI bool) {
|
func (a *Apple2) setup(clockMhz float64, fastMode bool) {
|
||||||
a.commandChannel = make(chan int, 100)
|
a.commandChannel = make(chan int, 100)
|
||||||
a.fastMode = fastMode
|
a.fastMode = fastMode
|
||||||
if traceMLI {
|
|
||||||
a.traceMLI = newTraceProDOS(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
if clockMhz <= 0 {
|
if clockMhz <= 0 {
|
||||||
// Full speed
|
// Full speed
|
||||||
|
@ -55,6 +52,14 @@ func setApple2eEnhanced(a *Apple2) {
|
||||||
addApple2ESoftSwitches(a.io)
|
addApple2ESoftSwitches(a.io)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Apple2) addTracer(tracer executionTracer) {
|
||||||
|
if a.tracers == nil {
|
||||||
|
a.tracers = make([]executionTracer, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.tracers = append(a.tracers, tracer)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Apple2) insertCard(c Card, slot int) {
|
func (a *Apple2) insertCard(c Card, slot int) {
|
||||||
c.assign(a, slot)
|
c.assign(a, slot)
|
||||||
a.cards[slot] = c
|
a.cards[slot] = c
|
||||||
|
|
|
@ -130,6 +130,10 @@ func MainApple() *Apple2 {
|
||||||
"traceMLI",
|
"traceMLI",
|
||||||
false,
|
false,
|
||||||
"dump to the console the calls to ProDOS machine language interface calls to $BF00")
|
"dump to the console the calls to ProDOS machine language interface calls to $BF00")
|
||||||
|
tracePascal := flag.Bool(
|
||||||
|
"tracePascal",
|
||||||
|
false,
|
||||||
|
"dump to the console the calls to the Apple Pascal BIOS")
|
||||||
forceCaps := flag.Bool(
|
forceCaps := flag.Bool(
|
||||||
"forceCaps",
|
"forceCaps",
|
||||||
false,
|
false,
|
||||||
|
@ -150,12 +154,18 @@ func MainApple() *Apple2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
a := newApple2()
|
a := newApple2()
|
||||||
a.setup(*cpuClock, *fastDisk, *traceMLI)
|
a.setup(*cpuClock, *fastDisk)
|
||||||
a.io.setTrace(*traceSS)
|
a.io.setTrace(*traceSS)
|
||||||
a.io.setTraceRegistrations(*traceSSReg)
|
a.io.setTraceRegistrations(*traceSSReg)
|
||||||
a.io.setPanicNotImplemented(*panicSS)
|
a.io.setPanicNotImplemented(*panicSS)
|
||||||
a.setProfiling(*profile)
|
a.setProfiling(*profile)
|
||||||
a.SetForceCaps(*forceCaps)
|
a.SetForceCaps(*forceCaps)
|
||||||
|
if *traceMLI {
|
||||||
|
a.addTracer(newTraceProDOS(a))
|
||||||
|
}
|
||||||
|
if *tracePascal {
|
||||||
|
a.addTracer(newTracePascal(a))
|
||||||
|
}
|
||||||
|
|
||||||
var charGenMap charColumnMap
|
var charGenMap charColumnMap
|
||||||
initialCharGenPage := 0
|
initialCharGenPage := 0
|
||||||
|
|
|
@ -87,7 +87,11 @@ func (r *registers) updateFlagZN(t uint8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r registers) String() string {
|
func (r registers) String() string {
|
||||||
ch := (r.getA() & 0x3F) + 0x40
|
//ch := (r.getA() & 0x3F) + 0x40
|
||||||
|
ch := (r.getA() & 0x7F)
|
||||||
|
if ch < 0x20 {
|
||||||
|
ch += 0x40
|
||||||
|
}
|
||||||
return fmt.Sprintf("A: %#02x(%v), X: %#02x, Y: %#02x, SP: %#02x, PC: %#04x, P: %#02x, (NV-BDIZC): %08b",
|
return fmt.Sprintf("A: %#02x(%v), X: %#02x, Y: %#02x, SP: %#02x, PC: %#04x, P: %#02x, (NV-BDIZC): %08b",
|
||||||
r.getA(), string(ch), r.getX(), r.getY(), r.getSP(), r.getPC(), r.getP(), r.getP())
|
r.getA(), string(ch), r.getX(), r.getY(), r.getSP(), r.getPC(), r.getP(), r.getP())
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ type memoryManager struct {
|
||||||
// Configuration switches, Language cards
|
// Configuration switches, Language cards
|
||||||
lcSelectedBlock uint8 // Language card block selected. Usually, allways 0. But Saturn has 8
|
lcSelectedBlock uint8 // Language card block selected. Usually, allways 0. But Saturn has 8
|
||||||
lcActiveRead bool // Upper RAM active for read
|
lcActiveRead bool // Upper RAM active for read
|
||||||
lcActiveWrite bool // Upper RAM active for read
|
lcActiveWrite bool // Upper RAM active for write
|
||||||
lcAltBank bool // Alternate
|
lcAltBank bool // Alternate
|
||||||
|
|
||||||
// Configuration switches, Apple //e
|
// Configuration switches, Apple //e
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
package izapple2
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type tracePascal struct {
|
||||||
|
a *Apple2
|
||||||
|
skipConsole bool
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
pascalJvabfoldL uint16 = 0x00ec // Points to the BIOS entry points
|
||||||
|
pascalJvabfoldH uint16 = 0x00ed // Points to the BIOS entry points
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTracePascal(a *Apple2) *tracePascal {
|
||||||
|
var t tracePascal
|
||||||
|
t.a = a
|
||||||
|
t.skipConsole = true
|
||||||
|
return &t
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
See:
|
||||||
|
https://archive.org/details/Hyde_P-Source-A_Guide_to_the_APPLE_Pascal_System_1983/page/n415/mode/1up?view=theater
|
||||||
|
https://archive.org/details/Apple_II_Pascal_1.2_Device_and_Interrupt_Support_Tools_Manual
|
||||||
|
|
||||||
|
Experimental. Not sure the paramters for DREAD and DWRITE are correct.
|
||||||
|
*/
|
||||||
|
func (t *tracePascal) inspect() {
|
||||||
|
bios := uint16(t.a.mmu.physicalMainRAM.peek(pascalJvabfoldL)) +
|
||||||
|
uint16(t.a.mmu.physicalMainRAM.peek(pascalJvabfoldH))<<8
|
||||||
|
pc, _ := t.a.cpu.GetPCAndSP()
|
||||||
|
if pc >= bios && pc < bios+0x5a {
|
||||||
|
offset := uint8(pc - bios)
|
||||||
|
|
||||||
|
if t.skipConsole && offset <= 0x03 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, regA := t.a.cpu.GetCarryAndAcc()
|
||||||
|
regAText := string(regA)
|
||||||
|
if regA < 0x20 {
|
||||||
|
regAText = "^" + string(regA+0x40)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Pascal BIOS call $%02x from $%04x ", offset, t.param(1))
|
||||||
|
switch offset {
|
||||||
|
case 0:
|
||||||
|
fmt.Printf("CREAD()")
|
||||||
|
case 3:
|
||||||
|
fmt.Printf("CWRITE('%s'[%v])", regAText, regA)
|
||||||
|
case 6:
|
||||||
|
fmt.Printf("CINIT(BREAK=[$%04x], SYSCOM=[$%04x])",
|
||||||
|
t.param(3), t.param(5))
|
||||||
|
case 9:
|
||||||
|
fmt.Printf("PWRITE('%s'[%v])", regAText, regA)
|
||||||
|
case 12:
|
||||||
|
fmt.Printf("PINIT()")
|
||||||
|
case 15:
|
||||||
|
fmt.Printf("DWRITE(UNIT=%v, BLOCK=%v, LEN=%v, DATA=[$%04x], DRIVE=%v, CONTROL=$%04x)",
|
||||||
|
regA, t.param(3), t.param(5), t.param(7), t.param(9), t.param(11))
|
||||||
|
case 18:
|
||||||
|
fmt.Printf("DREAD(UNIT=%v, BLOCK=%v, LEN=%v, DATA=[$%04x], DRIVE=%v, CONTROL=$%04x)",
|
||||||
|
regA, t.param(3), t.param(5), t.param(7), t.param(9), t.param(11))
|
||||||
|
case 21:
|
||||||
|
fmt.Printf("DINIT(DRIVE=%v)", regA)
|
||||||
|
case 24:
|
||||||
|
fmt.Printf("RREAD()")
|
||||||
|
case 27:
|
||||||
|
fmt.Printf("RWRITE('%s'[%v])", regAText, regA)
|
||||||
|
case 30:
|
||||||
|
fmt.Printf("RINIT()")
|
||||||
|
case 33:
|
||||||
|
fmt.Printf("GWRITE()")
|
||||||
|
case 36:
|
||||||
|
fmt.Printf("GRINIT()")
|
||||||
|
case 39:
|
||||||
|
fmt.Printf("PREAD()")
|
||||||
|
case 42:
|
||||||
|
fmt.Printf("CSTAT()")
|
||||||
|
case 45:
|
||||||
|
fmt.Printf("PSTAT()")
|
||||||
|
case 48:
|
||||||
|
fmt.Printf("DSTAT()")
|
||||||
|
case 51:
|
||||||
|
fmt.Printf("RSTAT()")
|
||||||
|
case 54:
|
||||||
|
fmt.Printf("CONCK()")
|
||||||
|
case 57:
|
||||||
|
fmt.Printf("UDRWI()")
|
||||||
|
case 60:
|
||||||
|
fmt.Printf("PSUBDRV()")
|
||||||
|
|
||||||
|
default:
|
||||||
|
fmt.Printf("<unknown>")
|
||||||
|
}
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
See http://www.bitsavers.org/pdf/softech/softechPascalIV_intArch1981.pdf
|
||||||
|
page 106
|
||||||
|
*/
|
||||||
|
func (t *tracePascal) inspectPerArchitectureGuide() {
|
||||||
|
bios := uint16(t.a.mmu.physicalMainRAM.peek(pascalJvabfoldL)) +
|
||||||
|
uint16(t.a.mmu.physicalMainRAM.peek(pascalJvabfoldH))<<8
|
||||||
|
pc, _ := t.a.cpu.GetPCAndSP()
|
||||||
|
if pc >= bios && pc < bios+0x5a {
|
||||||
|
offset := uint8(pc - bios)
|
||||||
|
|
||||||
|
if t.skipConsole && offset <= 0x03 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, regA := t.a.cpu.GetCarryAndAcc()
|
||||||
|
regAText := string(regA)
|
||||||
|
if regA < 0x20 {
|
||||||
|
regAText = "^" + string(regA+0x40)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Pascal BIOS call $%02x from $%04x ", offset, t.param(1))
|
||||||
|
switch offset {
|
||||||
|
// Console
|
||||||
|
case 0x00:
|
||||||
|
fmt.Printf("CONSOLEREAD()")
|
||||||
|
case 0x03:
|
||||||
|
fmt.Printf("CONSOLEWRITE('%s'[%v])", regAText, regA)
|
||||||
|
case 0x06:
|
||||||
|
fmt.Printf("CONSOLECTRL(BREAK=[%04x], SYSCOM=[%04x])",
|
||||||
|
t.param(3), t.param(5))
|
||||||
|
case 0x09:
|
||||||
|
fmt.Printf("CONSOLESTAT(STATREC=[%04x], CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5))
|
||||||
|
|
||||||
|
// Printer
|
||||||
|
case 0x0c:
|
||||||
|
fmt.Printf("PRINTERREAD()")
|
||||||
|
case 0x0f:
|
||||||
|
fmt.Printf("PRINTERWRITE('%s'[%v])", regAText, regA)
|
||||||
|
case 0x12:
|
||||||
|
fmt.Printf("PRINTERCTRL()")
|
||||||
|
case 0x15:
|
||||||
|
fmt.Printf("PRINTERSTAT(STATREC=[%04x], CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5))
|
||||||
|
|
||||||
|
// Disk
|
||||||
|
case 0x18:
|
||||||
|
fmt.Printf("DISKREAD(BLOCK=%04x, LEN=%04x, DATA=[%04x], DRIVE=%v, CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5), t.param(7), t.param(9), t.param(11))
|
||||||
|
case 0x1b:
|
||||||
|
fmt.Printf("DISKWRITE(BLOCK=%04x, LEN=%04x, DATA=[%04x], DRIVE=%v, CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5), t.param(7), t.param(9), t.param(11))
|
||||||
|
case 0x1e:
|
||||||
|
fmt.Printf("DISKCTRL(DRIVE=%v)", regA)
|
||||||
|
case 0x21:
|
||||||
|
fmt.Printf("DISKSTAT(DRIVE=%v, STATREC=[%04x], CONTROL=%04x)",
|
||||||
|
regA, t.param(3), t.param(5))
|
||||||
|
|
||||||
|
// Remote
|
||||||
|
case 0x24:
|
||||||
|
fmt.Printf("REMOTEREAD()")
|
||||||
|
case 0x27:
|
||||||
|
fmt.Printf("REMOTEWRITE('%s'[%v])", regAText, regA)
|
||||||
|
case 0x2a:
|
||||||
|
fmt.Printf("REMOTECTRL()")
|
||||||
|
case 0x2d:
|
||||||
|
fmt.Printf("REMOTESTAT(STATREC=[%04x], CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5))
|
||||||
|
|
||||||
|
// User
|
||||||
|
case 0x30:
|
||||||
|
fmt.Printf("USERREAD(BLOCK=%04x, LEN=%04x, DATA=[%04x], DEVICE=%v, CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5), t.param(7), t.param(9), t.param(11))
|
||||||
|
case 0x33:
|
||||||
|
fmt.Printf("USERWRITE(BLOCK=%04x, LEN=%04x, DATA=[%04x], DEVICE=%v, CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5), t.param(7), t.param(9), t.param(11))
|
||||||
|
case 0x36:
|
||||||
|
fmt.Printf("USERCTRL(DEVICE=%v)", regA)
|
||||||
|
case 0x39:
|
||||||
|
fmt.Printf("USERSTAT(DEVICE=%v, STATREC=[%04x], CONTROL=%04x)",
|
||||||
|
regA, t.param(3), t.param(5))
|
||||||
|
|
||||||
|
// Sys
|
||||||
|
case 0x3c:
|
||||||
|
fmt.Printf("SYSREAD(BLOCK=%04x, LEN=%04x, DATA=[%04x], DEVICE=%v, CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5), t.param(7), t.param(9), t.param(11))
|
||||||
|
case 0x3f:
|
||||||
|
fmt.Printf("SYSWRITE(BLOCK=%04x, LEN=%04x, DATA=[%04x], DEVICE=%v, CONTROL=%04x)",
|
||||||
|
t.param(3), t.param(5), t.param(7), t.param(9), t.param(11))
|
||||||
|
case 0x42:
|
||||||
|
fmt.Printf("SYSCTRL(DEVICE=%v)", regA)
|
||||||
|
case 0x43:
|
||||||
|
fmt.Printf("SYSSTAT(DEVICE=%v, STATREC=[%04x], CONTROL=%04x)",
|
||||||
|
regA, t.param(3), t.param(5))
|
||||||
|
|
||||||
|
default:
|
||||||
|
fmt.Printf("<unknown>")
|
||||||
|
}
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tracePascal) param(index uint8) uint16 {
|
||||||
|
_, sp := t.a.cpu.GetPCAndSP()
|
||||||
|
return uint16(t.a.mmu.Peek(0x100+uint16(sp+index))) +
|
||||||
|
uint16(t.a.mmu.Peek(0x100+uint16(sp+index+1)))<<8 - 2
|
||||||
|
}
|
|
@ -67,9 +67,9 @@ func (t *traceProDOS) inspect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *traceProDOS) dumpMLICall() {
|
func (t *traceProDOS) dumpMLICall() {
|
||||||
_, ps := t.a.cpu.GetPCAndSP()
|
_, sp := t.a.cpu.GetPCAndSP()
|
||||||
caller := uint16(t.a.mmu.Peek(0x100+uint16(ps+1))) +
|
caller := uint16(t.a.mmu.Peek(0x100+uint16(sp+1))) +
|
||||||
uint16(t.a.mmu.Peek(0x100+uint16(ps+2)))<<8 - 2
|
uint16(t.a.mmu.Peek(0x100+uint16(sp+2)))<<8 - 2
|
||||||
t.functionCode = t.a.mmu.Peek(caller + 3)
|
t.functionCode = t.a.mmu.Peek(caller + 3)
|
||||||
t.paramsAdddress = uint16(t.a.mmu.Peek(caller+4)) + uint16(t.a.mmu.Peek(caller+5))<<8
|
t.paramsAdddress = uint16(t.a.mmu.Peek(caller+4)) + uint16(t.a.mmu.Peek(caller+5))<<8
|
||||||
t.returnAddress = caller + 6
|
t.returnAddress = caller + 6
|
||||||
|
|
Loading…
Reference in New Issue