shiny resize, language card impl

This commit is contained in:
Zellyn Hunter 2018-05-20 21:12:12 -04:00
parent e8e766c0c7
commit 998569cee1
6 changed files with 202 additions and 36 deletions

View File

@ -1,6 +1,7 @@
package cards
type Card interface {
Init() // Give the card a chance to initialize
String() string // The name of the card, for debug/display purposes
Read16(address byte) byte // Read from the $C0(8+slot)X addresses
Write16(address byte, value byte) // Write to the $C0(8+slot)X addresses

View File

@ -58,6 +58,9 @@ func (dc *DiskCard) String() string {
}
func (dc *DiskCard) Init() {
}
func (dc *DiskCard) Slot() byte {
return dc.slot
}

View File

@ -5,18 +5,17 @@ import (
)
type FirmwareCard struct {
name string
rom [12288]byte
cm CardManager
slot byte
slotbit byte
name string
rom [12288]byte
cm CardManager
slot byte
}
func NewFirmwareCard(rom []byte, name string, slot byte, cm CardManager) (*FirmwareCard, error) {
if len(rom) != 12288 {
return nil, fmt.Errorf("Wrong size ROM: expected 12288, got %d", len(rom))
}
fc := &FirmwareCard{name: name, cm: cm, slot: slot, slotbit: 1 << slot}
fc := &FirmwareCard{name: name, cm: cm, slot: slot}
copy(fc.rom[:], rom)
return fc, nil
}
@ -25,6 +24,9 @@ func (fc *FirmwareCard) String() string {
return fmt.Sprintf("%s (slot %d)", fc.name, fc.slot)
}
func (fc *FirmwareCard) Init() {
}
func (fc *FirmwareCard) Slot() byte {
return fc.slot
}
@ -36,10 +38,10 @@ func (fc *FirmwareCard) ROMDisabled() {
func (fc *FirmwareCard) handleAccess(address byte) {
if address%2 == 1 {
// Card off
fc.cm.HandleROM(false, fc.slotbit)
fc.cm.HandleROM(false, fc.slot)
} else {
// Card on
fc.cm.HandleROM(true, fc.slotbit)
fc.cm.HandleROM(true, fc.slot)
}
}

142
cards/language.go Normal file
View File

@ -0,0 +1,142 @@
package cards
import (
"fmt"
)
type LanguageCard struct {
name string
rom [12288]byte
ram [16384]byte
cm CardManager
slot byte
slotbit byte
bank int // 1 = bank 1, 0 = bank 2
ramread bool
ramwrite bool
readcount int
}
func NewLanguageCard(rom []byte, name string, slot byte, cm CardManager) (*LanguageCard, error) {
if len(rom) != 12288 {
return nil, fmt.Errorf("Wrong size ROM: expected 12288, got %d", len(rom))
}
lc := &LanguageCard{
name: name,
cm: cm,
slot: slot,
slotbit: 1 << slot,
bank: 0,
ramread: false,
ramwrite: true,
readcount: 0,
}
copy(lc.rom[:], rom)
return lc, nil
}
func (lc *LanguageCard) String() string {
return fmt.Sprintf("%s (slot %d)", lc.name, lc.slot)
}
// Init: language card should always handle D000-FFFF accessess, since
// it contains either RAM or ROM.
func (lc *LanguageCard) Init() {
lc.cm.Handle12k(true, lc.slot)
}
func (lc *LanguageCard) Slot() byte {
return lc.slot
}
func (lc *LanguageCard) ROMDisabled() {
// Language card doesn't have a $C(8-F)xx ROM
}
func (lc *LanguageCard) handleAccess(address byte, write bool) {
if write {
lc.readcount = 0
}
address &^= 4
switch address &^ 8 {
case 0:
lc.ramread = true
lc.ramwrite = false
lc.readcount = 0
case 1:
lc.ramread = false
if lc.readcount > 0 {
lc.ramwrite = true
}
if !write {
lc.readcount++
}
case 2:
lc.ramread = false
lc.ramwrite = false
lc.readcount = 0
case 3:
lc.ramread = true
if lc.readcount > 0 {
lc.ramwrite = true
}
if !write {
lc.readcount++
}
}
lc.bank = int((address & 8) >> 3)
// fmt.Printf("ramread: %v, ramwrite: %v, bank: %d, readcount: %d\n", lc.ramread, lc.ramwrite, lc.bank, lc.readcount)
}
func (lc *LanguageCard) Read16(address byte) byte {
// fmt.Printf("Read to %02xd: ", address)
lc.handleAccess(address, false)
return lc.cm.EmptyRead()
}
func (lc *LanguageCard) Write16(address byte, value byte) {
// fmt.Printf("Write to %02xd: ", address)
lc.handleAccess(address, true)
}
func (lc *LanguageCard) ramOffset(address uint16) uint16 {
if address < 0xE000 {
return address - 0xD000 + 0x1000*uint16(lc.bank)
}
return address - 0xE000 + 0x2000
}
func (lc *LanguageCard) Read(address uint16) byte {
// fmt.Printf("Read from %04x\n", address)
if address < 0xD000 {
panic(fmt.Sprintf("%s got read to $%04X (<$D000)", lc.String(), address))
}
if lc.ramread {
return lc.ram[lc.ramOffset(address)]
}
return lc.rom[address-0xD000]
}
func (lc *LanguageCard) Write(address uint16, value byte) {
// fmt.Printf("Write to %04x\n", address)
if lc.ramwrite {
lc.ram[lc.ramOffset(address)] = value
}
}
func (lc *LanguageCard) Read256(address byte) byte {
return lc.cm.EmptyRead()
}
func (lc *LanguageCard) Write256(address byte, value byte) {
// Language is ROM: do nothing
}
func (lc *LanguageCard) WantTicker() bool {
return false
}
func (lc *LanguageCard) Tick() {
// do nothing
}

View File

@ -95,6 +95,7 @@ func (a2 *Apple2) AddCard(card cards.Card) error {
a2.cardTickerMask |= slotbit
}
a2.cards[slot] = card
card.Init()
return nil
}
@ -213,7 +214,7 @@ func (a2 *Apple2) Read(address uint16) byte {
if address&0xF000 == 0xC000 {
return a2.handleC00X(address, 0, false)
}
if address >= 0xD000 && a2.cardRomMask > 0 {
if address >= 0xD000 && a2.card12kMask > 0 {
if a2.card12kConflict {
panic(fmt.Sprintf("More than one card trying to provide 12K ROM: Mask=$%02X", a2.card12kMask))
}
@ -235,7 +236,7 @@ func (a2 *Apple2) Write(address uint16, value byte) {
// fmt.Printf("Write to 0x46: PC==$%04X\n", a2.cpu.PC())
// }
if address >= 0xD000 {
if a2.cardRomMask > 0 {
if a2.card12kMask > 0 {
if a2.card12kConflict {
panic(fmt.Sprintf("More than one card trying to provide 12K ROM: Mask=$%02X", a2.card12kMask))
}
@ -344,9 +345,9 @@ func (a2 *Apple2) HandleROM(onOff bool, slot byte) {
func (a2 *Apple2) Handle12k(onOff bool, slot byte) {
if onOff {
a2.card12kMask |= slot
a2.card12kMask |= (1 << slot)
} else {
a2.card12kMask &^= slot
a2.card12kMask &^= (1 << slot)
}
a2.card12kConflict = a2.card12kMask&(a2.card12kMask-1) > 0
if !onOff && !a2.card12kConflict && a2.card12kMask > 0 {

View File

@ -8,7 +8,6 @@ import (
"image/color"
"log"
"os"
"runtime"
"runtime/pprof"
"golang.org/x/exp/shiny/driver"
@ -18,6 +17,7 @@ import (
"github.com/zellyn/goapple2"
"github.com/zellyn/goapple2/cards"
"github.com/zellyn/goapple2/disk"
"github.com/zellyn/goapple2/util"
"github.com/zellyn/goapple2/videoscan"
)
@ -39,17 +39,17 @@ const (
func RunEmulator(s screen.Screen) {
rom := util.ReadRomOrDie("../data/roms/apple2+.rom", 12288)
charRom := util.ReadSmallCharacterRomOrDie("../data/roms/apple2-chars.rom")
intBasicRom := util.ReadRomOrDie("../data/roms/apple2.rom", 12288)
// intBasicRom := util.ReadRomOrDie("../data/roms/apple2.rom", 12288)
util.ReadRomOrDie("../data/roms/Apple Disk II 16 Sector Interface Card ROM P5 - 341-0027.bin", 256)
eventChan := make(chan (interface{}))
w, err := s.NewWindow(&screen.NewWindowOptions{Width: SCREEN_WIDTH, Height: SCREEN_HEIGHT})
w, err := s.NewWindow(&screen.NewWindowOptions{Width: SCREEN_WIDTH * 2, Height: SCREEN_HEIGHT * 2})
if err != nil {
log.Fatal(err)
}
defer w.Release()
winSize := image.Point{SCREEN_WIDTH, SCREEN_HEIGHT}
winSize := image.Point{SCREEN_WIDTH * 2, SCREEN_HEIGHT * 2}
b, err := s.NewBuffer(winSize)
if err != nil {
log.Fatal(err)
@ -59,37 +59,48 @@ func RunEmulator(s screen.Screen) {
var a2 *goapple2.Apple2
oncePerFrame := func() {
a2.Done = a2.Done || ProcessEvents(a2, w, eventChan)
runtime.Gosched()
}
plotter := ShinyPlotter{w, b, oncePerFrame}
a2 = goapple2.NewApple2(plotter, rom, charRom)
firmwareCard, err := cards.NewFirmwareCard(intBasicRom, "Intbasic Firmware Card", 0, a2)
if err != nil {
panic(err)
}
if err := a2.AddCard(firmwareCard); err != nil {
log.Fatal(err)
}
/*
diskCardRom := util.ReadRomOrDie("../data/roms/Apple Disk II 16 Sector Interface Card ROM P5 - 341-0027.bin", 256)
diskCard, err := cards.NewDiskCard(diskCardRom, 6, a2)
firmwareCard, err := cards.NewFirmwareCard(intBasicRom, "Intbasic Firmware Card", 0, a2)
if err != nil {
panic(err)
}
if err := a2.AddCard(diskCard); err != nil {
if err := a2.AddCard(firmwareCard); err != nil {
log.Fatal(err)
}
*/
languageCard, err := cards.NewLanguageCard(rom, "Language Card", 0, a2)
if err != nil {
panic(err)
}
if err := a2.AddCard(languageCard); err != nil {
log.Fatal(err)
}
diskCardRom := util.ReadRomOrDie("../data/roms/Apple Disk II 16 Sector Interface Card ROM P5 - 341-0027.bin", 256)
diskCard, err := cards.NewDiskCard(diskCardRom, 6, a2)
if err != nil {
panic(err)
}
if err := a2.AddCard(diskCard); err != nil {
log.Fatal(err)
}
// disk1, err := disk.DiskFromFile("../data/disks/spedtest.dsk", 0)
// disk1, err := disk.DiskFromFile("../data/disks/dung_beetles.dsk", 0)
// disk1, err := disk.DiskFromFile("../data/disks/chivalry.dsk", 0)
// disk1, err := disk.DiskFromFile("../data/disks/wavynavy.dsk", 0)
// if err != nil {
// log.Fatal(err)
// }
// diskCard.LoadDisk(disk1, 0)
disk1, err := disk.DiskFromFile("/Users/zellyn/Documents/a2-disks/disks/Rescue_Raiders_1.2.dsk", 0)
// disk1, err := disk.DiskFromFile("/Users/zellyn/Development/go/src/github.com/zellyn/a2audit/floatbus/floatbus.dsk", 0)
// disk1, err := disk.DiskFromFile("/Users/zellyn/Development/go/src/github.com/zellyn/a2audit/audit/audit.dsk", 0)
// disk1, err := disk.DiskFromFile("/Users/zellyn/Development/go/src/github.com/zellyn/diskii/lib/supermon/testdata/chacha20.dsk", 0)
if err != nil {
log.Fatal(err)
}
diskCard.LoadDisk(disk1, 0)
steps := *steplimit
@ -119,7 +130,7 @@ func RunEmulator(s screen.Screen) {
a2.AddPCAction(0xBDAF, goapple2.PCAction{Type: goapple2.ActionDiskStatus})
a2.AddPCAction(0xBDAF, goapple2.PCAction{Type: goapple2.ActionTrace, String: "on",
a2.AddPCAction(0x6000, goapple2.PCAction{Type: goapple2.ActionTrace, String: "on",
Delay: 70})
a2.AddPCAction(
@ -129,7 +140,9 @@ func RunEmulator(s screen.Screen) {
0xBDAF, goapple2.PCAction{Type: goapple2.ActionDumpMem, String: "0xBDAF-goa2.bin", Delay: 68})
*/
go typeProgram(a2)
// a2.AddPCAction(0x6000, goapple2.PCAction{Type: goapple2.ActionTrace, String: "on"})
// go typeProgram(a2)
go func() {
for {
@ -143,7 +156,6 @@ func RunEmulator(s screen.Screen) {
fmt.Println(err)
break
}
// runtime.Gosched() // So the keyboard-reading goroutines can run
if steps > 0 {
steps--
if steps == 0 {
@ -156,7 +168,12 @@ func RunEmulator(s screen.Screen) {
func plot(x, y int, c color.RGBA, b screen.Buffer) {
rgba := b.RGBA()
rgba.SetRGBA(x+BORDER_W, y+BORDER_H, c)
xx := (x + BORDER_W) * 2
yy := (y + BORDER_H) * 2
rgba.SetRGBA(xx, yy, c)
rgba.SetRGBA(xx+1, yy, c)
rgba.SetRGBA(xx, yy+1, c)
rgba.SetRGBA(xx+1, yy+1, c)
/*
x = x + BORDER_W