More comments

This commit is contained in:
Will Angenent 2018-05-28 10:54:36 +01:00
parent dc28e6afe4
commit bf09ca8257
3 changed files with 49 additions and 30 deletions

View File

@ -4,14 +4,14 @@ import (
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten"
) )
var ebitenAsciiMap map[ebiten.Key]uint8 var ebitenAsciiMap map[ebiten.Key]uint8 // ebiten keys mapped to ASCII
var shiftMap map[uint8]uint8 var shiftMap map[uint8]uint8 // ebiten keys mapped to ASCII when shift is pressed
var controlMap map[uint8]uint8 var controlMap map[uint8]uint8 // ebiten keys mapped to ASCII when control is pressed
var keyBoardData uint8 var keyBoardData uint8 // Contents of the $c000 address
var strobe uint8 var strobe uint8 // Contents of the $c010 address
var previousKeysPressed map[uint8]bool var previousKeysPressed map[uint8]bool // Keep track of what keys have been pressed in the previous round
var capsLock bool var capsLock bool // Is capslock down
// Init the keyboard state and ebiten translation tables // Init the keyboard state and ebiten translation tables
func Init() { func Init() {
@ -190,12 +190,14 @@ func Init() {
controlMap['~'] = 0x60 controlMap['~'] = 0x60
} }
// Poll queries ebiten's keyboard state and transforms that into apple //e // Poll queries ebiten's keyboard state and transforms that into ASCII
// values in $c000 and $c010 // values in $c000 and $c010. Keypresses from the previous round have to be
// taken into account in order to detect if a single new key has been pressed.
func Poll() { func Poll() {
allKeysPressed := make(map[uint8]bool) allKeysPressed := make(map[uint8]bool)
newKeysPressed := make(map[uint8]bool) newKeysPressed := make(map[uint8]bool)
// Query ebiten for all possible keys
for k, v := range ebitenAsciiMap { for k, v := range ebitenAsciiMap {
if ebiten.IsKeyPressed(k) { if ebiten.IsKeyPressed(k) {
allKeysPressed[v] = true allKeysPressed[v] = true
@ -222,6 +224,8 @@ func Poll() {
} }
// Implicit else, one new key has been pressed // Implicit else, one new key has been pressed
// Get the key
keys := []uint8{} keys := []uint8{}
for k := range newKeysPressed { for k := range newKeysPressed {
keys = append(keys, k) keys = append(keys, k)
@ -229,11 +233,13 @@ func Poll() {
key := keys[0] key := keys[0]
if ebiten.IsKeyPressed(ebiten.KeyControl) && ebiten.IsKeyPressed(ebiten.KeyAlt) && key == 'c' { if ebiten.IsKeyPressed(ebiten.KeyControl) && ebiten.IsKeyPressed(ebiten.KeyAlt) && key == 'c' {
// Toggle capslock
capsLock = !capsLock capsLock = !capsLock
} else { } else {
// Normal case. Transform the ebiten key into ASCII
shift := ebiten.IsKeyPressed(ebiten.KeyShift) shift := ebiten.IsKeyPressed(ebiten.KeyShift)
shift = shift || (capsLock && key >= 'a' && key <= 'z') shift = shift || (capsLock && key >= 'a' && key <= 'z')
if shift { if shift {
shiftedKey, present := shiftMap[key] shiftedKey, present := shiftMap[key]
if present { if present {
@ -247,6 +253,7 @@ func Poll() {
key = controlKey key = controlKey
} }
} }
keyBoardData = key | 0x80 keyBoardData = key | 0x80
strobe = keyBoardData strobe = keyBoardData
} }
@ -254,10 +261,12 @@ func Poll() {
return return
} }
// Read returns the data and strobe values from set from the Poll() call
func Read() (uint8, uint8) { func Read() (uint8, uint8) {
return keyBoardData, strobe return keyBoardData, strobe
} }
// ResetStrobe clears the high bit in keyboardData
func ResetStrobe() { func ResetStrobe() {
keyBoardData &= 0x7f keyBoardData &= 0x7f
} }

View File

@ -1,32 +1,36 @@
package system package system
// The system package is a dumping ground for globals that are shared between
// the packages.
const ( const (
CpuFrequency = 1023000 CpuFrequency = 1023000 // 6402 CPU frequency in Hz
AudioSampleRate = 44100 AudioSampleRate = 44100 // Audio sample rate in Hz
) )
var ( var (
PendingInterrupt bool PendingInterrupt bool // Set when an interrupt has just happened
PendingNMI bool PendingNMI bool // Set when a non maskable interrupt has just happened
RunningTests bool RunningTests bool // For testing
RunningFunctionalTests bool RunningFunctionalTests bool // For testing
RunningInterruptTests bool RunningInterruptTests bool // For testing
Cycles uint64 Cycles uint64 // Total CPU cycles executed
FrameCycles uint64 FrameCycles uint64 // CPU cycles executed in the current frame
AudioChannel chan int16 AudioChannel chan int16 // Audio channel
LastAudioValue int16 LastAudioValue int16 // + or - value of the current square wave
LastAudioCycles uint64 LastAudioCycles uint64 // Last CPU cycle when audio was sent to the channel
AudioAttenuationCounter uint64 AudioAttenuationCounter uint64 // Counter to keep track of when the audio should be zeroed after inactivity
) )
// DriveState has the state of the disk drive
var DriveState struct { var DriveState struct {
Drive uint8 Drive uint8 // What drive we're using. Currently only 1 is implemented
Spinning bool Spinning bool // Is the motor spinning
Phase int8 Phase int8 // Phase of the stepper motor
Phases uint8 Phases uint8 // the 4 lowest bits represent the 4 stepper motor magnet on/off states.
BytePosition int BytePosition int // Index of the position on the current track
Q6 bool Q6 bool // Q6 soft switch
Q7 bool Q7 bool // Q7 soft switch
} }
// Init initializes the system-wide state // Init initializes the system-wide state

View File

@ -12,6 +12,7 @@ import (
"github.com/freewilll/apple2/system" "github.com/freewilll/apple2/system"
) )
// ReadMemoryFromGzipFile just reads and uncompresses a gzip file
func ReadMemoryFromGzipFile(filename string) (data []byte, err error) { func ReadMemoryFromGzipFile(filename string) (data []byte, err error) {
f, err := os.Open(filename) f, err := os.Open(filename)
if err != nil { if err != nil {
@ -29,6 +30,7 @@ func ReadMemoryFromGzipFile(filename string) (data []byte, err error) {
return return
} }
// DecodeCmdLineAddress decodes a 4 byte string hex address
func DecodeCmdLineAddress(s *string) (result *uint16) { func DecodeCmdLineAddress(s *string) (result *uint16) {
if *s != "" { if *s != "" {
breakAddressValue, err := hex.DecodeString(*s) breakAddressValue, err := hex.DecodeString(*s)
@ -50,6 +52,9 @@ func DecodeCmdLineAddress(s *string) (result *uint16) {
return result return result
} }
// RunUntilBreakPoint runs the CPU until it either hits a breakpoint or a time
// has expired. An assertion is done at the end to ensure the breakpoint has
// been reached.
func RunUntilBreakPoint(t *testing.T, breakAddress uint16, seconds int, showInstructions bool, message string) { func RunUntilBreakPoint(t *testing.T, breakAddress uint16, seconds int, showInstructions bool, message string) {
fmt.Printf("Running until %#04x: %s \n", breakAddress, message) fmt.Printf("Running until %#04x: %s \n", breakAddress, message)
system.FrameCycles = 0 system.FrameCycles = 0
@ -62,6 +67,7 @@ func RunUntilBreakPoint(t *testing.T, breakAddress uint16, seconds int, showInst
} }
} }
// Disassemble disassembles and prints the code in memory between start and end
func Disassemble(start uint16, end uint16) { func Disassemble(start uint16, end uint16) {
oldPC := cpu.State.PC oldPC := cpu.State.PC