From 23ba372a25ea1052a7407920105ba13f23c4da50 Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Fri, 10 May 2019 18:07:36 +0200 Subject: [PATCH] Automatic fast mode while disks are spinning --- apple2/apple2.go | 47 +++++++++++++++++++++++++++++------------ apple2/cardBase.go | 2 ++ apple2/cardDisk2.go | 16 ++++++++------ apple2sdl/sdlSpeaker.go | 6 +++--- main.go | 8 ++++++- 5 files changed, 55 insertions(+), 24 deletions(-) diff --git a/apple2/apple2.go b/apple2/apple2.go index 336cb3a..c817699 100644 --- a/apple2/apple2.go +++ b/apple2/apple2.go @@ -10,17 +10,19 @@ import ( // 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 - commandChannel chan int - cycleDurationNs float64 // Inverse of the cpu clock in Ghz - isColor bool + 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 + isColor bool + fastMode bool + fastRequestsCounter int } const ( @@ -30,7 +32,8 @@ const ( ) // NewApple2 instantiates an apple2 -func NewApple2(romFile string, charRomFile string, clockMhz float64, isColor bool, panicSS bool) *Apple2 { +func NewApple2(romFile string, charRomFile string, clockMhz float64, + isColor bool, fastMode bool, panicSS bool) *Apple2 { var a Apple2 a.mmu = newMemoryManager(&a) a.cpu = core6502.NewNMOS6502(a.mmu) @@ -41,6 +44,7 @@ func NewApple2(romFile string, charRomFile string, clockMhz float64, isColor boo a.mmu.resetRomPaging() a.commandChannel = make(chan int, 100) a.isColor = isColor + a.fastMode = fastMode a.panicSS = panicSS if clockMhz <= 0 { @@ -122,6 +126,8 @@ func (a *Apple2) executeCommand(command int) { } } +const maxWaitDuration = 100 * time.Millisecond + // Run starts the Apple2 emulation func (a *Apple2) Run(log bool) { // Start the processor @@ -142,12 +148,12 @@ func (a *Apple2) Run(log bool) { } } - if a.cycleDurationNs != 0 { + if a.cycleDurationNs != 0 && a.fastRequestsCounter <= 0 { // Wait until next 6502 step has to run clockDuration := time.Since(referenceTime) simulatedDuration := time.Duration(float64(a.cpu.GetCycles()) * a.cycleDurationNs) waitDuration := simulatedDuration - clockDuration - if waitDuration > 1*time.Second { + if waitDuration > maxWaitDuration { // We have to wait too long. Let's fast forward referenceTime = referenceTime.Add(-waitDuration) waitDuration = 0 @@ -165,6 +171,19 @@ const ( apple2eRomSize = 16 * 1024 ) +func (a *Apple2) requestFastMode() { + // Note: if the fastMode is shorter than maxWaitDuration, there won't be any gain. + if a.fastMode { + a.fastRequestsCounter++ + } +} + +func (a *Apple2) releaseFastMode() { + if a.fastMode { + a.fastRequestsCounter-- + } +} + func (a *Apple2) loadRom(filename string) { f, err := os.Open(filename) if err != nil { diff --git a/apple2/cardBase.go b/apple2/cardBase.go index 4227168..a3dcbcc 100644 --- a/apple2/cardBase.go +++ b/apple2/cardBase.go @@ -1,6 +1,7 @@ package apple2 type cardBase struct { + a *Apple2 rom []memoryPage slot int ssr [16]softSwitchR @@ -8,6 +9,7 @@ type cardBase struct { } func (c *cardBase) insert(a *Apple2, slot int) { + c.a = a c.slot = slot if slot != 0 && c.rom[0] != nil { a.mmu.setPage(uint8(0xC0+slot), c.rom[0]) diff --git a/apple2/cardDisk2.go b/apple2/cardDisk2.go index 92267a7..fad5f60 100644 --- a/apple2/cardDisk2.go +++ b/apple2/cardDisk2.go @@ -31,8 +31,6 @@ type cardDisk2Drive struct { position int } -// type softSwitchR func(io *ioC0Page) uint8 - func newCardDisk2(filename string) *cardDisk2 { var c cardDisk2 c.rom = loadCardRom(filename) @@ -75,13 +73,19 @@ func newCardDisk2(filename string) *cardDisk2 { // Other soft switches c.ssr[0x8] = func(_ *ioC0Page) uint8 { - c.drive[c.selected].power = false - //fmt.Printf("DISKII: Disk %v is off\n", c.selected) + if c.drive[c.selected].power { + c.drive[c.selected].power = false + c.a.releaseFastMode() + //fmt.Printf("DISKII: Disk %v is off for %v\n", c.selected, x) + } return 0 } c.ssr[0x9] = func(_ *ioC0Page) uint8 { - c.drive[c.selected].power = true - //fmt.Printf("DISKII: Disk %v is on\n", c.selected) + if !c.drive[c.selected].power { + c.drive[c.selected].power = true + c.a.requestFastMode() + //fmt.Printf("DISKII: Disk %v is on\n", c.selected) + } return 0 } c.ssr[0xA] = func(_ *ioC0Page) uint8 { diff --git a/apple2sdl/sdlSpeaker.go b/apple2sdl/sdlSpeaker.go index b6c0af4..392a6c7 100644 --- a/apple2sdl/sdlSpeaker.go +++ b/apple2sdl/sdlSpeaker.go @@ -6,8 +6,8 @@ void SpeakerCallback(void *userdata, Uint8 *stream, int len); */ import "C" import ( + "fmt" "go6502/apple2" - "log" "reflect" "unsafe" @@ -135,7 +135,7 @@ func SpeakerCallback(userdata unsafe.Pointer, stream *C.Uint8, length C.int) { func (s *sdlSpeaker) start() { err := sdl.Init(sdl.INIT_AUDIO) if err != nil { - log.Printf("Error starting SDL audio: %v.\n", err) + fmt.Printf("Error starting SDL audio: %v.\n", err) return } @@ -148,7 +148,7 @@ func (s *sdlSpeaker) start() { } if err := sdl.OpenAudio(spec, nil); err != nil { - log.Printf("Error opening the SDL audio channel: %v.\n", err) + fmt.Printf("Error opening the SDL audio channel: %v.\n", err) return } sdl.PauseAudio(false) diff --git a/main.go b/main.go index 8834950..3999ce1 100644 --- a/main.go +++ b/main.go @@ -44,6 +44,12 @@ func main() { false, "emulate a green phosphor monitor instead of a NTSC color TV. Use F6 to toggle.", ) + fastDisk := flag.Bool( + "fastDisk", + true, + "set fast mode when the disks are spinning", + ) + panicSS := flag.Bool( "panicss", false, @@ -62,7 +68,7 @@ func main() { } log := false - a := apple2.NewApple2(*romFile, *charRomFile, *cpuClock, !*mono, *panicSS) + a := apple2.NewApple2(*romFile, *charRomFile, *cpuClock, !*mono, *fastDisk, *panicSS) if *disk2Slot > 0 { a.AddDisk2(*disk2Slot, *disk2RomFile, *diskImage) }