Trace sofswitches per card
This commit is contained in:
parent
0c615fc96c
commit
b2cf890957
|
@ -24,6 +24,10 @@ type cardBuilder struct {
|
||||||
|
|
||||||
const noCardName = "empty"
|
const noCardName = "empty"
|
||||||
|
|
||||||
|
var commonParams = []paramSpec{
|
||||||
|
{"tracess", "Trace softswitches", "false"},
|
||||||
|
}
|
||||||
|
|
||||||
var cardFactory map[string]*cardBuilder
|
var cardFactory map[string]*cardBuilder
|
||||||
|
|
||||||
func getCardFactory() map[string]*cardBuilder {
|
func getCardFactory() map[string]*cardBuilder {
|
||||||
|
@ -31,7 +35,9 @@ func getCardFactory() map[string]*cardBuilder {
|
||||||
return cardFactory
|
return cardFactory
|
||||||
}
|
}
|
||||||
cardFactory = make(map[string]*cardBuilder)
|
cardFactory = make(map[string]*cardBuilder)
|
||||||
cardFactory["brainboard"] = newCardBrainBoardIIBuilder()
|
//cardFactory["brainboard"] = newCardBrainBoardBuilder()
|
||||||
|
cardFactory["brainboard2"] = newCardBrainBoardIIBuilder()
|
||||||
|
//cardFactory["dan2sd"] = newCardDan2ControllerBuilder()
|
||||||
cardFactory["diskii"] = newCardDisk2Builder()
|
cardFactory["diskii"] = newCardDisk2Builder()
|
||||||
cardFactory["diskiiseq"] = newCardDisk2SequencerBuilder()
|
cardFactory["diskiiseq"] = newCardDisk2SequencerBuilder()
|
||||||
cardFactory["fastchip"] = newCardFastChipBuilder()
|
cardFactory["fastchip"] = newCardFastChipBuilder()
|
||||||
|
@ -57,9 +63,9 @@ func availableCards() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupCard(a *Apple2, slot int, paramString string) (Card, error) {
|
func setupCard(a *Apple2, slot int, paramString string) (Card, error) {
|
||||||
paramsArgs := splitConfigurationString(paramString, ',')
|
actualArgs := splitConfigurationString(paramString, ',')
|
||||||
|
|
||||||
cardName := paramsArgs[0]
|
cardName := actualArgs[0]
|
||||||
if cardName == "" || cardName == noCardName {
|
if cardName == "" || cardName == noCardName {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -74,25 +80,29 @@ func setupCard(a *Apple2, slot int, paramString string) (Card, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
finalParams := make(map[string]string)
|
finalParams := make(map[string]string)
|
||||||
|
for _, commonParam := range commonParams {
|
||||||
|
finalParams[commonParam.name] = commonParam.defaultValue
|
||||||
|
}
|
||||||
if builder.defaultParams != nil {
|
if builder.defaultParams != nil {
|
||||||
for _, defaultParam := range *builder.defaultParams {
|
for _, defaultParam := range *builder.defaultParams {
|
||||||
finalParams[defaultParam.name] = defaultParam.defaultValue
|
finalParams[defaultParam.name] = defaultParam.defaultValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 1; i < len(paramsArgs); i++ {
|
for i := 1; i < len(actualArgs); i++ {
|
||||||
paramArgSides := splitConfigurationString(paramsArgs[i], '=')
|
actualArgSides := splitConfigurationString(actualArgs[i], '=')
|
||||||
|
actualArgName := strings.ToLower(actualArgSides[0])
|
||||||
|
|
||||||
if _, ok := finalParams[paramArgSides[0]]; !ok {
|
if _, ok := finalParams[actualArgName]; !ok {
|
||||||
return nil, fmt.Errorf("unknown parameter %s", paramArgSides[0])
|
return nil, fmt.Errorf("unknown parameter %s", actualArgSides[0])
|
||||||
}
|
}
|
||||||
if len(paramArgSides) > 2 {
|
if len(actualArgSides) > 2 {
|
||||||
return nil, fmt.Errorf("invalid parameter value for %s", paramArgSides[0])
|
return nil, fmt.Errorf("invalid parameter value for %s", actualArgSides[0])
|
||||||
}
|
}
|
||||||
if len(paramArgSides) == 1 {
|
if len(actualArgSides) == 1 {
|
||||||
finalParams[paramArgSides[0]] = "true"
|
finalParams[actualArgName] = "true"
|
||||||
} else {
|
} else {
|
||||||
finalParams[paramArgSides[0]] = paramArgSides[1]
|
finalParams[actualArgName] = actualArgSides[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +111,12 @@ func setupCard(a *Apple2, slot int, paramString string) (Card, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Common parameters
|
||||||
|
traceSS := paramsGetBool(finalParams, "tracess")
|
||||||
|
if traceSS {
|
||||||
|
a.io.traceSlot(slot)
|
||||||
|
}
|
||||||
|
|
||||||
cardBase, ok := card.(*cardBase)
|
cardBase, ok := card.(*cardBase)
|
||||||
if err == nil && ok {
|
if err == nil && ok {
|
||||||
cardBase.name = builder.name
|
cardBase.name = builder.name
|
||||||
|
@ -139,11 +155,28 @@ func paramsGetPath(params map[string]string, name string) string {
|
||||||
func paramsGetInt(params map[string]string, name string) (int, error) {
|
func paramsGetInt(params map[string]string, name string) (int, error) {
|
||||||
value, ok := params[name]
|
value, ok := params[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
value = "0"
|
return 0, fmt.Errorf("missing parameter %s", name)
|
||||||
}
|
}
|
||||||
return strconv.Atoi(value)
|
return strconv.Atoi(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a 1 based array of bools
|
||||||
|
func paramsGetDIPs(params map[string]string, name string, size int) ([]bool, error) {
|
||||||
|
value, ok := params[name]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("missing parameter %s", name)
|
||||||
|
}
|
||||||
|
if len(value) != 8 {
|
||||||
|
return nil, fmt.Errorf("DIP switches must be 8 characters long")
|
||||||
|
}
|
||||||
|
result := make([]bool, size+1)
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
result[i+1] = value[i] == '1'
|
||||||
|
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func splitConfigurationString(s string, separator rune) []string {
|
func splitConfigurationString(s string, separator rune) []string {
|
||||||
// Split by comma, but not inside quotes
|
// Split by comma, but not inside quotes
|
||||||
var result []string
|
var result []string
|
||||||
|
|
|
@ -29,9 +29,8 @@ type CardThunderClockPlus struct {
|
||||||
|
|
||||||
func newCardThunderClockPlusBuilder() *cardBuilder {
|
func newCardThunderClockPlusBuilder() *cardBuilder {
|
||||||
return &cardBuilder{
|
return &cardBuilder{
|
||||||
name: "ThunderClock+ Card",
|
name: "ThunderClock+ Card",
|
||||||
description: "Clock card",
|
description: "Clock card",
|
||||||
defaultParams: &[]paramSpec{},
|
|
||||||
buildFunc: func(params map[string]string) (Card, error) {
|
buildFunc: func(params map[string]string) (Card, error) {
|
||||||
var c CardThunderClockPlus
|
var c CardThunderClockPlus
|
||||||
err := c.loadRomFromResource("<internal>/ThunderclockPlusROM.bin")
|
err := c.loadRomFromResource("<internal>/ThunderclockPlusROM.bin")
|
||||||
|
|
29
ioC0Page.go
29
ioC0Page.go
|
@ -16,7 +16,7 @@ type ioC0Page struct {
|
||||||
joysticks JoysticksProvider
|
joysticks JoysticksProvider
|
||||||
mouse MouseProvider
|
mouse MouseProvider
|
||||||
apple2 *Apple2
|
apple2 *Apple2
|
||||||
trace bool
|
traceMask uint16 // A bit for each 16 softswitches
|
||||||
traceRegistrations bool
|
traceRegistrations bool
|
||||||
panicNotImplemented bool
|
panicNotImplemented bool
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,16 @@ func newIoC0Page(a *Apple2) *ioC0Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ioC0Page) setTrace(trace bool) {
|
func (p *ioC0Page) setTrace(trace bool) {
|
||||||
p.trace = trace
|
if trace {
|
||||||
|
p.traceMask = 0xffff
|
||||||
|
} else {
|
||||||
|
p.traceMask = 0x0000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ioC0Page) traceSlot(slot int) {
|
||||||
|
p.traceMask |= 1 << (8 + slot)
|
||||||
|
fmt.Printf("Slot %v traced %04x\n", slot, p.traceMask)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ioC0Page) setTraceRegistrations(traceRegistrations bool) {
|
func (p *ioC0Page) setTraceRegistrations(traceRegistrations bool) {
|
||||||
|
@ -110,11 +119,17 @@ func (p *ioC0Page) setMouseProvider(m MouseProvider) {
|
||||||
p.mouse = m
|
p.mouse = m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *ioC0Page) isTraced(address uint16) bool {
|
||||||
|
ss := address & 0xff
|
||||||
|
return ss != 0xc000 && // Do not trace the spammy keyboard softswitch
|
||||||
|
(p.traceMask&(1<<(ss>>4))) != 0
|
||||||
|
}
|
||||||
|
|
||||||
func (p *ioC0Page) peek(address uint16) uint8 {
|
func (p *ioC0Page) peek(address uint16) uint8 {
|
||||||
pageAddress := uint8(address)
|
pageAddress := uint8(address)
|
||||||
ss := p.softSwitchesR[pageAddress]
|
ss := p.softSwitchesR[pageAddress]
|
||||||
if ss == nil {
|
if ss == nil {
|
||||||
if p.trace {
|
if p.isTraced(address) {
|
||||||
fmt.Printf("Unknown softswitch on read to $%04x\n", address)
|
fmt.Printf("Unknown softswitch on read to $%04x\n", address)
|
||||||
}
|
}
|
||||||
if p.panicNotImplemented {
|
if p.panicNotImplemented {
|
||||||
|
@ -123,7 +138,7 @@ func (p *ioC0Page) peek(address uint16) uint8 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
value := ss()
|
value := ss()
|
||||||
if p.trace && address != 0xc000 {
|
if p.isTraced(address) {
|
||||||
name := p.softSwitchesRName[pageAddress]
|
name := p.softSwitchesRName[pageAddress]
|
||||||
fmt.Printf("Softswitch peek on $%04x %v: $%02x\n", address, name, value)
|
fmt.Printf("Softswitch peek on $%04x %v: $%02x\n", address, name, value)
|
||||||
}
|
}
|
||||||
|
@ -134,15 +149,15 @@ func (p *ioC0Page) poke(address uint16, value uint8) {
|
||||||
pageAddress := uint8(address)
|
pageAddress := uint8(address)
|
||||||
ss := p.softSwitchesW[pageAddress]
|
ss := p.softSwitchesW[pageAddress]
|
||||||
if ss == nil {
|
if ss == nil {
|
||||||
if p.trace {
|
if p.isTraced(address) {
|
||||||
fmt.Printf("Unknown softswitch on write to $%04x\n", address)
|
fmt.Printf("Unknown softswitch on write $%02x to $%04x\n", value, address)
|
||||||
}
|
}
|
||||||
if p.panicNotImplemented {
|
if p.panicNotImplemented {
|
||||||
panic(fmt.Sprintf("Unknown softswitch on write to $%04x", address))
|
panic(fmt.Sprintf("Unknown softswitch on write to $%04x", address))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if p.trace && address != 0xc000 {
|
if p.isTraced(address) {
|
||||||
name := p.softSwitchesWName[pageAddress]
|
name := p.softSwitchesWName[pageAddress]
|
||||||
fmt.Printf("Softswitch poke on $%04x %v with $%02x\n", address, name, value)
|
fmt.Printf("Softswitch poke on $%04x %v with $%02x\n", address, name, value)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue