mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-03-17 04:29:19 +00:00
CPU clock speed emulation
This commit is contained in:
parent
240cfbae9b
commit
78ff401ff0
@ -51,12 +51,12 @@ func (fe *ansiConsoleFrontend) GetKey(strobed bool) (key uint8, ok bool) {
|
||||
stdinReader := func(c chan uint8) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
byte, err := reader.ReadByte()
|
||||
key, err := reader.ReadByte()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
c <- byte
|
||||
c <- key
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,22 +4,31 @@ import (
|
||||
"bufio"
|
||||
"go6502/core6502"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Apple2 represents all the components and state of the emulated machine
|
||||
type Apple2 struct {
|
||||
cpu *core6502.State
|
||||
mmu *memoryManager
|
||||
io *ioC0Page
|
||||
cg *CharacterGenerator
|
||||
cards []cardBase
|
||||
isApple2e bool
|
||||
panicSS bool
|
||||
activeSlot int // Slot that has the addressing 0xc800 to 0ccfff
|
||||
cpu *core6502.State
|
||||
mmu *memoryManager
|
||||
io *ioC0Page
|
||||
cg *CharacterGenerator
|
||||
cards []cardBase
|
||||
isApple2e bool
|
||||
panicSS bool
|
||||
activeSlot int // Slot that has the addressing 0xc800 to 0ccfff
|
||||
commandChannel chan int
|
||||
cycleDurationNs float64 // Inverse of the cpu clock in Ghz
|
||||
}
|
||||
|
||||
const (
|
||||
// CpuClockMhz is the actual Apple II clock speed
|
||||
CpuClockMhz = 14.318 / 14
|
||||
cpuClockEuroMhz = 14.238 / 14
|
||||
)
|
||||
|
||||
// NewApple2 instantiates an apple2
|
||||
func NewApple2(romFile string, charRomFile string, panicSS bool) *Apple2 {
|
||||
func NewApple2(romFile string, charRomFile string, clockMhz float64, panicSS bool) *Apple2 {
|
||||
var a Apple2
|
||||
a.mmu = newMemoryManager(&a)
|
||||
a.cpu = core6502.NewNMOS6502(a.mmu)
|
||||
@ -27,9 +36,17 @@ func NewApple2(romFile string, charRomFile string, panicSS bool) *Apple2 {
|
||||
if charRomFile != "" {
|
||||
a.cg = NewCharacterGenerator(charRomFile)
|
||||
}
|
||||
a.mmu.resetPaging()
|
||||
a.mmu.resetRomPaging()
|
||||
a.commandChannel = make(chan int, 100)
|
||||
a.panicSS = panicSS
|
||||
|
||||
if clockMhz <= 0 {
|
||||
// Full speed
|
||||
a.cycleDurationNs = 0
|
||||
} else {
|
||||
a.cycleDurationNs = 1000.0 / clockMhz
|
||||
}
|
||||
|
||||
// Set the io in 0xc000
|
||||
a.io = newIoC0Page(&a)
|
||||
a.mmu.setPage(0xc0, a.io)
|
||||
@ -65,18 +82,50 @@ func (a *Apple2) ConfigureStdConsole(stdinKeyboard bool, stdoutScreen bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetKeyboardProvider attaches an external keyboard provider
|
||||
func (a *Apple2) SetKeyboardProvider(kb KeyboardProvider) {
|
||||
a.io.setKeyboardProvider(kb)
|
||||
}
|
||||
|
||||
// SendCommand enqueues a command to the emulator thread
|
||||
func (a *Apple2) SendCommand(command int) {
|
||||
a.commandChannel <- command
|
||||
}
|
||||
|
||||
func (a *Apple2) executeCommand(command int) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
// Run starts the Apple2 emulation
|
||||
func (a *Apple2) Run(log bool) {
|
||||
// Start the processor
|
||||
a.cpu.Reset()
|
||||
startTime := time.Now()
|
||||
for {
|
||||
// Run a 6502 step
|
||||
a.cpu.ExecuteInstruction(log)
|
||||
}
|
||||
}
|
||||
|
||||
// SetKeyboardProvider attaches an external keyboard provider
|
||||
func (a *Apple2) SetKeyboardProvider(kb KeyboardProvider) {
|
||||
a.io.setKeyboardProvider(kb)
|
||||
// Execute meta commands
|
||||
commandsPending := true
|
||||
for commandsPending {
|
||||
select {
|
||||
case command := <-a.commandChannel:
|
||||
a.executeCommand(command)
|
||||
default:
|
||||
commandsPending = false
|
||||
}
|
||||
}
|
||||
|
||||
if a.cycleDurationNs != 0 {
|
||||
// Wait until next 6502 step has to run
|
||||
clockDuration := time.Since(startTime)
|
||||
simulatedDurationNs := time.Duration(float64(a.cpu.GetCycles()) * a.cycleDurationNs)
|
||||
waitDuration := simulatedDurationNs - clockDuration
|
||||
if waitDuration > 0 {
|
||||
time.Sleep(waitDuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// LoadRom loads a binary file to the top of the memory.
|
||||
|
@ -98,7 +98,7 @@ func newMemoryManager(a *Apple2) *memoryManager {
|
||||
return &mmu
|
||||
}
|
||||
|
||||
func (mmu *memoryManager) resetPaging() {
|
||||
func (mmu *memoryManager) resetRomPaging() {
|
||||
// Assign the first 12kb of ROM from 0xd000 to 0xfff
|
||||
for i := 0xd0; i <= 0xff; i++ {
|
||||
mmu.setPage(uint8(i), &(mmu.physicalROM[i-0xd0]))
|
||||
|
@ -68,7 +68,7 @@ func SDLRun(a *apple2.Apple2) {
|
||||
surface.Free()
|
||||
texture.Destroy()
|
||||
}
|
||||
sdl.Delay(1000 / 60)
|
||||
sdl.Delay(1000 / 30)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -69,9 +69,15 @@ func (s *State) ExecuteInstruction(log bool) {
|
||||
// Reset resets the processor state. Moves the program counter to the vector in 0cfffc.
|
||||
func (s *State) Reset() {
|
||||
startAddress := getWord(s.mem, vectorReset)
|
||||
s.cycles = 0
|
||||
s.reg.setPC(startAddress)
|
||||
}
|
||||
|
||||
// GetCycles returns the count of CPU cycles since last reset.
|
||||
func (s *State) GetCycles() int64 {
|
||||
return s.cycles
|
||||
}
|
||||
|
||||
func lineString(line []uint8, opcode opcode) string {
|
||||
t := opcode.name
|
||||
switch opcode.addressMode {
|
||||
|
14
main.go
14
main.go
@ -19,6 +19,10 @@ func main() {
|
||||
"disk",
|
||||
"../dos33.dsk",
|
||||
"file to load on the first disk drive")
|
||||
cpuClock := flag.Float64(
|
||||
"mhz",
|
||||
apple2.CpuClockMhz,
|
||||
"cpu speed in Mhz, use 0 for full speed")
|
||||
charRomFile := flag.String(
|
||||
"charRom",
|
||||
"apple2/romdumps/Apple2rev7CharGen.rom",
|
||||
@ -42,14 +46,6 @@ func main() {
|
||||
)
|
||||
flag.Parse()
|
||||
|
||||
//romFile := "apple2/romdumps/Apple2.rom"
|
||||
//romFile := "apple2/romdumps/Apple2_Plus.rom"
|
||||
//romFile := "apple2/romdumps/Apple2e.rom"
|
||||
//disk2RomFile := "apple2/romdumps/DISK2.rom"
|
||||
//diskImage := "../dos33.dsk"
|
||||
//diskImage := "../Apex II - Apple II Diagnostic (v4.7-1986).DSK"
|
||||
//diskImage := "../A2Diag.v4.1.SDK"
|
||||
|
||||
if *dumpChars {
|
||||
cg := apple2.NewCharacterGenerator(*charRomFile)
|
||||
cg.Dump()
|
||||
@ -57,7 +53,7 @@ func main() {
|
||||
}
|
||||
|
||||
log := false
|
||||
a := apple2.NewApple2(*romFile, *charRomFile, *panicSS)
|
||||
a := apple2.NewApple2(*romFile, *charRomFile, *cpuClock, *panicSS)
|
||||
a.AddDisk2(*disk2RomFile, *diskImage)
|
||||
if *useSdl {
|
||||
a.ConfigureStdConsole(false, *stdoutScreen)
|
||||
|
Loading…
x
Reference in New Issue
Block a user