Show alt text character map

This commit is contained in:
Iván Izaguirre 2021-03-02 00:19:18 +01:00
parent e49bef397b
commit 9d040fa58b
9 changed files with 41 additions and 28 deletions

View File

@ -159,6 +159,7 @@ Line:
- F7: Show the video mode and a split screen with the views for NTSC color TV, page 1, page 2 and extra info.
- F10: Cycle character generator code pages. Only if the character generator ROM has more than one 2Kb page.
- Ctrl-F10: Show the charater map for the current character generator page.
- Shift-F10: When showing the character map, use altText.
- F11: Toggle on and off the trace to console of the CPU execution
- F12: Save a screen snapshot to a file `snapshot.png`
- Pause: Pause the emulation

View File

@ -91,7 +91,7 @@ func sdlRun(a *izapple2.Apple2) {
if !a.IsPaused() {
var img *image.RGBA
if kp.showCharGen {
img = screen.SnapshotCharacterGenerator(a)
img = screen.SnapshotCharacterGenerator(a, kp.showAltText)
window.SetTitle(fmt.Sprintf("%v character map", a.Name))
} else if kp.showPages {
img = screen.SnapshotParts(a, screen.ScreenModeNTSC)

View File

@ -14,6 +14,7 @@ type sdlKeyboard struct {
showPages bool
showCharGen bool
showAltText bool
}
func newSDLKeyBoard(a *izapple2.Apple2) *sdlKeyboard {
@ -43,6 +44,7 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
key := keyEvent.Keysym
ctrl := key.Mod&sdl.KMOD_CTRL != 0
shift := key.Mod&sdl.KMOD_SHIFT != 0
if ctrl {
if key.Sym >= 'a' && key.Sym <= 'z' {
@ -103,6 +105,8 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
case sdl.K_F10:
if ctrl {
k.showCharGen = !k.showCharGen
} else if shift {
k.showAltText = !k.showAltText
} else {
k.a.SendCommand(izapple2.CommandNextCharGenPage)
}

View File

@ -40,6 +40,7 @@ func snapshotByMode(vs VideoSource, videoMode uint16, screenMode int) *image.RGB
videoBase := videoMode & VideoBaseMask
mixMode := videoMode & VideoMixTextMask
isSecondPage := (videoMode & VideoSecondPage) != 0
isAltText := (videoMode & VideoAltText) != 0
var lightColor color.Color = color.White
if screenMode == ScreenModeGreen {
@ -53,13 +54,13 @@ func snapshotByMode(vs VideoSource, videoMode uint16, screenMode int) *image.RGB
var ntscMask *image.Alpha
switch videoBase {
case VideoText40:
snap = snapshotText40(vs, isSecondPage, lightColor)
snap = snapshotText40(vs, isSecondPage, isAltText, lightColor)
applyNTSCFilter = false
case VideoText80:
snap = snapshotText80(vs, isSecondPage, lightColor)
snap = snapshotText80(vs, isSecondPage, isAltText, lightColor)
applyNTSCFilter = false
case VideoText40RGB:
snap = snapshotText40RGB(vs, isSecondPage)
snap = snapshotText40RGB(vs, isSecondPage, isAltText)
applyNTSCFilter = false
case VideoGR:
snap = snapshotLoRes(vs, isSecondPage, lightColor)
@ -90,11 +91,11 @@ func snapshotByMode(vs VideoSource, videoMode uint16, screenMode int) *image.RGB
applyNTSCFilter := screenMode != ScreenModeGreen
switch mixMode {
case VideoMixText40:
bottom = snapshotText40(vs, isSecondPage, lightColor)
bottom = snapshotText40(vs, isSecondPage, isAltText, lightColor)
case VideoMixText80:
bottom = snapshotText80(vs, isSecondPage, lightColor)
bottom = snapshotText80(vs, isSecondPage, isAltText, lightColor)
case VideoMixText40RGB:
bottom = snapshotText40RGB(vs, isSecondPage)
bottom = snapshotText40RGB(vs, isSecondPage, isAltText)
applyNTSCFilter = false
}
if applyNTSCFilter {

View File

@ -79,6 +79,10 @@ func VideoModeName(vs VideoSource) string {
name += "-PAGE2"
}
if (videoMode & VideoAltText) != 0 {
name += "-ALT"
}
switch mixMode {
case VideoMixText40:
name += "-MIX40"
@ -130,7 +134,7 @@ func doubleWidthFilter(in *image.RGBA) *image.RGBA {
}
// SnapshotCharacterGenerator shows the current character set
func SnapshotCharacterGenerator(vs VideoSource) *image.RGBA {
func SnapshotCharacterGenerator(vs VideoSource, isAltText bool) *image.RGBA {
text := make([]uint8, textLines*text40Columns)
for l := 0; l < textLines; l++ {
for c := 0; c < text40Columns; c++ {
@ -144,5 +148,5 @@ func SnapshotCharacterGenerator(vs VideoSource) *image.RGBA {
}
}
return renderText(vs, text, nil, color.White)
return renderText(vs, text, isAltText, nil, color.White)
}

View File

@ -114,7 +114,7 @@ func (ts *TestScenario) GetVideoMemory(secondPage bool, ext bool) []uint8 {
}
// GetCharacterPixel returns the pixel as output by the character generator
func (ts *TestScenario) GetCharacterPixel(char uint8, rowInChar int, colInChar int) bool {
func (ts *TestScenario) GetCharacterPixel(char uint8, rowInChar int, colInChar int, isAltText bool, isFlashedFrame bool) bool {
// We don't have a character generator. We will return a square or blank for spaces
if char&0x3f == 0x20 {
return false // Space char

View File

@ -3,6 +3,7 @@ package screen
import (
"image"
"image/color"
"time"
)
const (
@ -12,25 +13,25 @@ const (
textLines = 24
)
func snapshotText40(vs VideoSource, isSecondPage bool, light color.Color) *image.RGBA {
func snapshotText40(vs VideoSource, isSecondPage bool, isAltText bool, light color.Color) *image.RGBA {
text := getTextFromMemory(vs, isSecondPage, false)
return renderText(vs, text, nil /*colorMap*/, light)
return renderText(vs, text, isAltText, nil /*colorMap*/, light)
}
func snapshotText80(vs VideoSource, isSecondPage bool, light color.Color) *image.RGBA {
func snapshotText80(vs VideoSource, isSecondPage bool, isAltText bool, light color.Color) *image.RGBA {
text := getText80FromMemory(vs, isSecondPage)
return renderText(vs, text, nil /*colorMap*/, light)
return renderText(vs, text, isAltText, nil /*colorMap*/, light)
}
func snapshotText40RGB(vs VideoSource, isSecondPage bool) *image.RGBA {
func snapshotText40RGB(vs VideoSource, isSecondPage bool, isAltText bool) *image.RGBA {
text := getTextFromMemory(vs, isSecondPage, false)
colorMap := getTextFromMemory(vs, isSecondPage, true)
return renderText(vs, text, colorMap, nil)
return renderText(vs, text, isAltText, colorMap, nil)
}
func snapshotText40RGBColors(vs VideoSource, isSecondPage bool) *image.RGBA {
colorMap := getTextFromMemory(vs, isSecondPage, true)
return renderText(vs, nil /*text*/, colorMap, nil)
return renderText(vs, nil /*text*/, false, colorMap, nil)
}
func getText80FromMemory(vs VideoSource, isSecondPage bool) []uint8 {
@ -77,7 +78,10 @@ func getRGBTextColor(pixel bool, colorKey uint8) color.Color {
}
func renderText(vs VideoSource, text []uint8, colorMap []uint8, light color.Color) *image.RGBA {
func renderText(vs VideoSource, text []uint8, isAltText bool, colorMap []uint8, light color.Color) *image.RGBA {
// Flash mode is 2Hz (host time)
isFlashedFrame := time.Now().Nanosecond() > (1 * 1000 * 1000 * 1000 / 2)
columns := len(text) / textLines
if text == nil {
columns = text40Columns
@ -102,7 +106,7 @@ func renderText(vs VideoSource, text []uint8, colorMap []uint8, light color.Colo
char = 79 + 128 // Debug screen filed with O
}
pixel := vs.GetCharacterPixel(char, rowInChar, colInChar)
pixel := vs.GetCharacterPixel(char, rowInChar, colInChar, isAltText, isFlashedFrame)
var colour color.Color
if colorMap != nil {

View File

@ -28,6 +28,7 @@ const (
const (
VideoModifiersMask uint16 = 0xf000
VideoSecondPage uint16 = 0x1000
VideoAltText uint16 = 0x2000
)
// VideoSource provides the info to build the video output
@ -39,7 +40,7 @@ type VideoSource interface {
// GetVideoMemory returns a slice to the video memory pages
GetVideoMemory(secondPage bool, ext bool) []uint8
// GetCharactePixel returns the pixel as output by the character generator
GetCharacterPixel(char uint8, rowInChar int, colInChar int) bool
GetCharacterPixel(char uint8, rowInChar int, colInChar int, isAltText bool, isFlashedFrame bool) bool
// GetSuperVideoMemory returns a slice to the SHR video memory
GetSuperVideoMemory() []uint8
}

View File

@ -1,8 +1,6 @@
package izapple2
import (
"time"
"github.com/ivanizag/izapple2/screen"
)
@ -34,6 +32,8 @@ func (a *Apple2) GetCurrentVideoMode() uint16 {
isRGB160Mode := isDoubleResMode && rgbFlag1 && !rgbFlag2
isMixMode := a.io.isSoftSwitchActive(ioFlagMixed)
isSecondPage := a.io.isSoftSwitchActive(ioFlagSecondPage) && !a.mmu.store80Active
isAltText := a.isApple2e && a.io.isSoftSwitchActive(ioFlagAltChar)
var mode uint16
if isSuperHighResMode {
@ -76,10 +76,12 @@ func (a *Apple2) GetCurrentVideoMode() uint16 {
mode |= screen.VideoMixText40
}
}
isSecondPage := a.io.isSoftSwitchActive(ioFlagSecondPage) && !a.mmu.store80Active
if isSecondPage {
mode |= screen.VideoSecondPage
}
if isAltText {
mode |= screen.VideoAltText
}
return mode
}
@ -111,11 +113,7 @@ func (a *Apple2) GetSuperVideoMemory() []uint8 {
}
// GetCharacterPixel returns the pixel as output by the character generator
func (a *Apple2) GetCharacterPixel(char uint8, rowInChar int, colInChar int) bool {
// Flash mode is 2Hz (host time)
isFlashedFrame := time.Now().Nanosecond() > (1 * 1000 * 1000 * 1000 / 2)
isAltText := a.io.isSoftSwitchActive(ioFlagAltChar)
func (a *Apple2) GetCharacterPixel(char uint8, rowInChar int, colInChar int, isAltText bool, isFlashedFrame bool) bool {
var pixel bool
if a.isApple2e {
vid6 := (char & 0x40) != 0