From 22a6e2967895e291e0cc97753aa7d4f4cebd3e53 Mon Sep 17 00:00:00 2001 From: Zellyn Hunter Date: Fri, 9 Sep 2016 20:49:21 -0400 Subject: [PATCH] texty: allow executing binary file --- goapple2.go | 32 +++++++++++++++++++++++--------- texty/texty.go | 43 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 16 deletions(-) diff --git a/goapple2.go b/goapple2.go index e4285da..8446be1 100644 --- a/goapple2.go +++ b/goapple2.go @@ -55,7 +55,16 @@ type Apple2 struct { 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{ // BUG(zellyn): this is not how the apple2 keyboard actually works 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) a2.scanner = videoscan.NewScanner(a2, p, charRom) a2.cpu = cpu.NewCPU(a2, a2.Tick, cpu.VERSION_6502) + + for _, o := range options { + o(a2) + } + a2.cpu.Reset() return a2 } @@ -106,28 +120,28 @@ func (a2 *Apple2) handleC00X(address uint16, value byte, write bool) byte { } switch address { case 0xC050: // GRAPHICS - fmt.Printf("$%04X: GRAPHICS\n", a2.cpu.PC()) + // fmt.Printf("$%04X: GRAPHICS\n", a2.cpu.PC()) a2.scanner.SetGraphics(true) 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) case 0xC052: // NOMIX - fmt.Printf("$%04X: NOMIX\n", a2.cpu.PC()) + // fmt.Printf("$%04X: NOMIX\n", a2.cpu.PC()) a2.scanner.SetMix(false) case 0xC053: // MIX - fmt.Printf("$%04X: MIX\n", a2.cpu.PC()) + // fmt.Printf("$%04X: MIX\n", a2.cpu.PC()) a2.scanner.SetMix(true) case 0xC054: // PAGE 1 - fmt.Printf("$%04X: PAGE1\n", a2.cpu.PC()) + // fmt.Printf("$%04X: PAGE1\n", a2.cpu.PC()) a2.scanner.SetPage(1) case 0xC055: // PAGE 2 - fmt.Printf("$%04X: PAGE2\n", a2.cpu.PC()) + // fmt.Printf("$%04X: PAGE2\n", a2.cpu.PC()) a2.scanner.SetPage(2) case 0xC056: // LORES - fmt.Printf("$%04X: LORES\n", a2.cpu.PC()) + // fmt.Printf("$%04X: LORES\n", a2.cpu.PC()) a2.scanner.SetHires(false) case 0xC057: // HIRES - fmt.Printf("$%04X: HIRES\n", a2.cpu.PC()) + // fmt.Printf("$%04X: HIRES\n", a2.cpu.PC()) a2.scanner.SetHires(true) } } diff --git a/texty/texty.go b/texty/texty.go index a38a3e1..36263ff 100644 --- a/texty/texty.go +++ b/texty/texty.go @@ -2,7 +2,10 @@ package main import ( + "flag" "fmt" + "io/ioutil" + "os" "time" "github.com/nsf/termbox-go" @@ -14,14 +17,17 @@ import ( // Mapping of screen bytes to character values var AppleChars = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ !\"#$%&'()*+,-./0123456789:;<=>?" +var ColorFG = termbox.ColorGreen +var ColorBG = termbox.ColorBlack + // Translate to termbox func translateToTermbox(value byte) (char rune, fg, bg termbox.Attribute) { // BUG(zellyn): change this to return char, MODE_ENUM. ch := rune(AppleChars[value&0x3F]) 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) { @@ -76,16 +82,32 @@ func (p TextPlotter) OncePerFrame() { } // Run the emulator -func RunEmulator() { - rom := util.ReadRomOrDie("../data/roms/apple2+.rom") +func RunEmulator(file string) error { + 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") plotter := TextPlotter(0) - a2 := goapple2.NewApple2(plotter, rom, charRom) + a2 := goapple2.NewApple2(plotter, rom, charRom, options...) if err := termbox.Init(); err != nil { - panic(err) + return err } events := make(chan termbox.Event) go func() { + if file != "" { + for _, ch := range "CALL 24576" { + a2.Keypress(byte(ch)) + } + a2.Keypress(13) + } for { events <- termbox.PollEvent() } @@ -99,8 +121,15 @@ func RunEmulator() { time.Sleep(1 * time.Nanosecond) // So the keyboard-reading goroutines can run } termbox.Close() + return nil } +var binfile = flag.String("binfile", "", "binary file to load at $6000 and CALL") + func main() { - RunEmulator() + flag.Parse() + if err := RunEmulator(*binfile); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } }