mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-01-02 20:29:44 +00:00
Show alt text character map
This commit is contained in:
parent
e49bef397b
commit
9d040fa58b
@ -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.
|
- 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.
|
- 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.
|
- 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
|
- F11: Toggle on and off the trace to console of the CPU execution
|
||||||
- F12: Save a screen snapshot to a file `snapshot.png`
|
- F12: Save a screen snapshot to a file `snapshot.png`
|
||||||
- Pause: Pause the emulation
|
- Pause: Pause the emulation
|
||||||
|
@ -91,7 +91,7 @@ func sdlRun(a *izapple2.Apple2) {
|
|||||||
if !a.IsPaused() {
|
if !a.IsPaused() {
|
||||||
var img *image.RGBA
|
var img *image.RGBA
|
||||||
if kp.showCharGen {
|
if kp.showCharGen {
|
||||||
img = screen.SnapshotCharacterGenerator(a)
|
img = screen.SnapshotCharacterGenerator(a, kp.showAltText)
|
||||||
window.SetTitle(fmt.Sprintf("%v character map", a.Name))
|
window.SetTitle(fmt.Sprintf("%v character map", a.Name))
|
||||||
} else if kp.showPages {
|
} else if kp.showPages {
|
||||||
img = screen.SnapshotParts(a, screen.ScreenModeNTSC)
|
img = screen.SnapshotParts(a, screen.ScreenModeNTSC)
|
||||||
|
@ -14,6 +14,7 @@ type sdlKeyboard struct {
|
|||||||
|
|
||||||
showPages bool
|
showPages bool
|
||||||
showCharGen bool
|
showCharGen bool
|
||||||
|
showAltText bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSDLKeyBoard(a *izapple2.Apple2) *sdlKeyboard {
|
func newSDLKeyBoard(a *izapple2.Apple2) *sdlKeyboard {
|
||||||
@ -43,6 +44,7 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
|
|||||||
|
|
||||||
key := keyEvent.Keysym
|
key := keyEvent.Keysym
|
||||||
ctrl := key.Mod&sdl.KMOD_CTRL != 0
|
ctrl := key.Mod&sdl.KMOD_CTRL != 0
|
||||||
|
shift := key.Mod&sdl.KMOD_SHIFT != 0
|
||||||
|
|
||||||
if ctrl {
|
if ctrl {
|
||||||
if key.Sym >= 'a' && key.Sym <= 'z' {
|
if key.Sym >= 'a' && key.Sym <= 'z' {
|
||||||
@ -103,6 +105,8 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
|
|||||||
case sdl.K_F10:
|
case sdl.K_F10:
|
||||||
if ctrl {
|
if ctrl {
|
||||||
k.showCharGen = !k.showCharGen
|
k.showCharGen = !k.showCharGen
|
||||||
|
} else if shift {
|
||||||
|
k.showAltText = !k.showAltText
|
||||||
} else {
|
} else {
|
||||||
k.a.SendCommand(izapple2.CommandNextCharGenPage)
|
k.a.SendCommand(izapple2.CommandNextCharGenPage)
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ func snapshotByMode(vs VideoSource, videoMode uint16, screenMode int) *image.RGB
|
|||||||
videoBase := videoMode & VideoBaseMask
|
videoBase := videoMode & VideoBaseMask
|
||||||
mixMode := videoMode & VideoMixTextMask
|
mixMode := videoMode & VideoMixTextMask
|
||||||
isSecondPage := (videoMode & VideoSecondPage) != 0
|
isSecondPage := (videoMode & VideoSecondPage) != 0
|
||||||
|
isAltText := (videoMode & VideoAltText) != 0
|
||||||
|
|
||||||
var lightColor color.Color = color.White
|
var lightColor color.Color = color.White
|
||||||
if screenMode == ScreenModeGreen {
|
if screenMode == ScreenModeGreen {
|
||||||
@ -53,13 +54,13 @@ func snapshotByMode(vs VideoSource, videoMode uint16, screenMode int) *image.RGB
|
|||||||
var ntscMask *image.Alpha
|
var ntscMask *image.Alpha
|
||||||
switch videoBase {
|
switch videoBase {
|
||||||
case VideoText40:
|
case VideoText40:
|
||||||
snap = snapshotText40(vs, isSecondPage, lightColor)
|
snap = snapshotText40(vs, isSecondPage, isAltText, lightColor)
|
||||||
applyNTSCFilter = false
|
applyNTSCFilter = false
|
||||||
case VideoText80:
|
case VideoText80:
|
||||||
snap = snapshotText80(vs, isSecondPage, lightColor)
|
snap = snapshotText80(vs, isSecondPage, isAltText, lightColor)
|
||||||
applyNTSCFilter = false
|
applyNTSCFilter = false
|
||||||
case VideoText40RGB:
|
case VideoText40RGB:
|
||||||
snap = snapshotText40RGB(vs, isSecondPage)
|
snap = snapshotText40RGB(vs, isSecondPage, isAltText)
|
||||||
applyNTSCFilter = false
|
applyNTSCFilter = false
|
||||||
case VideoGR:
|
case VideoGR:
|
||||||
snap = snapshotLoRes(vs, isSecondPage, lightColor)
|
snap = snapshotLoRes(vs, isSecondPage, lightColor)
|
||||||
@ -90,11 +91,11 @@ func snapshotByMode(vs VideoSource, videoMode uint16, screenMode int) *image.RGB
|
|||||||
applyNTSCFilter := screenMode != ScreenModeGreen
|
applyNTSCFilter := screenMode != ScreenModeGreen
|
||||||
switch mixMode {
|
switch mixMode {
|
||||||
case VideoMixText40:
|
case VideoMixText40:
|
||||||
bottom = snapshotText40(vs, isSecondPage, lightColor)
|
bottom = snapshotText40(vs, isSecondPage, isAltText, lightColor)
|
||||||
case VideoMixText80:
|
case VideoMixText80:
|
||||||
bottom = snapshotText80(vs, isSecondPage, lightColor)
|
bottom = snapshotText80(vs, isSecondPage, isAltText, lightColor)
|
||||||
case VideoMixText40RGB:
|
case VideoMixText40RGB:
|
||||||
bottom = snapshotText40RGB(vs, isSecondPage)
|
bottom = snapshotText40RGB(vs, isSecondPage, isAltText)
|
||||||
applyNTSCFilter = false
|
applyNTSCFilter = false
|
||||||
}
|
}
|
||||||
if applyNTSCFilter {
|
if applyNTSCFilter {
|
||||||
|
@ -79,6 +79,10 @@ func VideoModeName(vs VideoSource) string {
|
|||||||
name += "-PAGE2"
|
name += "-PAGE2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (videoMode & VideoAltText) != 0 {
|
||||||
|
name += "-ALT"
|
||||||
|
}
|
||||||
|
|
||||||
switch mixMode {
|
switch mixMode {
|
||||||
case VideoMixText40:
|
case VideoMixText40:
|
||||||
name += "-MIX40"
|
name += "-MIX40"
|
||||||
@ -130,7 +134,7 @@ func doubleWidthFilter(in *image.RGBA) *image.RGBA {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SnapshotCharacterGenerator shows the current character set
|
// 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)
|
text := make([]uint8, textLines*text40Columns)
|
||||||
for l := 0; l < textLines; l++ {
|
for l := 0; l < textLines; l++ {
|
||||||
for c := 0; c < text40Columns; c++ {
|
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)
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ func (ts *TestScenario) GetVideoMemory(secondPage bool, ext bool) []uint8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCharacterPixel returns the pixel as output by the character generator
|
// 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
|
// We don't have a character generator. We will return a square or blank for spaces
|
||||||
if char&0x3f == 0x20 {
|
if char&0x3f == 0x20 {
|
||||||
return false // Space char
|
return false // Space char
|
||||||
|
@ -3,6 +3,7 @@ package screen
|
|||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -12,25 +13,25 @@ const (
|
|||||||
textLines = 24
|
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)
|
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)
|
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)
|
text := getTextFromMemory(vs, isSecondPage, false)
|
||||||
colorMap := getTextFromMemory(vs, isSecondPage, true)
|
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 {
|
func snapshotText40RGBColors(vs VideoSource, isSecondPage bool) *image.RGBA {
|
||||||
colorMap := getTextFromMemory(vs, isSecondPage, true)
|
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 {
|
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
|
columns := len(text) / textLines
|
||||||
if text == nil {
|
if text == nil {
|
||||||
columns = text40Columns
|
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
|
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
|
var colour color.Color
|
||||||
if colorMap != nil {
|
if colorMap != nil {
|
||||||
|
@ -28,6 +28,7 @@ const (
|
|||||||
const (
|
const (
|
||||||
VideoModifiersMask uint16 = 0xf000
|
VideoModifiersMask uint16 = 0xf000
|
||||||
VideoSecondPage uint16 = 0x1000
|
VideoSecondPage uint16 = 0x1000
|
||||||
|
VideoAltText uint16 = 0x2000
|
||||||
)
|
)
|
||||||
|
|
||||||
// VideoSource provides the info to build the video output
|
// 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 returns a slice to the video memory pages
|
||||||
GetVideoMemory(secondPage bool, ext bool) []uint8
|
GetVideoMemory(secondPage bool, ext bool) []uint8
|
||||||
// GetCharactePixel returns the pixel as output by the character generator
|
// 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 returns a slice to the SHR video memory
|
||||||
GetSuperVideoMemory() []uint8
|
GetSuperVideoMemory() []uint8
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package izapple2
|
package izapple2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/ivanizag/izapple2/screen"
|
"github.com/ivanizag/izapple2/screen"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,6 +32,8 @@ func (a *Apple2) GetCurrentVideoMode() uint16 {
|
|||||||
isRGB160Mode := isDoubleResMode && rgbFlag1 && !rgbFlag2
|
isRGB160Mode := isDoubleResMode && rgbFlag1 && !rgbFlag2
|
||||||
|
|
||||||
isMixMode := a.io.isSoftSwitchActive(ioFlagMixed)
|
isMixMode := a.io.isSoftSwitchActive(ioFlagMixed)
|
||||||
|
isSecondPage := a.io.isSoftSwitchActive(ioFlagSecondPage) && !a.mmu.store80Active
|
||||||
|
isAltText := a.isApple2e && a.io.isSoftSwitchActive(ioFlagAltChar)
|
||||||
|
|
||||||
var mode uint16
|
var mode uint16
|
||||||
if isSuperHighResMode {
|
if isSuperHighResMode {
|
||||||
@ -76,10 +76,12 @@ func (a *Apple2) GetCurrentVideoMode() uint16 {
|
|||||||
mode |= screen.VideoMixText40
|
mode |= screen.VideoMixText40
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isSecondPage := a.io.isSoftSwitchActive(ioFlagSecondPage) && !a.mmu.store80Active
|
|
||||||
if isSecondPage {
|
if isSecondPage {
|
||||||
mode |= screen.VideoSecondPage
|
mode |= screen.VideoSecondPage
|
||||||
}
|
}
|
||||||
|
if isAltText {
|
||||||
|
mode |= screen.VideoAltText
|
||||||
|
}
|
||||||
|
|
||||||
return mode
|
return mode
|
||||||
}
|
}
|
||||||
@ -111,11 +113,7 @@ func (a *Apple2) GetSuperVideoMemory() []uint8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetCharacterPixel returns the pixel as output by the character generator
|
// GetCharacterPixel returns the pixel as output by the character generator
|
||||||
func (a *Apple2) GetCharacterPixel(char uint8, rowInChar int, colInChar int) bool {
|
func (a *Apple2) GetCharacterPixel(char uint8, rowInChar int, colInChar int, isAltText bool, isFlashedFrame bool) bool {
|
||||||
// Flash mode is 2Hz (host time)
|
|
||||||
isFlashedFrame := time.Now().Nanosecond() > (1 * 1000 * 1000 * 1000 / 2)
|
|
||||||
isAltText := a.io.isSoftSwitchActive(ioFlagAltChar)
|
|
||||||
|
|
||||||
var pixel bool
|
var pixel bool
|
||||||
if a.isApple2e {
|
if a.isApple2e {
|
||||||
vid6 := (char & 0x40) != 0
|
vid6 := (char & 0x40) != 0
|
||||||
|
Loading…
Reference in New Issue
Block a user