mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-06-15 08:29:28 +00:00
Support for video7 RGB 160*192 video mode
This commit is contained in:
parent
d47b0a5e28
commit
62d0a35b3e
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ func SDLRun(a *apple2.Apple2) {
|
||||||
var img *image.RGBA
|
var img *image.RGBA
|
||||||
if kp.showPages {
|
if kp.showPages {
|
||||||
img = a.SnapshotParts()
|
img = a.SnapshotParts()
|
||||||
window.SetTitle(a.Name + " " + a.VideoModeName())
|
window.SetTitle(fmt.Sprintf("%v %v %vx%v", a.Name, a.VideoModeName(), img.Rect.Dx()/2, img.Rect.Dy()/2))
|
||||||
} else {
|
} else {
|
||||||
img = a.Snapshot()
|
img = a.Snapshot()
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,9 @@ See:
|
||||||
https://apple2online.com/web_documents/Video-7%20Manual%20KB.pdf
|
https://apple2online.com/web_documents/Video-7%20Manual%20KB.pdf
|
||||||
https://mirrors.apple2.org.za/ftp.apple.asimov.net/documentation/hardware/video/DIGICARD%2064K%20Extended%2080%20Column%20RGB%20Card%20for%20Apple%20IIe%20Instruction%20Manual.pdf
|
https://mirrors.apple2.org.za/ftp.apple.asimov.net/documentation/hardware/video/DIGICARD%2064K%20Extended%2080%20Column%20RGB%20Card%20for%20Apple%20IIe%20Instruction%20Manual.pdf
|
||||||
|
|
||||||
|
Diagnostics disk:
|
||||||
|
https://mirrors.apple2.org.za/ftp.apple.asimov.net/images/hardware/video/Video-7%20Apple%20II%20RGB%20Demo%20%28Video-7%2C%20Inc.%29%281984%29.dsk
|
||||||
|
|
||||||
It goes to the 80 column slot.
|
It goes to the 80 column slot.
|
||||||
|
|
||||||
To set the state it AN3 in graphics mode has to go off-on-off-on. Each pair off-on record the state of 80col:
|
To set the state it AN3 in graphics mode has to go off-on-off-on. Each pair off-on record the state of 80col:
|
||||||
|
|
|
@ -27,7 +27,8 @@ const (
|
||||||
videoRGBText40 uint8 = 0x10
|
videoRGBText40 uint8 = 0x10
|
||||||
videoMono560 uint8 = 0x11
|
videoMono560 uint8 = 0x11
|
||||||
videoRGBMix uint8 = 0x12
|
videoRGBMix uint8 = 0x12
|
||||||
videoSHR uint8 = 0x13
|
videoRGB160 uint8 = 0x13
|
||||||
|
videoSHR uint8 = 0x14
|
||||||
|
|
||||||
// Modifiers
|
// Modifiers
|
||||||
videoBaseMask uint8 = 0x1f
|
videoBaseMask uint8 = 0x1f
|
||||||
|
@ -47,6 +48,8 @@ func getCurrentVideoMode(a *Apple2) uint8 {
|
||||||
rgbFlag2 := a.io.isSoftSwitchActive(ioFlag2RGBCard)
|
rgbFlag2 := a.io.isSoftSwitchActive(ioFlag2RGBCard)
|
||||||
isMono560 := isDoubleResMode && !rgbFlag1 && !rgbFlag2
|
isMono560 := isDoubleResMode && !rgbFlag1 && !rgbFlag2
|
||||||
isRGBMixMode := isDoubleResMode && !rgbFlag1 && rgbFlag2
|
isRGBMixMode := isDoubleResMode && !rgbFlag1 && rgbFlag2
|
||||||
|
isRGB160Mode := isDoubleResMode && rgbFlag1 && !rgbFlag2
|
||||||
|
|
||||||
isMixMode := a.io.isSoftSwitchActive(ioFlagMixed)
|
isMixMode := a.io.isSoftSwitchActive(ioFlagMixed)
|
||||||
|
|
||||||
mode := uint8(0)
|
mode := uint8(0)
|
||||||
|
@ -71,6 +74,8 @@ func getCurrentVideoMode(a *Apple2) uint8 {
|
||||||
mode = videoMono560
|
mode = videoMono560
|
||||||
} else if isRGBMixMode {
|
} else if isRGBMixMode {
|
||||||
mode = videoRGBMix
|
mode = videoRGBMix
|
||||||
|
} else if isRGB160Mode {
|
||||||
|
mode = videoRGB160
|
||||||
} else {
|
} else {
|
||||||
mode = videoDHGR
|
mode = videoDHGR
|
||||||
}
|
}
|
||||||
|
@ -137,6 +142,8 @@ func snapshotByMode(a *Apple2, videoMode uint8) *image.RGBA {
|
||||||
applyNTSCFilter = false
|
applyNTSCFilter = false
|
||||||
case videoRGBMix:
|
case videoRGBMix:
|
||||||
snap, ntscMask = snapshotDoubleHiResModeMono(a, isSecondPage, true /*isRGBMixMode*/, lightColor)
|
snap, ntscMask = snapshotDoubleHiResModeMono(a, isSecondPage, true /*isRGBMixMode*/, lightColor)
|
||||||
|
case videoRGB160:
|
||||||
|
snap = snapshotDoubleHiRes160ModeMono(a, isSecondPage, lightColor)
|
||||||
case videoSHR:
|
case videoSHR:
|
||||||
snap = snapshotSuperHiResMode(a)
|
snap = snapshotSuperHiResMode(a)
|
||||||
applyNTSCFilter = false
|
applyNTSCFilter = false
|
||||||
|
|
|
@ -63,6 +63,8 @@ func (a *Apple2) VideoModeName() string {
|
||||||
applyNTSCFilter = false
|
applyNTSCFilter = false
|
||||||
case videoRGBMix:
|
case videoRGBMix:
|
||||||
name = "RGMMIX"
|
name = "RGMMIX"
|
||||||
|
case videoRGB160:
|
||||||
|
name = "RGB160"
|
||||||
case videoSHR:
|
case videoSHR:
|
||||||
name = "SHR"
|
name = "SHR"
|
||||||
applyNTSCFilter = false
|
applyNTSCFilter = false
|
||||||
|
@ -89,21 +91,23 @@ func (a *Apple2) VideoModeName() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mixFourSnapshots(snaps []*image.RGBA) *image.RGBA {
|
func mixFourSnapshots(snaps []*image.RGBA) *image.RGBA {
|
||||||
size := image.Rect(0, 0, hiResWidth*4, hiResHeight*2)
|
width := snaps[0].Rect.Dx()
|
||||||
|
height := snaps[0].Rect.Dy()
|
||||||
|
size := image.Rect(0, 0, width*2, height*2)
|
||||||
out := image.NewRGBA(size)
|
out := image.NewRGBA(size)
|
||||||
|
|
||||||
for i := 0; i < 4; i++ {
|
for i := 1; i < 4; i++ {
|
||||||
if snaps[i].Bounds().Dx() < hiResWidth*2 {
|
if snaps[i].Bounds().Dx() < width {
|
||||||
snaps[i] = doubleWidthFilter(snaps[i])
|
snaps[i] = doubleWidthFilter(snaps[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for y := 0; y < hiResHeight; y++ {
|
for y := 0; y < height; y++ {
|
||||||
for x := 0; x < hiResWidth*2; x++ {
|
for x := 0; x < width; x++ {
|
||||||
out.Set(x, y, snaps[0].At(x, y))
|
out.Set(x, y, snaps[0].At(x, y))
|
||||||
out.Set(x+hiResWidth*2, y, snaps[1].At(x, y))
|
out.Set(x+width, y, snaps[1].At(x, y))
|
||||||
out.Set(x, y+hiResHeight, snaps[2].At(x, y))
|
out.Set(x, y+height, snaps[2].At(x, y))
|
||||||
out.Set(x+hiResWidth*2, y+hiResHeight, snaps[3].At(x, y))
|
out.Set(x+width, y+height, snaps[3].At(x, y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
doubleHiResWidth = 2 * hiResWidth
|
doubleHiResWidth = 2 * hiResWidth
|
||||||
|
rgb160Width = 4 * 160
|
||||||
)
|
)
|
||||||
|
|
||||||
func snapshotDoubleHiResModeMono(a *Apple2, isSecondPage bool, getNTSCMask bool, light color.Color) (*image.RGBA, *image.Alpha) {
|
func snapshotDoubleHiResModeMono(a *Apple2, isSecondPage bool, getNTSCMask bool, light color.Color) (*image.RGBA, *image.Alpha) {
|
||||||
|
@ -62,3 +63,32 @@ func snapshotDoubleHiResModeMono(a *Apple2, isSecondPage bool, getNTSCMask bool,
|
||||||
}
|
}
|
||||||
return img, ntscMask
|
return img, ntscMask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func snapshotDoubleHiRes160ModeMono(a *Apple2, isSecondPage bool, light color.Color) *image.RGBA {
|
||||||
|
size := image.Rect(0, 0, rgb160Width, hiResHeight)
|
||||||
|
img := image.NewRGBA(size)
|
||||||
|
|
||||||
|
for y := 0; y < hiResHeight; y++ {
|
||||||
|
lineParts := [][]uint8{
|
||||||
|
getHiResLine(a, y, isSecondPage, true /*auxmem*/),
|
||||||
|
getHiResLine(a, y, isSecondPage, false /*auxmem*/),
|
||||||
|
}
|
||||||
|
x := 0
|
||||||
|
for iByte := 0; iByte < hiResLineBytes; iByte++ {
|
||||||
|
for iPart := 0; iPart < 2; iPart++ {
|
||||||
|
b := lineParts[iPart][iByte]
|
||||||
|
for j := uint(0); j < 8; j++ {
|
||||||
|
// Set color
|
||||||
|
bit := (b >> j) & 1
|
||||||
|
colour := light
|
||||||
|
if bit == 0 {
|
||||||
|
colour = color.Black
|
||||||
|
}
|
||||||
|
img.Set(x, y, colour)
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
|
|
@ -73,8 +73,8 @@ func renderGrMode(data []uint8, isDoubleResMode bool, light color.Color) *image.
|
||||||
|
|
||||||
if isDoubleResMode && ((c % 2) == 0) {
|
if isDoubleResMode && ((c % 2) == 0) {
|
||||||
// See "Understanding the Apple II", page 8-44
|
// See "Understanding the Apple II", page 8-44
|
||||||
// Even blocks color are rotated left on bit
|
// Even blocks color are rotated left one bit
|
||||||
offset = offset + 3
|
offset = offset + 3 // Equivalent to -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert the pixelWidth pixels required
|
// Insert the pixelWidth pixels required
|
||||||
|
|
|
@ -52,13 +52,15 @@ func filterNTSCColor(in *image.RGBA, mask *image.Alpha) *image.RGBA {
|
||||||
colorMap := ntscColorMap // or rgbColorMap
|
colorMap := ntscColorMap // or rgbColorMap
|
||||||
|
|
||||||
b := in.Bounds()
|
b := in.Bounds()
|
||||||
size := image.Rect(0, 0, b.Dx()+3, b.Dy())
|
width := b.Dx()
|
||||||
|
height := b.Dy()
|
||||||
|
size := image.Rect(0, 0, width+4, height)
|
||||||
out := image.NewRGBA(size)
|
out := image.NewRGBA(size)
|
||||||
|
|
||||||
for y := b.Min.Y; y < b.Max.Y; y++ {
|
for y := 0; y < height; y++ {
|
||||||
// We store the last four bits. We start with 0000
|
// We store the last four bits. We start with 0000
|
||||||
v := 0
|
v := 0
|
||||||
for x := b.Min.X; x < b.Dx(); x++ {
|
for x := 0; x < width; x++ {
|
||||||
cIn := in.At(x, y)
|
cIn := in.At(x, y)
|
||||||
r, _, _, _ := cIn.RGBA()
|
r, _, _, _ := cIn.RGBA()
|
||||||
|
|
||||||
|
@ -82,7 +84,7 @@ func filterNTSCColor(in *image.RGBA, mask *image.Alpha) *image.RGBA {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We fade for the last three positions
|
// We fade for the last three positions
|
||||||
for x := b.Dx(); x < b.Max.X; x++ {
|
for x := width; x < width+4; x++ {
|
||||||
v >>= 1
|
v >>= 1
|
||||||
cOut := colorMap[v]
|
cOut := colorMap[v]
|
||||||
out.Set(x, y, cOut)
|
out.Set(x, y, cOut)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user