Automatic fast mode while disks are spinning

This commit is contained in:
Ivan Izaguirre 2019-05-10 18:07:36 +02:00
parent e449ccd907
commit 23ba372a25
5 changed files with 55 additions and 24 deletions

View File

@ -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 {

View File

@ -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])

View File

@ -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 {

View File

@ -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)

View File

@ -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)
}