F6 to toggle mono/color modes
This commit is contained in:
parent
9247ae02af
commit
6fca02da6b
|
@ -20,6 +20,7 @@ type Apple2 struct {
|
||||||
activeSlot int // Slot that has the addressing 0xc800 to 0ccfff
|
activeSlot int // Slot that has the addressing 0xc800 to 0ccfff
|
||||||
commandChannel chan int
|
commandChannel chan int
|
||||||
cycleDurationNs float64 // Inverse of the cpu clock in Ghz
|
cycleDurationNs float64 // Inverse of the cpu clock in Ghz
|
||||||
|
isColor bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -29,7 +30,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewApple2 instantiates an apple2
|
// NewApple2 instantiates an apple2
|
||||||
func NewApple2(romFile string, charRomFile string, clockMhz float64, panicSS bool) *Apple2 {
|
func NewApple2(romFile string, charRomFile string, clockMhz float64, isColor bool, panicSS bool) *Apple2 {
|
||||||
var a Apple2
|
var a Apple2
|
||||||
a.mmu = newMemoryManager(&a)
|
a.mmu = newMemoryManager(&a)
|
||||||
a.cpu = core6502.NewNMOS6502(a.mmu)
|
a.cpu = core6502.NewNMOS6502(a.mmu)
|
||||||
|
@ -39,6 +40,7 @@ func NewApple2(romFile string, charRomFile string, clockMhz float64, panicSS boo
|
||||||
}
|
}
|
||||||
a.mmu.resetRomPaging()
|
a.mmu.resetRomPaging()
|
||||||
a.commandChannel = make(chan int, 100)
|
a.commandChannel = make(chan int, 100)
|
||||||
|
a.isColor = isColor
|
||||||
a.panicSS = panicSS
|
a.panicSS = panicSS
|
||||||
|
|
||||||
if clockMhz <= 0 {
|
if clockMhz <= 0 {
|
||||||
|
@ -91,6 +93,8 @@ func (a *Apple2) SetKeyboardProvider(kb KeyboardProvider) {
|
||||||
const (
|
const (
|
||||||
// CommandToggleSpeed toggles cpu speed between full speed and actual Apple II speed
|
// CommandToggleSpeed toggles cpu speed between full speed and actual Apple II speed
|
||||||
CommandToggleSpeed = iota + 1
|
CommandToggleSpeed = iota + 1
|
||||||
|
// CommandToggleColor toggles between NTSC color TV and Green phospor monitor
|
||||||
|
CommandToggleColor
|
||||||
)
|
)
|
||||||
|
|
||||||
// SendCommand enqueues a command to the emulator thread
|
// SendCommand enqueues a command to the emulator thread
|
||||||
|
@ -108,6 +112,8 @@ func (a *Apple2) executeCommand(command int) {
|
||||||
fmt.Println("Fast")
|
fmt.Println("Fast")
|
||||||
a.cycleDurationNs = 0
|
a.cycleDurationNs = 0
|
||||||
}
|
}
|
||||||
|
case CommandToggleColor:
|
||||||
|
a.isColor = !a.isColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ References:
|
||||||
|
|
||||||
// Snapshot the currently visible screen
|
// Snapshot the currently visible screen
|
||||||
func Snapshot(a *Apple2) *image.RGBA {
|
func Snapshot(a *Apple2) *image.RGBA {
|
||||||
|
isColor := a.isColor
|
||||||
isTextMode := a.io.isSoftSwitchActive(ioFlagText)
|
isTextMode := a.io.isSoftSwitchActive(ioFlagText)
|
||||||
isHiResMode := a.io.isSoftSwitchActive(ioFlagHiRes)
|
isHiResMode := a.io.isSoftSwitchActive(ioFlagHiRes)
|
||||||
isMixMode := a.io.isSoftSwitchActive(ioFlagMixed)
|
isMixMode := a.io.isSoftSwitchActive(ioFlagMixed)
|
||||||
|
@ -26,32 +27,36 @@ func Snapshot(a *Apple2) *image.RGBA {
|
||||||
pageIndex = 1
|
pageIndex = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var lightColor color.Color
|
||||||
|
if isColor {
|
||||||
|
lightColor = color.White
|
||||||
|
} else {
|
||||||
|
// Color for typical Apple ][ period green P1 phosphor monitors
|
||||||
|
// See: https://superuser.com/questions/361297/what-colour-is-the-dark-green-on-old-fashioned-green-screen-computer-displays
|
||||||
|
lightColor = color.RGBA{65, 255, 0, 255}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
var snap *image.RGBA
|
var snap *image.RGBA
|
||||||
if isTextMode {
|
if isTextMode {
|
||||||
// Color for typical Apple ][ period green phosphor monitors
|
snap = snapshotTextMode(a, pageIndex, false, lightColor)
|
||||||
// See: https://superuser.com/questions/361297/what-colour-is-the-dark-green-on-old-fashioned-green-screen-computer-displays
|
|
||||||
p1GreenPhosphorColor := color.RGBA{65, 255, 0, 255}
|
|
||||||
|
|
||||||
snap = snapshotTextMode(a, pageIndex, false, p1GreenPhosphorColor)
|
|
||||||
snap = linesSeparatedFilter(snap)
|
|
||||||
} else {
|
} else {
|
||||||
if isHiResMode {
|
if isHiResMode {
|
||||||
//snap = snapshotHiResModeReferenceMono(a, pageIndex, isMixMode)
|
snap = snapshotHiResModeMonoShift(a, pageIndex, isMixMode, lightColor)
|
||||||
//snap = snapshotHiResModeReferenceColor(a, pageIndex, isMixMode)
|
|
||||||
//snap = snapshotHiResModeReferenceColorSolid(a, pageIndex, isMixMode)
|
|
||||||
snap = snapshotHiResModeMonoShift(a, pageIndex, isMixMode)
|
|
||||||
} else {
|
} else {
|
||||||
// Lo res mode not supported
|
// Lo res mode not supported
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if isMixMode {
|
if isMixMode {
|
||||||
snapText := snapshotTextMode(a, pageIndex, isHiResMode, color.White)
|
snapText := snapshotTextMode(a, pageIndex, isHiResMode, lightColor)
|
||||||
snap = mixSnapshots(snap, snapText)
|
snap = mixSnapshots(snap, snapText)
|
||||||
}
|
}
|
||||||
//snap = filterNTSCColorStatic(snap)
|
if isColor {
|
||||||
snap = filterNTSCColorMoving(false /*blacker*/, snap)
|
snap = filterNTSCColor(false /*blacker*/, snap)
|
||||||
snap = linesSeparatedFilter(snap)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snap = linesSeparatedFilter(snap)
|
||||||
return snap
|
return snap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,37 +37,7 @@ func getGraphLine(a *Apple2, line int, page int) []uint8 {
|
||||||
return memPage[lo : lo+40]
|
return memPage[lo : lo+40]
|
||||||
}
|
}
|
||||||
|
|
||||||
func snapshotHiResModeReferenceMono(a *Apple2, page int, mixedMode bool) *image.RGBA {
|
func snapshotHiResModeMonoShift(a *Apple2, page int, mixedMode bool, light color.Color) *image.RGBA {
|
||||||
// As defined on "Apple II Reference Manual", page 19
|
|
||||||
|
|
||||||
height := graphHeight
|
|
||||||
if mixedMode {
|
|
||||||
height = graphHeightMixed
|
|
||||||
}
|
|
||||||
|
|
||||||
size := image.Rect(0, 0, graphWidth, height)
|
|
||||||
img := image.NewRGBA(size)
|
|
||||||
|
|
||||||
for y := 0; y < height; y++ {
|
|
||||||
bytes := getGraphLine(a, y, page)
|
|
||||||
x := 0
|
|
||||||
for _, b := range bytes {
|
|
||||||
for j := uint(0); j < 7; j++ {
|
|
||||||
bit := (b >> j) & 1
|
|
||||||
colour := color.Black
|
|
||||||
if bit == 1 {
|
|
||||||
colour = color.White
|
|
||||||
}
|
|
||||||
img.Set(x, y, colour)
|
|
||||||
x++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return img
|
|
||||||
}
|
|
||||||
|
|
||||||
func snapshotHiResModeMonoShift(a *Apple2, page int, mixedMode bool) *image.RGBA {
|
|
||||||
// As described in "Undertanding the Apple II", with half pixel shifts
|
// As described in "Undertanding the Apple II", with half pixel shifts
|
||||||
|
|
||||||
height := graphHeight
|
height := graphHeight
|
||||||
|
@ -81,14 +51,14 @@ func snapshotHiResModeMonoShift(a *Apple2, page int, mixedMode bool) *image.RGBA
|
||||||
for y := 0; y < height; y++ {
|
for y := 0; y < height; y++ {
|
||||||
bytes := getGraphLine(a, y, page)
|
bytes := getGraphLine(a, y, page)
|
||||||
x := 0
|
x := 0
|
||||||
previousColour := color.Black
|
var previousColour color.Color = color.Black
|
||||||
for _, b := range bytes {
|
for _, b := range bytes {
|
||||||
shifted := b>>7 == 1
|
shifted := b>>7 == 1
|
||||||
for j := uint(0); j < 7; j++ {
|
for j := uint(0); j < 7; j++ {
|
||||||
bit := (b >> j) & 1
|
bit := (b >> j) & 1
|
||||||
colour := color.Black
|
colour := light
|
||||||
if bit == 1 {
|
if bit == 0 {
|
||||||
colour = color.White
|
colour = color.Black
|
||||||
}
|
}
|
||||||
|
|
||||||
if shifted {
|
if shifted {
|
||||||
|
|
|
@ -53,31 +53,7 @@ func getNTSCColorMap() []color.Color {
|
||||||
return colorMap
|
return colorMap
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterNTSCColorStatic(in *image.RGBA) *image.RGBA {
|
func filterNTSCColor(blacker bool, in *image.RGBA) *image.RGBA {
|
||||||
colorMap := getNTSCColorMap()
|
|
||||||
|
|
||||||
b := in.Bounds()
|
|
||||||
size := image.Rect(0, 0, b.Dx()/4, b.Dy())
|
|
||||||
out := image.NewRGBA(size)
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
|
||||||
for x := b.Min.X; x < b.Max.X; x += 4 {
|
|
||||||
v := 0
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
cIn := in.At(x+i, y)
|
|
||||||
r, _, _, _ := cIn.RGBA()
|
|
||||||
v = v << 1
|
|
||||||
if r != 0 {
|
|
||||||
v++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cOut := colorMap[v]
|
|
||||||
out.Set(x/4, y, cOut)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func filterNTSCColorMoving(blacker bool, in *image.RGBA) *image.RGBA {
|
|
||||||
colorMap := getNTSCColorMap()
|
colorMap := getNTSCColorMap()
|
||||||
|
|
||||||
b := in.Bounds()
|
b := in.Bounds()
|
||||||
|
|
|
@ -91,6 +91,8 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
|
||||||
// Control of the emulator
|
// Control of the emulator
|
||||||
case sdl.K_F5:
|
case sdl.K_F5:
|
||||||
k.a.SendCommand(apple2.CommandToggleSpeed)
|
k.a.SendCommand(apple2.CommandToggleSpeed)
|
||||||
|
case sdl.K_F6:
|
||||||
|
k.a.SendCommand(apple2.CommandToggleColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Missing values 91 to 95. Usually control for [\]^_
|
// Missing values 91 to 95. Usually control for [\]^_
|
||||||
|
|
9
main.go
9
main.go
|
@ -22,7 +22,7 @@ func main() {
|
||||||
cpuClock := flag.Float64(
|
cpuClock := flag.Float64(
|
||||||
"mhz",
|
"mhz",
|
||||||
apple2.CpuClockMhz,
|
apple2.CpuClockMhz,
|
||||||
"cpu speed in Mhz, use 0 for full speed")
|
"cpu speed in Mhz, use 0 for full speed. Use F5 to toggle.")
|
||||||
charRomFile := flag.String(
|
charRomFile := flag.String(
|
||||||
"charRom",
|
"charRom",
|
||||||
"apple2/romdumps/Apple2rev7CharGen.rom",
|
"apple2/romdumps/Apple2rev7CharGen.rom",
|
||||||
|
@ -35,6 +35,11 @@ func main() {
|
||||||
"stdout",
|
"stdout",
|
||||||
false,
|
false,
|
||||||
"show the text screen on the standard output")
|
"show the text screen on the standard output")
|
||||||
|
mono := flag.Bool(
|
||||||
|
"mono",
|
||||||
|
false,
|
||||||
|
"emulate a green phosphor monitor instead of a NTSC color TV. Use F6 to toggle.",
|
||||||
|
)
|
||||||
panicSS := flag.Bool(
|
panicSS := flag.Bool(
|
||||||
"panicss",
|
"panicss",
|
||||||
false,
|
false,
|
||||||
|
@ -53,7 +58,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
log := false
|
log := false
|
||||||
a := apple2.NewApple2(*romFile, *charRomFile, *cpuClock, *panicSS)
|
a := apple2.NewApple2(*romFile, *charRomFile, *cpuClock, !*mono, *panicSS)
|
||||||
a.AddDisk2(*disk2RomFile, *diskImage)
|
a.AddDisk2(*disk2RomFile, *diskImage)
|
||||||
if *useSdl {
|
if *useSdl {
|
||||||
a.ConfigureStdConsole(false, *stdoutScreen)
|
a.ConfigureStdConsole(false, *stdoutScreen)
|
||||||
|
|
Loading…
Reference in New Issue