mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-12-21 18:29:45 +00:00
UI to select screen modes
This commit is contained in:
parent
a9b8fe76df
commit
4ec3bff858
@ -191,8 +191,6 @@ Only valid on SDL mode
|
||||
cpu speed in Mhz, use 0 for full speed. Use F5 to toggle. (default 1.0227142857142857)
|
||||
-model string
|
||||
set base model. Models available 2plus, 2e, 2enh, base64a (default "2enh")
|
||||
-mono
|
||||
emulate a green phosphor monitor instead of a NTSC color TV. Use F6 to toggle.
|
||||
-nsc int
|
||||
add a DS1216 No-Slot-Clock on the main ROM (use 0) or a slot ROM. -1 for none (default -1)
|
||||
-panicSS
|
||||
|
@ -18,7 +18,6 @@ type Apple2 struct {
|
||||
isApple2e bool
|
||||
commandChannel chan int
|
||||
cycleDurationNs float64 // Current speed. Inverse of the cpu clock in Ghz
|
||||
isColor bool
|
||||
fastMode bool
|
||||
fastRequestsCounter int
|
||||
profile bool
|
||||
@ -126,8 +125,6 @@ const (
|
||||
CommandToggleSpeed = iota + 1
|
||||
// CommandShowSpeed toggles printinf the current freq in Mhz
|
||||
CommandShowSpeed
|
||||
// CommandToggleColor toggles between NTSC color TV and Green phospor monitor
|
||||
CommandToggleColor
|
||||
// CommandDumpDebugInfo dumps useful info
|
||||
CommandDumpDebugInfo
|
||||
// CommandNextCharGenPage cycles the CharGen page if several
|
||||
@ -159,8 +156,6 @@ func (a *Apple2) executeCommand(command int) {
|
||||
}
|
||||
case CommandShowSpeed:
|
||||
a.showSpeed = !a.showSpeed
|
||||
case CommandToggleColor:
|
||||
a.isColor = !a.isColor
|
||||
case CommandDumpDebugInfo:
|
||||
a.dumpDebugInfo()
|
||||
case CommandNextCharGenPage:
|
||||
|
@ -15,9 +15,8 @@ func newApple2() *Apple2 {
|
||||
return &a
|
||||
}
|
||||
|
||||
func (a *Apple2) setup(isColor bool, clockMhz float64, fastMode bool, traceMLI bool) {
|
||||
func (a *Apple2) setup(clockMhz float64, fastMode bool, traceMLI bool) {
|
||||
a.commandChannel = make(chan int, 100)
|
||||
a.isColor = isColor
|
||||
a.fastMode = fastMode
|
||||
if traceMLI {
|
||||
a.traceMLI = newTraceProDOS(a)
|
||||
|
@ -81,10 +81,6 @@ func MainApple() *Apple2 {
|
||||
"nsc",
|
||||
-1,
|
||||
"add a DS1216 No-Slot-Clock on the main ROM (use 0) or a slot ROM. -1 for none")
|
||||
mono := flag.Bool(
|
||||
"mono",
|
||||
false,
|
||||
"emulate a green phosphor monitor instead of a NTSC color TV. Use F6 to toggle.")
|
||||
rgbCard := flag.Bool(
|
||||
"rgb",
|
||||
true,
|
||||
@ -155,7 +151,7 @@ func MainApple() *Apple2 {
|
||||
}
|
||||
|
||||
a := newApple2()
|
||||
a.setup(!*mono, *cpuClock, *fastDisk, *traceMLI)
|
||||
a.setup(*cpuClock, *fastDisk, *traceMLI)
|
||||
a.io.setTrace(*traceSS)
|
||||
a.io.setTraceRegistrations(*traceSSReg)
|
||||
a.io.setPanicNotImplemented(*panicSS)
|
||||
|
@ -88,7 +88,7 @@ func sdlRun(a *izapple2.Apple2) {
|
||||
img = a.SnapshotParts()
|
||||
window.SetTitle(fmt.Sprintf("%v %v %vx%v", a.Name, a.VideoModeName(), img.Rect.Dx()/2, img.Rect.Dy()/2))
|
||||
} else {
|
||||
img = a.Snapshot()
|
||||
img = a.Snapshot(izapple2.ScreenModeNTSC)
|
||||
}
|
||||
if img != nil {
|
||||
surface, err := sdl.CreateRGBSurfaceFrom(unsafe.Pointer(&img.Pix[0]),
|
||||
|
@ -94,8 +94,6 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
|
||||
} else {
|
||||
k.a.SendCommand(izapple2.CommandToggleSpeed)
|
||||
}
|
||||
case sdl.K_F6:
|
||||
k.a.SendCommand(izapple2.CommandToggleColor)
|
||||
case sdl.K_F7:
|
||||
k.showPages = !k.showPages
|
||||
case sdl.K_F9:
|
||||
@ -106,7 +104,7 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
|
||||
k.a.SendCommand(izapple2.CommandToggleCPUTrace)
|
||||
case sdl.K_F12:
|
||||
case sdl.K_PRINTSCREEN:
|
||||
err := izapple2.SaveSnapshot(k.a, "snapshot.png")
|
||||
err := izapple2.SaveSnapshot(k.a, izapple2.ScreenModeNTSC, "snapshot.png")
|
||||
if err != nil {
|
||||
fmt.Printf("Error saving snapshoot: %v.\n.", err)
|
||||
} else {
|
||||
|
36
screen.go
36
screen.go
@ -40,6 +40,15 @@ const (
|
||||
videoSecondPage uint16 = 0x1000
|
||||
)
|
||||
|
||||
const (
|
||||
// ScreenModeGreen to render as a green phosphor monitor
|
||||
ScreenModeGreen = iota
|
||||
// ScreenModePlain to render in color with filled areas
|
||||
ScreenModePlain
|
||||
//ScreenModeNTSC shows spaces between pixels
|
||||
ScreenModeNTSC
|
||||
)
|
||||
|
||||
func getCurrentVideoMode(a *Apple2) uint16 {
|
||||
isTextMode := a.io.isSoftSwitchActive(ioFlagText)
|
||||
isHiResMode := a.io.isSoftSwitchActive(ioFlagHiRes)
|
||||
@ -106,22 +115,19 @@ func getCurrentVideoMode(a *Apple2) uint16 {
|
||||
return mode
|
||||
}
|
||||
|
||||
func snapshotByMode(a *Apple2, videoMode uint16) *image.RGBA {
|
||||
func snapshotByMode(a *Apple2, videoMode uint16, screenMode int) *image.RGBA {
|
||||
videoBase := videoMode & videoBaseMask
|
||||
mixMode := videoMode & videoMixTextMask
|
||||
isSecondPage := (videoMode & videoSecondPage) != 0
|
||||
|
||||
var lightColor color.Color
|
||||
if a.isColor {
|
||||
lightColor = color.White
|
||||
} else {
|
||||
var lightColor color.Color = color.White
|
||||
if screenMode == ScreenModeGreen {
|
||||
// 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}
|
||||
|
||||
}
|
||||
|
||||
applyNTSCFilter := a.isColor
|
||||
applyNTSCFilter := screenMode != ScreenModeGreen
|
||||
var snap *image.RGBA
|
||||
var ntscMask *image.Alpha
|
||||
switch videoBase {
|
||||
@ -155,12 +161,12 @@ func snapshotByMode(a *Apple2, videoMode uint16) *image.RGBA {
|
||||
}
|
||||
|
||||
if applyNTSCFilter {
|
||||
snap = filterNTSCColor(snap, ntscMask)
|
||||
snap = filterNTSCColor(snap, ntscMask, screenMode)
|
||||
}
|
||||
|
||||
if mixMode != 0 {
|
||||
var bottom *image.RGBA
|
||||
applyNTSCFilter := a.isColor
|
||||
applyNTSCFilter := screenMode != ScreenModeGreen
|
||||
switch mixMode {
|
||||
case videoMixText40:
|
||||
bottom = snapshotText40Mode(a, isSecondPage, lightColor)
|
||||
@ -171,7 +177,7 @@ func snapshotByMode(a *Apple2, videoMode uint16) *image.RGBA {
|
||||
applyNTSCFilter = false
|
||||
}
|
||||
if applyNTSCFilter {
|
||||
bottom = filterNTSCColor(bottom, ntscMask)
|
||||
bottom = filterNTSCColor(bottom, ntscMask, screenMode)
|
||||
}
|
||||
snap = mixSnapshots(snap, bottom)
|
||||
}
|
||||
@ -180,11 +186,11 @@ func snapshotByMode(a *Apple2, videoMode uint16) *image.RGBA {
|
||||
}
|
||||
|
||||
// Snapshot the currently visible screen
|
||||
func (a *Apple2) Snapshot() *image.RGBA {
|
||||
func (a *Apple2) Snapshot(screenMode int) *image.RGBA {
|
||||
videoMode := getCurrentVideoMode(a)
|
||||
snap := snapshotByMode(a, videoMode)
|
||||
snap := snapshotByMode(a, videoMode, screenMode)
|
||||
|
||||
if snap.Bounds().Dy() == hiResHeight {
|
||||
if screenMode == ScreenModeNTSC && snap.Bounds().Dy() == hiResHeight {
|
||||
// Apply the filter to regular CRT snapshots with 192 lines. Not to SHR
|
||||
snap = linesSeparatedFilter(snap)
|
||||
}
|
||||
@ -207,8 +213,8 @@ func mixSnapshots(top, bottom *image.RGBA) *image.RGBA {
|
||||
}
|
||||
|
||||
// SaveSnapshot saves a snapshot of the screen to a png file
|
||||
func SaveSnapshot(a *Apple2, filename string) error {
|
||||
img := a.Snapshot()
|
||||
func SaveSnapshot(a *Apple2, screenMode int, filename string) error {
|
||||
img := a.Snapshot(screenMode)
|
||||
img = squarishPixelsFilter(img)
|
||||
|
||||
f, err := os.Create(filename)
|
||||
|
@ -12,9 +12,9 @@ func (a *Apple2) SnapshotParts() *image.RGBA {
|
||||
mixMode := videoMode & videoMixTextMask
|
||||
modifiers := videoMode & videoModifiersMask
|
||||
|
||||
snapScreen := snapshotByMode(a, videoMode)
|
||||
snapPage1 := snapshotByMode(a, videoMode&^videoSecondPage)
|
||||
snapPage2 := snapshotByMode(a, videoMode|videoSecondPage)
|
||||
snapScreen := snapshotByMode(a, videoMode, ScreenModePlain)
|
||||
snapPage1 := snapshotByMode(a, videoMode&^videoSecondPage, ScreenModePlain)
|
||||
snapPage2 := snapshotByMode(a, videoMode|videoSecondPage, ScreenModePlain)
|
||||
var snapAux *image.RGBA
|
||||
|
||||
/*
|
||||
@ -28,11 +28,11 @@ func (a *Apple2) SnapshotParts() *image.RGBA {
|
||||
} else {
|
||||
switch mixMode {
|
||||
case videoMixText80:
|
||||
snapAux = snapshotByMode(a, videoText80|modifiers)
|
||||
snapAux = snapshotByMode(a, videoText80|modifiers, ScreenModePlain)
|
||||
case videoMixText40RGB:
|
||||
snapAux = snapshotByMode(a, videoText40RGB|modifiers)
|
||||
snapAux = snapshotByMode(a, videoText40RGB|modifiers, ScreenModePlain)
|
||||
default:
|
||||
snapAux = snapshotByMode(a, videoText40|modifiers)
|
||||
snapAux = snapshotByMode(a, videoText40|modifiers, ScreenModePlain)
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,18 +46,14 @@ func (a *Apple2) VideoModeName() string {
|
||||
mixMode := videoMode & videoMixTextMask
|
||||
|
||||
var name string
|
||||
applyNTSCFilter := a.isColor
|
||||
|
||||
switch videoBase {
|
||||
case videoText40:
|
||||
name = "TEXT40COL"
|
||||
applyNTSCFilter = false
|
||||
case videoText80:
|
||||
name = "TEXT80COL"
|
||||
applyNTSCFilter = false
|
||||
case videoText40RGB:
|
||||
name = "TEXT40COLRGB"
|
||||
applyNTSCFilter = false
|
||||
case videoGR:
|
||||
name = "GR"
|
||||
case videoDGR:
|
||||
@ -68,14 +64,12 @@ func (a *Apple2) VideoModeName() string {
|
||||
name = "DHGR"
|
||||
case videoMono560:
|
||||
name = "Mono560"
|
||||
applyNTSCFilter = false
|
||||
case videoRGBMix:
|
||||
name = "RGMMIX"
|
||||
case videoRGB160:
|
||||
name = "RGB160"
|
||||
case videoSHR:
|
||||
name = "SHR"
|
||||
applyNTSCFilter = false
|
||||
default:
|
||||
name = "Unknown video mode"
|
||||
}
|
||||
@ -93,9 +87,6 @@ func (a *Apple2) VideoModeName() string {
|
||||
name += "-MIX40RGB"
|
||||
}
|
||||
|
||||
if applyNTSCFilter {
|
||||
name += "-NTSC"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
|
@ -49,14 +49,16 @@ var rgbColorMap = [16]color.Color{
|
||||
color.RGBA{255, 255, 255, 255}, // White
|
||||
}
|
||||
|
||||
func filterNTSCColor(in *image.RGBA, mask *image.Alpha) *image.RGBA {
|
||||
func filterNTSCColor(in *image.RGBA, mask *image.Alpha, screenMode int) *image.RGBA {
|
||||
colorMap := ntscColorMap // or rgbColorMap
|
||||
attenuatedColorMap := make([]color.Color, 16, 16)
|
||||
for i := 0; i < len(colorMap); i++ {
|
||||
r, g, b, _ := colorMap[i].RGBA()
|
||||
attenuatedColorMap[i] = color.RGBA64{
|
||||
uint16(r / 2), uint16(g / 2), uint16(b / 2),
|
||||
65535,
|
||||
attenuatedColorMap := ntscColorMap
|
||||
if screenMode == ScreenModeNTSC {
|
||||
for i := 0; i < len(colorMap); i++ {
|
||||
r, g, b, _ := colorMap[i].RGBA()
|
||||
attenuatedColorMap[i] = color.RGBA64{
|
||||
uint16(r / 2), uint16(g / 2), uint16(b / 2),
|
||||
65535,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user