Support color graphics. As defined in the Reference Manual, no artifacts.
This commit is contained in:
parent
1196890c18
commit
fc3754159f
122
apple2/screen.go
122
apple2/screen.go
|
@ -11,28 +11,26 @@ import (
|
||||||
// Snapshot the currently visible screen
|
// Snapshot the currently visible screen
|
||||||
func Snapshot(a *Apple2) *image.RGBA {
|
func Snapshot(a *Apple2) *image.RGBA {
|
||||||
isTextMode := a.io.isSoftSwitchActive(ioFlagText)
|
isTextMode := a.io.isSoftSwitchActive(ioFlagText)
|
||||||
is80ColMode := a.io.isSoftSwitchActive(ioFlag80Col)
|
|
||||||
isHiResMode := a.io.isSoftSwitchActive(ioFlagHiRes)
|
isHiResMode := a.io.isSoftSwitchActive(ioFlagHiRes)
|
||||||
|
// Todo: isMixMode
|
||||||
pageIndex := 0
|
pageIndex := 0
|
||||||
if a.io.isSoftSwitchActive(ioFlagSecondPage) {
|
if a.io.isSoftSwitchActive(ioFlagSecondPage) {
|
||||||
pageIndex = 1
|
pageIndex = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if isTextMode {
|
if isTextMode {
|
||||||
if is80ColMode {
|
return snapshotTextMode(a, pageIndex)
|
||||||
// Not supported
|
|
||||||
} else {
|
|
||||||
return snapshotTextMode(a, pageIndex)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if isHiResMode {
|
if isHiResMode {
|
||||||
return snapshotGraphMode(a, pageIndex)
|
//return snapshotHiResModeReferenceMono(a, pageIndex)
|
||||||
|
return snapshotHiResModeReferenceColor(a, pageIndex)
|
||||||
|
//return snapshotHiResModeReferenceColorSolid(a, pageIndex)
|
||||||
} else {
|
} else {
|
||||||
// Not supported
|
// Lo res mode not supported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//fmt.Printf("g: %v, 8: %v, h: %v\n", isTextMode, is80ColMode, isHiResMode)
|
//fmt.Printf("g: %v, h: %v\n", isTextMode, isHiResMode)
|
||||||
return nil
|
return nil
|
||||||
//panic("Screen mode not supported")
|
//panic("Screen mode not supported")
|
||||||
}
|
}
|
||||||
|
@ -137,7 +135,8 @@ func getGraphLine(a *Apple2, line int, page int) []uint8 {
|
||||||
return memPage[lo : lo+40]
|
return memPage[lo : lo+40]
|
||||||
}
|
}
|
||||||
|
|
||||||
func snapshotGraphMode(a *Apple2, page int) *image.RGBA {
|
func snapshotHiResModeReferenceMono(a *Apple2, page int) *image.RGBA {
|
||||||
|
// As defined on "Apple II Reference Manual", page 19
|
||||||
size := image.Rect(0, 0, graphWidth, graphHeight)
|
size := image.Rect(0, 0, graphWidth, graphHeight)
|
||||||
img := image.NewRGBA(size)
|
img := image.NewRGBA(size)
|
||||||
|
|
||||||
|
@ -159,3 +158,106 @@ func snapshotGraphMode(a *Apple2, page int) *image.RGBA {
|
||||||
|
|
||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func snapshotHiResModeReferenceColor(a *Apple2, page int) *image.RGBA {
|
||||||
|
// As defined on "Apple II Reference Manual", page 19
|
||||||
|
size := image.Rect(0, 0, graphWidth, graphHeight)
|
||||||
|
img := image.NewRGBA(size)
|
||||||
|
|
||||||
|
// RGB values from https://mrob.com/pub/xapple2/colors.html
|
||||||
|
black := color.RGBA{0, 0, 0, 255}
|
||||||
|
violet := color.RGBA{255, 68, 253, 255}
|
||||||
|
red := color.RGBA{255, 106, 60, 255}
|
||||||
|
green := color.RGBA{20, 246, 60, 255}
|
||||||
|
blue := color.RGBA{20, 207, 253, 255}
|
||||||
|
white := color.RGBA{255, 255, 255, 255}
|
||||||
|
colorMap := [][][]color.Color{
|
||||||
|
{
|
||||||
|
/* 00 */ {black, black},
|
||||||
|
/* 01 */ {black, green},
|
||||||
|
/* 10 */ {violet, black},
|
||||||
|
/* 11 */ {white, white},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 00 */ {black, black},
|
||||||
|
/* 01 */ {black, red},
|
||||||
|
/* 10 */ {blue, black},
|
||||||
|
/* 11 */ {white, white},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := 0; y < graphHeight; y++ {
|
||||||
|
bytes := getGraphLine(a, y, page)
|
||||||
|
x := 0
|
||||||
|
previous := uint8(0)
|
||||||
|
for _, b := range bytes {
|
||||||
|
shift := b >> 7
|
||||||
|
for j := uint(0); j < 7; j++ {
|
||||||
|
bit := (b >> j) & 1
|
||||||
|
even := x%2 == 0
|
||||||
|
if even {
|
||||||
|
previous = bit
|
||||||
|
} else {
|
||||||
|
pair := colorMap[shift][(previous<<1)+bit]
|
||||||
|
img.Set(x-1, y, pair[0])
|
||||||
|
img.Set(x, y, pair[1])
|
||||||
|
}
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
|
||||||
|
func snapshotHiResModeReferenceColorSolid(a *Apple2, page int) *image.RGBA {
|
||||||
|
// As defined on "Apple II Reference Manual", page 19
|
||||||
|
// but with more solid colors
|
||||||
|
size := image.Rect(0, 0, graphWidth, graphHeight)
|
||||||
|
img := image.NewRGBA(size)
|
||||||
|
|
||||||
|
// RGB values from https://mrob.com/pub/xapple2/colors.html
|
||||||
|
black := color.RGBA{0, 0, 0, 255}
|
||||||
|
violet := color.RGBA{255, 68, 253, 255}
|
||||||
|
red := color.RGBA{255, 106, 60, 255}
|
||||||
|
green := color.RGBA{20, 246, 60, 255}
|
||||||
|
blue := color.RGBA{20, 207, 253, 255}
|
||||||
|
white := color.RGBA{255, 255, 255, 255}
|
||||||
|
colorMap := [][]color.Color{
|
||||||
|
{
|
||||||
|
/* 00 */ black,
|
||||||
|
/* 01 */ green,
|
||||||
|
/* 10 */ violet,
|
||||||
|
/* 11 */ white,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/* 00 */ black,
|
||||||
|
/* 01 */ red,
|
||||||
|
/* 10 */ blue,
|
||||||
|
/* 11 */ white,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for y := 0; y < graphHeight; y++ {
|
||||||
|
bytes := getGraphLine(a, y, page)
|
||||||
|
x := 0
|
||||||
|
previous := uint8(0)
|
||||||
|
for _, b := range bytes {
|
||||||
|
shift := b >> 7
|
||||||
|
for j := uint(0); j < 7; j++ {
|
||||||
|
bit := (b >> j) & 1
|
||||||
|
even := x%2 == 0
|
||||||
|
if even {
|
||||||
|
previous = bit
|
||||||
|
} else {
|
||||||
|
colour := colorMap[shift][(previous<<1)+bit]
|
||||||
|
img.Set(x-1, y, colour)
|
||||||
|
img.Set(x, y, colour)
|
||||||
|
}
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ func addApple2SoftSwitches(io *ioC0Page) {
|
||||||
io.addSoftSwitchRW(0x55, getSoftSwitch(ioFlagSecondPage, true))
|
io.addSoftSwitchRW(0x55, getSoftSwitch(ioFlagSecondPage, true))
|
||||||
io.addSoftSwitchRW(0x56, getSoftSwitch(ioFlagHiRes, false))
|
io.addSoftSwitchRW(0x56, getSoftSwitch(ioFlagHiRes, false))
|
||||||
io.addSoftSwitchRW(0x57, getSoftSwitch(ioFlagHiRes, true))
|
io.addSoftSwitchRW(0x57, getSoftSwitch(ioFlagHiRes, true))
|
||||||
|
|
||||||
io.addSoftSwitchRW(0x58, getSoftSwitch(ioFlagAnnunciator0, false))
|
io.addSoftSwitchRW(0x58, getSoftSwitch(ioFlagAnnunciator0, false))
|
||||||
io.addSoftSwitchRW(0x59, getSoftSwitch(ioFlagAnnunciator0, true))
|
io.addSoftSwitchRW(0x59, getSoftSwitch(ioFlagAnnunciator0, true))
|
||||||
io.addSoftSwitchRW(0x5a, getSoftSwitch(ioFlagAnnunciator1, false))
|
io.addSoftSwitchRW(0x5a, getSoftSwitch(ioFlagAnnunciator1, false))
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
// SDLRun starts the Apple2 emulator on SDL
|
// SDLRun starts the Apple2 emulator on SDL
|
||||||
func SDLRun(a *apple2.Apple2) {
|
func SDLRun(a *apple2.Apple2) {
|
||||||
window, renderer, err := sdl.CreateWindowAndRenderer(800, 600,
|
window, renderer, err := sdl.CreateWindowAndRenderer(4*40*7, 4*24*8,
|
||||||
sdl.WINDOW_SHOWN)
|
sdl.WINDOW_SHOWN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Failed to create window")
|
panic("Failed to create window")
|
||||||
|
@ -45,7 +45,10 @@ func SDLRun(a *apple2.Apple2) {
|
||||||
img := apple2.Snapshot(a)
|
img := apple2.Snapshot(a)
|
||||||
if img != nil {
|
if img != nil {
|
||||||
surface, err := sdl.CreateRGBSurfaceFrom(unsafe.Pointer(&img.Pix[0]), 40*7, 24*8, 32, 40*7*4,
|
surface, err := sdl.CreateRGBSurfaceFrom(unsafe.Pointer(&img.Pix[0]), 40*7, 24*8, 32, 40*7*4,
|
||||||
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff)
|
0x0000ff, 0x0000ff00, 0x00ff0000, 0xff000000)
|
||||||
|
// Valid for little endian. Should we reverse for big endian?
|
||||||
|
// 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,15 @@ func (k *sdlKeyboard) putText(textEvent *sdl.TextInputEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
|
func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
|
||||||
/* To get keys as understood by the Apple2 hardware run:
|
/*
|
||||||
10 A=PEEK(49152)
|
See "Apple II reference manual", page 5
|
||||||
20 PRINT A, A - 128
|
|
||||||
30 GOTO 10
|
To get keys as understood by the Apple2 hardware run:
|
||||||
|
10 A=PEEK(49152)
|
||||||
|
20 PRINT A, A - 128
|
||||||
|
30 GOTO 10
|
||||||
|
|
||||||
|
Missing Reset button
|
||||||
*/
|
*/
|
||||||
if keyEvent.Type != sdl.KEYDOWN {
|
if keyEvent.Type != sdl.KEYDOWN {
|
||||||
// Process only key pushes
|
// Process only key pushes
|
||||||
|
|
Loading…
Reference in New Issue