Reverse 6 colors mod

This commit is contained in:
Ivan Izaguirre 2024-02-08 20:24:37 +01:00
parent 7cd5ce02ec
commit 5cf351f05c
20 changed files with 58 additions and 28 deletions

View File

@ -19,6 +19,7 @@ type Apple2 struct {
softVideoSwitch *SoftVideoSwitch
board string
isApple2e bool
isFourColors bool // An Apple II without the 6 color mod
commandChannel chan command
cycleDurationNs float64 // Current speed. Inverse of the cpu clock in Ghz

View File

@ -5,6 +5,7 @@ profile: false
forceCaps: false
ramworks: none
nsc: none
mods:
rgb: false
romx: false
chargenmap: 2e

View File

@ -6,6 +6,8 @@ import (
"fmt"
"os"
"strings"
"golang.org/x/exp/slices"
)
const configSuffix = ".cfg"
@ -28,6 +30,7 @@ const (
confForceCaps = "forceCaps"
confRgb = "rgb"
confRomx = "romx"
confMods = "mods"
confS0 = "s0"
confS1 = "s1"
confS2 = "s2"
@ -204,6 +207,7 @@ func getConfigurationFromCommandLine() (*configuration, string, error) {
confCharRom: "rom file for the character generator",
confCpu: "cpu type, can be '6502' or '65c02'",
confSpeed: "cpu speed in Mhz, can be 'ntsc', 'pal', 'full' or a decimal nunmber",
confMods: "comma separated list of mods applied to the board, available mods are 'shift', 'four-colors",
confRamworks: "memory to use with RAMWorks card, max is 16384",
confNsc: "add a DS1216 No-Slot-Clock on the main ROM (use 'main') or a slot ROM",
confTrace: "trace CPU execution with one or more comma separated tracers",
@ -221,10 +225,6 @@ func getConfigurationFromCommandLine() (*configuration, string, error) {
confS7: "slot 7 configuration.",
}
stringParams := []string{
confRom, confCharRom, confCpu, confSpeed, confRamworks, confNsc, confTrace, confModel,
confS0, confS1, confS2, confS3, confS4, confS5, confS6, confS7,
}
boolParams := []string{confProfile, confForceCaps, confRgb, confRomx}
configuration, err := configurationModels.getFromModel(defaultConfiguration)
@ -233,20 +233,16 @@ func getConfigurationFromCommandLine() (*configuration, string, error) {
}
configuration.set(confModel, defaultConfiguration)
for _, name := range stringParams {
for name, description := range paramDescription {
defaultValue, ok := configuration.getHas(name)
if !ok {
return nil, "", fmt.Errorf("default value not found for %s", name)
}
flag.String(name, defaultValue, paramDescription[name])
}
for _, name := range boolParams {
defaultValue, ok := configuration.getHas(name)
if !ok {
return nil, "", fmt.Errorf("default value not found for %s", name)
if slices.Contains(boolParams, name) {
flag.Bool(name, defaultValue == "true", description)
} else {
flag.String(name, defaultValue, description)
}
flag.Bool(name, defaultValue == "true", paramDescription[name])
}
flag.Usage = func() {

View File

@ -124,11 +124,15 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) {
case sdl.K_F12:
fallthrough
case sdl.K_PRINTSCREEN:
err := screen.SaveSnapshot(k.a, screen.ScreenModeNTSC, "snapshot.png")
if err != nil {
fmt.Printf("Error saving snapshoot: %v.\n.", err)
if ctrl {
screen.AddScenario(k.a, "../../screen/test_resources/")
} else {
fmt.Println("Saving snapshot 'snapshot.png'")
err := screen.SaveSnapshot(k.a, screen.ScreenModeNTSC, "snapshot.png")
if err != nil {
fmt.Printf("Error saving snapshoot: %v.\n.", err)
} else {
fmt.Println("Saving snapshot 'snapshot.png'")
}
}
case sdl.K_PAUSE:
k.a.SendCommand(izapple2.CommandPauseUnpause)

View File

@ -117,7 +117,7 @@ func (mmu *memoryManager) accessCArea(address uint16) memoryHandler {
}
func (mmu *memoryManager) accessUpperRAMArea(address uint16) memoryHandler {
if mmu.altZeroPage {
if mmu.altZeroPage && mmu.hasExtendedRAM() {
// Use extended RAM
block := mmu.extendedRAMBlock
if mmu.lcAltBank && address <= addressLimitDArea {
@ -135,14 +135,14 @@ func (mmu *memoryManager) accessUpperRAMArea(address uint16) memoryHandler {
}
func (mmu *memoryManager) getPhysicalMainRAM(ext bool) memoryHandler {
if ext {
if ext && mmu.hasExtendedRAM() {
return mmu.physicalExtRAM[mmu.extendedRAMBlock]
}
return mmu.physicalMainRAM
}
func (mmu *memoryManager) getVideoRAM(ext bool) *memoryRange {
if ext {
if ext && mmu.hasExtendedRAM() {
// The video memory uses the first extended RAM block, even with RAMWorks
return mmu.physicalExtRAM[0]
}
@ -334,6 +334,10 @@ func (mmu *memoryManager) setExtendedRAMActiveBlock(block uint8) {
mmu.extendedRAMBlock = block
}
func (mmu *memoryManager) hasExtendedRAM() bool {
return len(mmu.physicalExtRAM) > 0
}
func (mmu *memoryManager) reset() {
if mmu.apple2.isApple2e {
// MMU UtA2e 4-14, 5-22

View File

@ -12,9 +12,9 @@ const (
hiResHeightMixed = 160
)
func snapshotHiRes(vs VideoSource, isSecondPage bool, light color.Color) *image.RGBA {
func snapshotHiRes(vs VideoSource, isSecondPage bool, light color.Color, shiftSupported bool) *image.RGBA {
data := vs.GetVideoMemory(isSecondPage, false)
return renderHiRes(data, light)
return renderHiRes(data, light, shiftSupported)
}
func getHiResLineOffset(line int) uint16 {
@ -26,7 +26,7 @@ func getHiResLineOffset(line int) uint16 {
return uint16(section*40 + outerEighth*0x80 + innerEighth*0x400)
}
func renderHiRes(data []uint8, light color.Color) *image.RGBA {
func renderHiRes(data []uint8, light color.Color, shiftSupported bool) *image.RGBA {
// As described in "Undertanding the Apple II", with half pixel shifts
size := image.Rect(0, 0, 2*hiResWidth, hiResHeight)
img := image.NewRGBA(size)
@ -37,7 +37,7 @@ func renderHiRes(data []uint8, light color.Color) *image.RGBA {
x := 0
var previousColour color.Color = color.Black
for _, b := range bytes {
shifted := b>>7 == 1
shifted := shiftSupported && b>>7 == 1
for j := uint(0); j < 7; j++ {
bit := (b >> j) & 1
colour := light

View File

@ -52,6 +52,7 @@ func snapshotByMode(vs VideoSource, videoMode uint16, screenMode int) *image.RGB
isSecondPage := (videoMode & VideoSecondPage) != 0
isAltText := (videoMode & VideoAltText) != 0
isRGBCard := (videoMode & VideoRGBCard) != 0
shiftSupported := (videoMode & VideoFourColors) == 0
var lightColor color.Color = color.White
if screenMode == ScreenModeGreen {
@ -76,7 +77,7 @@ func snapshotByMode(vs VideoSource, videoMode uint16, screenMode int) *image.RGB
case VideoDGR:
snap = snapshotMeRes(vs, isSecondPage, lightColor)
case VideoHGR:
snap = snapshotHiRes(vs, isSecondPage, lightColor)
snap = snapshotHiRes(vs, isSecondPage, lightColor, shiftSupported)
case VideoDHGR:
snap, _ = snapshotDoubleHiRes(vs, isSecondPage, false /*isRGBMixMode*/, lightColor)
case VideoMono560:

View File

@ -85,6 +85,10 @@ func VideoModeName(vs VideoSource) string {
name += "-ALT"
}
if (videoMode & VideoFourColors) != 0 {
name += "-4COLORS"
}
switch mixMode {
case VideoMixText40:
name += "-MIX40"

View File

@ -6,7 +6,6 @@ import (
"image"
"image/color"
"image/png"
"io/ioutil"
"os"
"strings"
)
@ -58,7 +57,7 @@ func cloneSlice(src []uint8) []uint8 {
}
func loadTestScenario(filename string) (*TestScenario, error) {
bytes, err := ioutil.ReadFile(filename)
bytes, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
@ -79,7 +78,7 @@ func (ts *TestScenario) save(dir string) (string, error) {
}
pattern := fmt.Sprintf("%v_*.json", strings.ToLower(ts.VideoModeName))
file, err := ioutil.TempFile(dir, pattern)
file, err := os.CreateTemp(dir, pattern)
if err != nil {
return "", err
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -36,6 +36,7 @@ const (
VideoSecondPage uint16 = 0x1000
VideoAltText uint16 = 0x2000
VideoRGBCard uint16 = 0x4000
VideoFourColors uint16 = 0x8000
)
// VideoSource provides the info to build the video output

View File

@ -3,6 +3,7 @@ package izapple2
import (
"fmt"
"strconv"
"strings"
"github.com/ivanizag/iz6502"
)
@ -62,6 +63,19 @@ func configure(configuration *configuration) (*Apple2, error) {
}
}
// Add mods
mods := strings.Split(configuration.get(confMods), ",")
for _, mod := range mods {
switch strings.TrimSpace(mod) {
//case "shift":
// setupShiftedKeyboard(a)
case "four-colors":
// This removes the mod to have 6 colors sent by Wozniak to Byte
// magazine. See: https://archive.org/details/byte-magazine-1979-06/page/n67/mode/2up?view=theater
a.isFourColors = true
}
}
// Add optional accesories including the aux slot
ramWorksSize := configuration.get(confRamworks)
if ramWorksSize != "" && ramWorksSize != "none" {

View File

@ -92,6 +92,9 @@ func (a *Apple2) GetCurrentVideoMode() uint16 {
if isRGBCard {
mode |= screen.VideoRGBCard
}
if a.isFourColors {
mode |= screen.VideoFourColors
}
return mode
}