Improved keyboard support wih SDL
This commit is contained in:
parent
2ca630ddfc
commit
b775526b34
|
@ -42,7 +42,7 @@ func (fe *ansiConsoleFrontend) subscribeToTextPages() {
|
|||
|
||||
const refreshDelayMs = 100
|
||||
|
||||
func (fe *ansiConsoleFrontend) getKey() (key uint8, ok bool) {
|
||||
func (fe *ansiConsoleFrontend) GetKey() (key uint8, ok bool) {
|
||||
stdinReader := func(c chan uint8) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
|
|
|
@ -44,10 +44,12 @@ func (a *Apple2) AddDisk2(diskRomFile string, diskImage string) {
|
|||
}
|
||||
|
||||
// Run starts the Apple2 emulation
|
||||
func (a *Apple2) Run(log bool) {
|
||||
func (a *Apple2) Run(log bool, consoleKeyboard bool) {
|
||||
// Init frontend
|
||||
fe := newAnsiConsoleFrontend(a)
|
||||
a.io.setKeyboardProvider(fe)
|
||||
if consoleKeyboard {
|
||||
a.io.setKeyboardProvider(fe)
|
||||
}
|
||||
if !log {
|
||||
go fe.textModeGoRoutine()
|
||||
}
|
||||
|
@ -59,6 +61,11 @@ func (a *Apple2) Run(log bool) {
|
|||
}
|
||||
}
|
||||
|
||||
// SetKeyboardProvider attaches an external keyboard provider
|
||||
func (a *Apple2) SetKeyboardProvider(kb KeyboardProvider) {
|
||||
a.io.setKeyboardProvider(kb)
|
||||
}
|
||||
|
||||
// LoadRom loads a binary file to the top of the memory.
|
||||
const (
|
||||
apple2RomSize = 12 * 1024
|
||||
|
|
|
@ -8,15 +8,15 @@ type ioC0Page struct {
|
|||
softSwitchesR [256]softSwitchR
|
||||
softSwitchesW [256]softSwitchW
|
||||
softSwitchesData [128]uint8
|
||||
keyboard keyboardProvider
|
||||
keyboard KeyboardProvider
|
||||
apple2 *Apple2
|
||||
}
|
||||
|
||||
type softSwitchR func(io *ioC0Page) uint8
|
||||
type softSwitchW func(io *ioC0Page, value uint8)
|
||||
|
||||
type keyboardProvider interface {
|
||||
getKey() (key uint8, ok bool)
|
||||
type KeyboardProvider interface {
|
||||
GetKey() (key uint8, ok bool)
|
||||
}
|
||||
|
||||
// See https://www.kreativekorp.com/miscpages/a2info/iomemory.shtml
|
||||
|
@ -64,7 +64,7 @@ func (p *ioC0Page) isSoftSwitchExtActive(ioFlag uint8) bool {
|
|||
return (p.softSwitchesData[ioFlag] & ssOn) == ssOn
|
||||
}
|
||||
|
||||
func (p *ioC0Page) setKeyboardProvider(kb keyboardProvider) {
|
||||
func (p *ioC0Page) setKeyboardProvider(kb KeyboardProvider) {
|
||||
p.keyboard = kb
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ func getSoftSwitch(ioFlag uint8, isSet bool) softSwitchR {
|
|||
func getKeySoftSwitch(io *ioC0Page) uint8 {
|
||||
strobed := (io.softSwitchesData[ioDataKeyboard] & (1 << 7)) == 0
|
||||
if strobed && io.keyboard != nil {
|
||||
if key, ok := io.keyboard.getKey(); ok {
|
||||
if key, ok := io.keyboard.GetKey(); ok {
|
||||
io.softSwitchesData[ioDataKeyboard] = key + (1 << 7)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package apple2sdl
|
||||
|
||||
import (
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
|
||||
"go6502/apple2"
|
||||
)
|
||||
|
||||
// SDLRun starts the Apple2 emulator on SDL
|
||||
func SDLRun(a *apple2.Apple2) {
|
||||
window, renderer, err := sdl.CreateWindowAndRenderer(800, 600, sdl.WINDOW_SHOWN)
|
||||
if err != nil {
|
||||
panic("Failed to create window")
|
||||
}
|
||||
defer window.Destroy()
|
||||
defer renderer.Destroy()
|
||||
window.SetTitle("Apple2")
|
||||
renderer.Clear()
|
||||
renderer.Present()
|
||||
|
||||
kp := newSDLKeyBoard()
|
||||
a.SetKeyboardProvider(&kp)
|
||||
go a.Run(false, false)
|
||||
|
||||
running := true
|
||||
for running {
|
||||
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
||||
switch t := event.(type) {
|
||||
case *sdl.QuitEvent:
|
||||
running = false
|
||||
case *sdl.KeyboardEvent:
|
||||
//fmt.Printf("[%d ms] Keyboard\ttype:%d\tsym:%c\tmodifiers:%d\tstate:%d\trepeat:%d\n",
|
||||
// t.Timestamp, t.Type, t.Keysym.Sym, t.Keysym.Mod, t.State, t.Repeat)
|
||||
kp.putKey(t)
|
||||
case *sdl.TextInputEvent:
|
||||
//fmt.Printf("[%d ms] TextInput\ttype:%d\texts:%s\n",
|
||||
// t.Timestamp, t.Type, t.GetText())
|
||||
kp.putText(t)
|
||||
}
|
||||
}
|
||||
sdl.Delay(1000 / 60)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package apple2sdl
|
||||
|
||||
import (
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/veandco/go-sdl2/sdl"
|
||||
)
|
||||
|
||||
type sdlKeyboard struct {
|
||||
keyChannel chan uint8
|
||||
}
|
||||
|
||||
func newSDLKeyBoard() sdlKeyboard {
|
||||
var k sdlKeyboard
|
||||
k.keyChannel = make(chan uint8, 100)
|
||||
return k
|
||||
}
|
||||
|
||||
func (k *sdlKeyboard) putText(textEvent *sdl.TextInputEvent) {
|
||||
text := textEvent.GetText()
|
||||
|
||||
for _, ch := range text {
|
||||
// We will use computed text only for printable ASCII chars
|
||||
if ch < ' ' || ch > '~' {
|
||||
continue
|
||||
}
|
||||
|
||||
buf := make([]uint8, 1)
|
||||
utf8.EncodeRune(buf, ch)
|
||||
|
||||
k.putChar(buf[0])
|
||||
}
|
||||
}
|
||||
|
||||
func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
|
||||
/* To get keys as understood by the Apple2 hardware run:
|
||||
10 A=PEEK(49152)
|
||||
20 B = A - 128
|
||||
30 PRINT A, B
|
||||
40 GOTO 10
|
||||
*/
|
||||
if keyEvent.Type != sdl.KEYDOWN {
|
||||
// Process only key pushes
|
||||
return
|
||||
}
|
||||
|
||||
key := keyEvent.Keysym
|
||||
ctrl := key.Mod&sdl.KMOD_CTRL != 0
|
||||
|
||||
if ctrl {
|
||||
if key.Sym >= 'a' && key.Sym <= 'z' {
|
||||
k.putChar(uint8(key.Sym) - 97 + 1)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
result := uint8(0)
|
||||
|
||||
switch key.Sym {
|
||||
case sdl.K_ESCAPE:
|
||||
result = 27
|
||||
case sdl.K_BACKSPACE:
|
||||
result = 24
|
||||
case sdl.K_RETURN:
|
||||
result = 13
|
||||
case sdl.K_RETURN2:
|
||||
result = 13
|
||||
case sdl.K_LEFT:
|
||||
if ctrl {
|
||||
result = 31 // Base64A
|
||||
}
|
||||
result = 8
|
||||
case sdl.K_RIGHT:
|
||||
result = 21
|
||||
|
||||
// Base64A clone particularities
|
||||
case sdl.K_F2:
|
||||
result = 127
|
||||
case sdl.K_UP:
|
||||
result = 31
|
||||
case sdl.K_DOWN:
|
||||
result = 10
|
||||
}
|
||||
|
||||
// Missing values 91 to 95. Usually control for [\]^_
|
||||
// On the Base64A it's control for \]./
|
||||
|
||||
if result != 0 {
|
||||
k.putChar(result)
|
||||
}
|
||||
}
|
||||
|
||||
func (k *sdlKeyboard) putChar(ch uint8) {
|
||||
k.keyChannel <- ch
|
||||
}
|
||||
|
||||
func (k *sdlKeyboard) GetKey() (key uint8, ok bool) {
|
||||
select {
|
||||
case key = <-k.keyChannel:
|
||||
ok = true
|
||||
default:
|
||||
ok = false
|
||||
}
|
||||
return
|
||||
}
|
12
main.go
12
main.go
|
@ -1,6 +1,9 @@
|
|||
package main
|
||||
|
||||
import "go6502/apple2"
|
||||
import (
|
||||
"go6502/apple2"
|
||||
"go6502/apple2sdl"
|
||||
)
|
||||
|
||||
func main() {
|
||||
//romFile := "apple2/romdumps/Apple2.rom"
|
||||
|
@ -10,7 +13,12 @@ func main() {
|
|||
diskImage := "../dos33.dsk"
|
||||
|
||||
log := false
|
||||
sdl := true
|
||||
a := apple2.NewApple2(romFile)
|
||||
a.AddDisk2(disk2RomFile, diskImage)
|
||||
a.Run(log)
|
||||
if sdl {
|
||||
apple2sdl.SDLRun(a)
|
||||
} else {
|
||||
a.Run(log, true)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue