mirror of
https://github.com/zellyn/goapple2.git
synced 2024-12-26 16:29:22 +00:00
shiny resize, language card impl
This commit is contained in:
parent
e8e766c0c7
commit
998569cee1
@ -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
|
||||
|
@ -58,6 +58,9 @@ func (dc *DiskCard) String() string {
|
||||
|
||||
}
|
||||
|
||||
func (dc *DiskCard) Init() {
|
||||
}
|
||||
|
||||
func (dc *DiskCard) Slot() byte {
|
||||
return dc.slot
|
||||
}
|
||||
|
@ -9,14 +9,13 @@ type FirmwareCard struct {
|
||||
rom [12288]byte
|
||||
cm CardManager
|
||||
slot byte
|
||||
slotbit 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
142
cards/language.go
Normal 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
|
||||
}
|
@ -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 {
|
||||
|
@ -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,11 +59,11 @@ 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)
|
||||
@ -71,8 +71,16 @@ func RunEmulator(s screen.Screen) {
|
||||
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 {
|
||||
@ -81,15 +89,18 @@ func RunEmulator(s screen.Screen) {
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user