F6 to toggle mono/color modes

This commit is contained in:
Ivan Izaguirre 2019-05-05 13:25:45 +02:00
parent 9247ae02af
commit 6fca02da6b
6 changed files with 41 additions and 77 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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 [\]^_

View File

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