texty: allow executing binary file

This commit is contained in:
Zellyn Hunter 2016-09-09 20:49:21 -04:00
parent ab0712fe68
commit 22a6e29678
2 changed files with 59 additions and 16 deletions

View File

@ -55,7 +55,16 @@ type Apple2 struct {
cycle uint64 cycle uint64
} }
func NewApple2(p videoscan.Plotter, rom []byte, charRom [2048]byte) *Apple2 { // Option is an optional param to NewApple2.
type Option func(*Apple2)
func WithRAM(address uint16, bytes []byte) Option {
return func(a2 *Apple2) {
copy(a2.mem[address:], bytes)
}
}
func NewApple2(p videoscan.Plotter, rom []byte, charRom [2048]byte, options ...Option) *Apple2 {
a2 := &Apple2{ a2 := &Apple2{
// BUG(zellyn): this is not how the apple2 keyboard actually works // BUG(zellyn): this is not how the apple2 keyboard actually works
keys: make(chan byte, 16), keys: make(chan byte, 16),
@ -64,6 +73,11 @@ func NewApple2(p videoscan.Plotter, rom []byte, charRom [2048]byte) *Apple2 {
copy(a2.mem[len(a2.mem)-len(rom):len(a2.mem)], rom) copy(a2.mem[len(a2.mem)-len(rom):len(a2.mem)], rom)
a2.scanner = videoscan.NewScanner(a2, p, charRom) a2.scanner = videoscan.NewScanner(a2, p, charRom)
a2.cpu = cpu.NewCPU(a2, a2.Tick, cpu.VERSION_6502) a2.cpu = cpu.NewCPU(a2, a2.Tick, cpu.VERSION_6502)
for _, o := range options {
o(a2)
}
a2.cpu.Reset() a2.cpu.Reset()
return a2 return a2
} }
@ -106,28 +120,28 @@ func (a2 *Apple2) handleC00X(address uint16, value byte, write bool) byte {
} }
switch address { switch address {
case 0xC050: // GRAPHICS case 0xC050: // GRAPHICS
fmt.Printf("$%04X: GRAPHICS\n", a2.cpu.PC()) // fmt.Printf("$%04X: GRAPHICS\n", a2.cpu.PC())
a2.scanner.SetGraphics(true) a2.scanner.SetGraphics(true)
case 0xC051: // TEXT case 0xC051: // TEXT
fmt.Printf("$%04X: NO GRAPHICS\n", a2.cpu.PC()) // fmt.Printf("$%04X: NO GRAPHICS\n", a2.cpu.PC())
a2.scanner.SetGraphics(false) a2.scanner.SetGraphics(false)
case 0xC052: // NOMIX case 0xC052: // NOMIX
fmt.Printf("$%04X: NOMIX\n", a2.cpu.PC()) // fmt.Printf("$%04X: NOMIX\n", a2.cpu.PC())
a2.scanner.SetMix(false) a2.scanner.SetMix(false)
case 0xC053: // MIX case 0xC053: // MIX
fmt.Printf("$%04X: MIX\n", a2.cpu.PC()) // fmt.Printf("$%04X: MIX\n", a2.cpu.PC())
a2.scanner.SetMix(true) a2.scanner.SetMix(true)
case 0xC054: // PAGE 1 case 0xC054: // PAGE 1
fmt.Printf("$%04X: PAGE1\n", a2.cpu.PC()) // fmt.Printf("$%04X: PAGE1\n", a2.cpu.PC())
a2.scanner.SetPage(1) a2.scanner.SetPage(1)
case 0xC055: // PAGE 2 case 0xC055: // PAGE 2
fmt.Printf("$%04X: PAGE2\n", a2.cpu.PC()) // fmt.Printf("$%04X: PAGE2\n", a2.cpu.PC())
a2.scanner.SetPage(2) a2.scanner.SetPage(2)
case 0xC056: // LORES case 0xC056: // LORES
fmt.Printf("$%04X: LORES\n", a2.cpu.PC()) // fmt.Printf("$%04X: LORES\n", a2.cpu.PC())
a2.scanner.SetHires(false) a2.scanner.SetHires(false)
case 0xC057: // HIRES case 0xC057: // HIRES
fmt.Printf("$%04X: HIRES\n", a2.cpu.PC()) // fmt.Printf("$%04X: HIRES\n", a2.cpu.PC())
a2.scanner.SetHires(true) a2.scanner.SetHires(true)
} }
} }

