mirror of
https://github.com/sehugg/rustyapple.git
synced 2024-12-11 15:49:39 +00:00
started on lazy simple TUI
This commit is contained in:
parent
92ba23e8b3
commit
cae5e36d74
3
Makefile
3
Makefile
@ -4,5 +4,8 @@ RUSTC=rustc
|
||||
test:
|
||||
$(RUSTC) -Z debug-info -o appletest --test apple.rs
|
||||
./appletest
|
||||
|
||||
tui:
|
||||
$(RUSTC) -Z debug-info tui.rs
|
||||
|
||||
|
||||
|
16
a2.rs
16
a2.rs
@ -2,14 +2,14 @@
|
||||
use mem::Mem;
|
||||
use util::Xorshift;
|
||||
|
||||
static GR_TXMODE: int = 1;
|
||||
static GR_MIXMODE: int = 2;
|
||||
static GR_PAGE1: int = 4;
|
||||
static GR_HIRES: int = 8;
|
||||
pub static GR_TXMODE: u8 = 1;
|
||||
pub static GR_MIXMODE: u8 = 2;
|
||||
pub static GR_PAGE1: u8 = 4;
|
||||
pub static GR_HIRES: u8 = 8;
|
||||
|
||||
static HW_LO: u16 = 0xC000;
|
||||
static ROM_LO: u16 = 0xD000;
|
||||
static ROM_LEN: u16 = 0x3000;
|
||||
pub static HW_LO: u16 = 0xC000;
|
||||
pub static ROM_LO: u16 = 0xD000;
|
||||
pub static ROM_LEN: u16 = 0x3000;
|
||||
|
||||
pub trait Peripheral
|
||||
{
|
||||
@ -58,7 +58,7 @@ pub struct AppleII
|
||||
|
||||
debugflags: int,
|
||||
kbdlatch: u8,
|
||||
grswitch: u16,
|
||||
grswitch: u8,
|
||||
soundstate: bool,
|
||||
aux: LangCardState,
|
||||
nreads: u16 // counts # of reads for noise() fn
|
||||
|
145
lazyterm.rs
Normal file
145
lazyterm.rs
Normal file
@ -0,0 +1,145 @@
|
||||
|
||||
use std::vec;
|
||||
use std::io;
|
||||
use std::io::stdio::{StdReader,StdWriter};
|
||||
use std::io::Timer;
|
||||
|
||||
// TODO: use these but they are inconvenient
|
||||
pub struct TermColor(u8);
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct TermCell
|
||||
{
|
||||
bg: u8,
|
||||
fg: u8,
|
||||
ch: char
|
||||
}
|
||||
|
||||
//static BLACK: TermColor = TermColor(0);
|
||||
//static WHITE: TermColor = TermColor(15);
|
||||
pub static BLACK: u8 = 0;
|
||||
pub static WHITE: u8 = 15;
|
||||
|
||||
pub static EMPTY: TermCell = TermCell { fg:WHITE, bg:BLACK, ch:' ' };
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct Buffer
|
||||
{
|
||||
buf: ~[~[TermCell]],
|
||||
width: uint,
|
||||
height: uint,
|
||||
}
|
||||
|
||||
impl Buffer
|
||||
{
|
||||
pub fn new(cols: uint, rows: uint) -> Buffer
|
||||
{
|
||||
Buffer { width:cols, height:rows, buf:vec::from_elem(rows, vec::from_elem(cols, EMPTY)) }
|
||||
}
|
||||
|
||||
pub fn set(&mut self, col: uint, row: uint, cell: TermCell)
|
||||
{
|
||||
self.buf[row][col] = cell;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Terminal
|
||||
{
|
||||
hin : StdReader,
|
||||
hout: StdWriter,
|
||||
lastbuf: Buffer,
|
||||
}
|
||||
|
||||
impl Terminal
|
||||
{
|
||||
pub fn new() -> Terminal
|
||||
{
|
||||
Terminal { lastbuf: Buffer::new(0,0), hin: io::stdin(), hout: io::stdout() }
|
||||
}
|
||||
|
||||
fn reset(&mut self)
|
||||
{
|
||||
self.hout.write_str(format!("\x1b[0"));
|
||||
}
|
||||
|
||||
fn update(&mut self, buf: &Buffer)
|
||||
{
|
||||
let ref mut hout = self.hout;
|
||||
let mut prev = EMPTY;
|
||||
for y in range(0,buf.height)
|
||||
{
|
||||
for x in range(0,buf.width)
|
||||
{
|
||||
let cell = buf.buf[y][x];
|
||||
let last = self.lastbuf.buf[y][x];
|
||||
let mut dirty = false;
|
||||
if (cell.fg != prev.fg)
|
||||
{
|
||||
hout.write_str(format!("\x1b[38;5;{}m", cell.fg));
|
||||
dirty = true;
|
||||
}
|
||||
if (cell.bg != prev.bg)
|
||||
{
|
||||
hout.write_str(format!("\x1b[48;5;{}m", cell.bg));
|
||||
dirty = true;
|
||||
}
|
||||
// TODO
|
||||
//if (dirty || cell.ch != last.ch)
|
||||
{
|
||||
hout.write_char(cell.ch);
|
||||
}
|
||||
prev = cell;
|
||||
}
|
||||
hout.write_char('\n');
|
||||
}
|
||||
}
|
||||
|
||||
fn redraw(&mut self, buf: &Buffer)
|
||||
{
|
||||
let ref mut hout = self.hout;
|
||||
for y in range(0,buf.height)
|
||||
{
|
||||
for x in range(0,buf.width)
|
||||
{
|
||||
let cell = buf.buf[y][x];
|
||||
hout.write_str(format!("\x1b[38;5;{}m", cell.fg));
|
||||
hout.write_str(format!("\x1b[48;5;{}m", cell.bg));
|
||||
hout.write_char(cell.ch);
|
||||
}
|
||||
hout.write_char('\n');
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self, buf: &Buffer)
|
||||
{
|
||||
self.reset();
|
||||
if buf.width == self.lastbuf.width && buf.height == self.lastbuf.height
|
||||
{
|
||||
// scroll up N lines
|
||||
self.hout.write_str(format!("\x1b[{}A", buf.height));
|
||||
// update dirty cells
|
||||
self.update(buf);
|
||||
} else {
|
||||
// redraw entire window
|
||||
// TODO: rescroll window
|
||||
self.redraw(buf);
|
||||
}
|
||||
self.reset();
|
||||
self.lastbuf = buf.clone();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
fn main()
|
||||
{
|
||||
let mut buf = Buffer::new(40,24);
|
||||
let mut term = Terminal::new();
|
||||
let mut timer = Timer::new().unwrap();
|
||||
for i in range(0u8,15)
|
||||
{
|
||||
buf.set(1, 1, TermCell { bg:i, fg:i+1, ch:'#' } );
|
||||
term.refresh(&buf);
|
||||
timer.sleep(50);
|
||||
}
|
||||
}
|
104
tui.rs
Normal file
104
tui.rs
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
#[feature(link_args, macro_rules)];
|
||||
|
||||
use cpu::Cpu;
|
||||
use mem::Mem;
|
||||
use a2::AppleII;
|
||||
use a2::Peripheral;
|
||||
use diskii::DiskController;
|
||||
use util::current_time_millis;
|
||||
use lazyterm::{Terminal,Buffer};
|
||||
|
||||
// NB: This must be first to pick up the macro definitions. What a botch.
|
||||
#[macro_escape]
|
||||
pub mod util;
|
||||
|
||||
#[macro_escape]
|
||||
pub mod cpu;
|
||||
pub mod mem;
|
||||
pub mod a2;
|
||||
pub mod diskii;
|
||||
|
||||
pub mod lazyterm;
|
||||
|
||||
static text_lut: [u16, ..8*3] = [
|
||||
0x000, 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380,
|
||||
0x028, 0x0a8, 0x128, 0x1a8, 0x228, 0x2a8, 0x328, 0x3a8,
|
||||
0x050, 0x0d0, 0x150, 0x1d0, 0x250, 0x2d0, 0x350, 0x3d0
|
||||
];
|
||||
|
||||
static flashInterval: u64 = 500;
|
||||
|
||||
fn draw_text_line(a2: &AppleII, buf: &mut Buffer, flash: bool, y: uint)
|
||||
{
|
||||
// get the base address of this line
|
||||
let base = text_lut[y] + if (a2.grswitch & a2::GR_PAGE1) != 0 { 0x800 } else { 0x400 };
|
||||
for x in range(0u,40)
|
||||
{
|
||||
let mut b = a2.mem[base + x as u16];
|
||||
let invert: bool;
|
||||
// invert flash characters 1/2 of the time
|
||||
if (b >= 0x80)
|
||||
{
|
||||
invert = false;
|
||||
}
|
||||
else if (b >= 0x40)
|
||||
{
|
||||
invert = flash;
|
||||
if (flash) { b -= 0x40; } else { b += 0x40; }
|
||||
}
|
||||
else
|
||||
{
|
||||
invert = true;
|
||||
}
|
||||
// if the char. changed, draw it
|
||||
let ch = (b & 0x7f) as char;
|
||||
let cell = lazyterm::TermCell { fg:lazyterm::WHITE, bg:lazyterm::BLACK, ch:ch };
|
||||
buf.set(x, y, cell);
|
||||
//drawTextChar(x, y, b & 0x7f, invert);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_term_buf(a2: &AppleII, buf: &mut Buffer, flash: bool)
|
||||
{
|
||||
for y in range(0u,24)
|
||||
{
|
||||
draw_text_line(a2, buf, flash, y);
|
||||
}
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
let mut a2 = AppleII::new();
|
||||
a2.read_roms();
|
||||
let mut dc: DiskController = DiskController::new();
|
||||
dc.load_disk(0, "JUNK4.DSK");
|
||||
assert!(dc.has_disk(0));
|
||||
a2.set_slot(6, ~dc);
|
||||
let mut cpu = Cpu::new(a2);
|
||||
cpu.reset();
|
||||
|
||||
let mut term = Terminal::new();
|
||||
let mut buf = Buffer::new(40,24);
|
||||
|
||||
// mismatched types: expected `<generic integer #5>` but found `<generic float #0>`
|
||||
let speedup = 2;
|
||||
let clocks_per_msec = (1000 * speedup);
|
||||
let mut t0 = current_time_millis();
|
||||
loop
|
||||
{
|
||||
// cursor flashing?
|
||||
let flash = (t0 % (flashInterval<<1)) > flashInterval;
|
||||
update_term_buf(&cpu.mem, &mut buf, flash);
|
||||
term.refresh(&buf);
|
||||
|
||||
let t1 = current_time_millis();
|
||||
let cycle = cpu.cy + (t1-t0)*clocks_per_msec;
|
||||
while cpu.cy < cycle
|
||||
{
|
||||
cpu.step();
|
||||
}
|
||||
t0 = t1;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user