From fc3754159f185cfe19fcffa8312ba4b8be561692 Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Sun, 28 Apr 2019 00:13:34 +0200 Subject: [PATCH] Support color graphics. As defined in the Reference Manual, no artifacts. --- apple2/screen.go | 122 +++++++++++++++++++++++++++++++++++---- apple2/softSwitches2.go | 1 + apple2sdl/run.go | 7 ++- apple2sdl/sdlKeyboard.go | 13 +++-- 4 files changed, 127 insertions(+), 16 deletions(-) diff --git a/apple2/screen.go b/apple2/screen.go index 8188ca2..53fb968 100644 --- a/apple2/screen.go +++ b/apple2/screen.go @@ -11,28 +11,26 @@ import ( // Snapshot the currently visible screen func Snapshot(a *Apple2) *image.RGBA { isTextMode := a.io.isSoftSwitchActive(ioFlagText) - is80ColMode := a.io.isSoftSwitchActive(ioFlag80Col) isHiResMode := a.io.isSoftSwitchActive(ioFlagHiRes) + // Todo: isMixMode pageIndex := 0 if a.io.isSoftSwitchActive(ioFlagSecondPage) { pageIndex = 1 } if isTextMode { - if is80ColMode { - // Not supported - } else { - return snapshotTextMode(a, pageIndex) - } + return snapshotTextMode(a, pageIndex) } else { if isHiResMode { - return snapshotGraphMode(a, pageIndex) + //return snapshotHiResModeReferenceMono(a, pageIndex) + return snapshotHiResModeReferenceColor(a, pageIndex) + //return snapshotHiResModeReferenceColorSolid(a, pageIndex) } 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 //panic("Screen mode not supported") } @@ -137,7 +135,8 @@ func getGraphLine(a *Apple2, line int, page int) []uint8 { 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) img := image.NewRGBA(size) @@ -159,3 +158,106 @@ func snapshotGraphMode(a *Apple2, page int) *image.RGBA { 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 +} diff --git a/apple2/softSwitches2.go b/apple2/softSwitches2.go index a9970a4..66da090 100644 --- a/apple2/softSwitches2.go +++ b/apple2/softSwitches2.go @@ -41,6 +41,7 @@ func addApple2SoftSwitches(io *ioC0Page) { io.addSoftSwitchRW(0x55, getSoftSwitch(ioFlagSecondPage, true)) io.addSoftSwitchRW(0x56, getSoftSwitch(ioFlagHiRes, false)) io.addSoftSwitchRW(0x57, getSoftSwitch(ioFlagHiRes, true)) + io.addSoftSwitchRW(0x58, getSoftSwitch(ioFlagAnnunciator0, false)) io.addSoftSwitchRW(0x59, getSoftSwitch(ioFlagAnnunciator0, true)) io.addSoftSwitchRW(0x5a, getSoftSwitch(ioFlagAnnunciator1, false)) diff --git a/apple2sdl/run.go b/apple2sdl/run.go index 8c909ce..cec4778 100644 --- a/apple2sdl/run.go +++ b/apple2sdl/run.go @@ -10,7 +10,7 @@ import ( // SDLRun starts the Apple2 emulator on SDL 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) if err != nil { panic("Failed to create window") @@ -45,7 +45,10 @@ func SDLRun(a *apple2.Apple2) { img := apple2.Snapshot(a) if img != nil { 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 { panic(err) } diff --git a/apple2sdl/sdlKeyboard.go b/apple2sdl/sdlKeyboard.go index bb35a73..7707def 100644 --- a/apple2sdl/sdlKeyboard.go +++ b/apple2sdl/sdlKeyboard.go @@ -33,10 +33,15 @@ func (k *sdlKeyboard) putText(textEvent *sdl.TextInputEvent) { } func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) { - /* To get keys as understood by the Apple2 hardware run: - 10 A=PEEK(49152) - 20 PRINT A, A - 128 - 30 GOTO 10 + /* + See "Apple II reference manual", page 5 + + 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 { // Process only key pushes