View File

@ -2,7 +2,10 @@
package main package main
import ( import (
"flag"
"fmt" "fmt"
"io/ioutil"
"os"
"time" "time"
"github.com/nsf/termbox-go" "github.com/nsf/termbox-go"
@ -14,14 +17,17 @@ import (
// Mapping of screen bytes to character values // Mapping of screen bytes to character values
var AppleChars = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?" var AppleChars = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?"
var ColorFG = termbox.ColorGreen
var ColorBG = termbox.ColorBlack
// Translate to termbox // Translate to termbox
func translateToTermbox(value byte) (char rune, fg, bg termbox.Attribute) { func translateToTermbox(value byte) (char rune, fg, bg termbox.Attribute) {
// BUG(zellyn): change this to return char, MODE_ENUM. // BUG(zellyn): change this to return char, MODE_ENUM.
ch := rune(AppleChars[value&0x3F]) ch := rune(AppleChars[value&0x3F])
if value&0x80 > 0 { if value&0x80 > 0 {
return ch, termbox.ColorGreen, termbox.ColorBlack return ch, ColorFG, ColorBG
} }
return ch, termbox.ColorGreen, termbox.ColorBlack + termbox.AttrReverse return ch, ColorBG, ColorFG
} }
func termboxToAppleKeyboard(ev termbox.Event) (key byte, err error) { func termboxToAppleKeyboard(ev termbox.Event) (key byte, err error) {
@ -76,16 +82,32 @@ func (p TextPlotter) OncePerFrame() {
} }
// Run the emulator // Run the emulator
func RunEmulator() { func RunEmulator(file string) error {
rom := util.ReadRomOrDie("../data/roms/apple2+.rom") var options []goapple2.Option
if file != "" {
ColorFG = termbox.ColorDefault
ColorBG = termbox.ColorDefault
bytes, err := ioutil.ReadFile(file)
if err != nil {
return err
}
options = append(options, goapple2.WithRAM(0x6000, bytes))
}
rom := util.ReadRomOrDie("../data/roms/apple2+.rom", 12288)
charRom := util.ReadSmallCharacterRomOrDie("../data/roms/apple2-chars.rom") charRom := util.ReadSmallCharacterRomOrDie("../data/roms/apple2-chars.rom")
plotter := TextPlotter(0) plotter := TextPlotter(0)
a2 := goapple2.NewApple2(plotter, rom, charRom) a2 := goapple2.NewApple2(plotter, rom, charRom, options...)
if err := termbox.Init(); err != nil { if err := termbox.Init(); err != nil {
panic(err) return err
} }
events := make(chan termbox.Event) events := make(chan termbox.Event)
go func() { go func() {
if file != "" {
for _, ch := range "CALL 24576" {
a2.Keypress(byte(ch))
}
a2.Keypress(13)
}
for { for {
events <- termbox.PollEvent() events <- termbox.PollEvent()
} }
@ -99,8 +121,15 @@ func RunEmulator() {
time.Sleep(1 * time.Nanosecond) // So the keyboard-reading goroutines can run time.Sleep(1 * time.Nanosecond) // So the keyboard-reading goroutines can run
} }
termbox.Close() termbox.Close()
return nil
} }
var binfile = flag.String("binfile", "", "binary file to load at $6000 and CALL")
func main() { func main() {
RunEmulator() flag.Parse()
if err := RunEmulator(*binfile); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
} }