Skip to content

Commit

Permalink
Ensure we preserve the state of user/drives across restarts
Browse files Browse the repository at this point in the history
  • Loading branch information
skx authored and ivanizag committed Jun 22, 2024
1 parent 6933396 commit f4183d3
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 21 deletions.
13 changes: 9 additions & 4 deletions src/bdos_drive.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::bdos_environment::*;
use super::constants::*;
use iz80::Machine;

pub fn select(env: &mut BdosEnvironment, selected: u8) {
// The Select Disk function designates the disk drive named in register E as
Expand All @@ -15,6 +16,10 @@ pub fn select(env: &mut BdosEnvironment, selected: u8) {
// directly reference drives A through P.
env.state.drive = selected & 0x0f;
env.state.selected_bitmap |= 1 << env.state.drive;


// Update the RAM bye to mark our drive/user in a persistent way.
env.machine.poke(CCP_USER_DRIVE_ADDRESS, env.state.user << 4 | env.state.drive)
}

pub fn get_current(env: &BdosEnvironment) -> u8 {
Expand All @@ -33,7 +38,7 @@ pub fn get_log_in_vector(env: &BdosEnvironment) -> u16 {
// or an implicit drive select caused by a file operation that specified a
// nonzero dr field. The user should note that compatibility is maintained
// with earlier releases, because registers A and L contain the same values
// upon return.
// upon return.
env.state.selected_bitmap
}

Expand All @@ -51,7 +56,7 @@ pub fn get_read_only_vector(env: &BdosEnvironment) -> u16 {
// least significant bit corresponds to drive A, while the most significant
// bit corresponds to drive P. The R/O bit is set either by an explicit call
// to Function 28 or by the automatic software mechanisms within CP/M that
// detect changed disks.
// detect changed disks.
env.state.read_only_bitmap
}

Expand All @@ -64,7 +69,7 @@ pub fn get_disk_allocation_vector(_env: &BdosEnvironment) -> u16 {
// information might be invalid if the selected disk has been marked
// Read-Only. Although this function is not normally used by application
// programs, additional details of the allocation vector are found in
// Section 6.
// Section 6.
BDOS_ALVEC0_ADDRESS
}

Expand All @@ -91,4 +96,4 @@ pub fn reset_drives(env: &mut BdosEnvironment, drives: u16) -> u8 {
env.state.selected_bitmap |= 1 << env.state.drive;

0
}
}
4 changes: 1 addition & 3 deletions src/bdos_environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ impl BdosState {
}

pub fn reset(&mut self) {
self.user = 0;
self.drive = 0;
self.selected_bitmap = 1<<0;
self.read_only_bitmap = 0;
self.dma = DEFAULT_DMA;
Expand Down Expand Up @@ -77,7 +75,7 @@ impl <'a> BdosEnvironment<'_> {
self.machine.peek(IOBYTE_ADDRESS) & 0x0f
}
pub fn set_iobyte(&mut self, iobyte: u8) {
self.machine.poke(IOBYTE_ADDRESS, iobyte);
self.machine.poke(IOBYTE_ADDRESS, iobyte);
}

pub fn load_buffer(&mut self) {
Expand Down
19 changes: 13 additions & 6 deletions src/bdos_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use std::path::Path;
use std::path::PathBuf;

use super::bdos_environment::*;
use super::constants::*;
use super::fcb::*;
use iz80::Machine;

// Many file processing functions return a value in register A that is either
// OFFH, indicating that the file named in the FCB could not be found, or equal
Expand Down Expand Up @@ -37,7 +39,7 @@ pub fn set_dma(env: &mut BdosEnvironment, dma: u16) {
// another area of memory where the data records reside. Thus, the DMA
// address becomes the value specified by DE until it is changed by a
// subsequent Set DMA function, cold start, warm start, or disk system
// reset.
// reset.
env.state.dma = dma;
}

Expand All @@ -58,7 +60,7 @@ pub fn open(env: &mut BdosEnvironment, fcb_address: u16) -> u8 {
// decimal) if the file cannot be found. If question marks occur in the FCB,
// the first matching FCB is activated. Note that the current record, (cr)
// must be zeroed by the program if the file is to be accessed sequentially
// from the first record.
// from the first record.
let mut fcb = Fcb::new(fcb_address);
if env.call_trace {
print!("[[Open file {}]]", fcb.get_name_for_log(env));
Expand Down Expand Up @@ -110,7 +112,7 @@ pub fn close(env: &mut BdosEnvironment, fcb_address: u16) -> u8 {
// 3, while a 0FFH (255 decimal) is returned if the filename cannot be found
// in the directory. A file need not be closed if only read operations have
// taken place. If write operations have occurred, the close operation is
// necessary to record the new directory information permanently.
// necessary to record the new directory information permanently.
let fcb = Fcb::new(fcb_address);
match find_host_files(env, &fcb, false, false){
Err(_) => FILE_NOT_FOUND, // Error or file not found
Expand Down Expand Up @@ -172,7 +174,7 @@ pub fn rename(env: &mut BdosEnvironment, fcb_address: u16) -> u8 {
// drive, while the drive code for the new filename at position 16 of the
// FCB is assumed to be zero. Upon return, register A is set to a value
// between 0 and 3 if the rename was successful and 0FFH (255 decimal) if
// the first filename could not be found in the directory scan.
// the first filename could not be found in the directory scan.
let fcb = Fcb::new(fcb_address);
if env.call_trace {
print!("[[Rename file {} to {}]]", fcb.get_name_for_log(env), fcb.get_name_secondary(env));
Expand Down Expand Up @@ -360,7 +362,12 @@ pub fn get_set_user_number(env: &mut BdosEnvironment, user: u8) -> u8 {
*/
if user != 0xff {
env.state.user = user & 0x0f;

// Update the RAM bye to mark our drive/user in a persistent way.
env.machine.poke(CCP_USER_DRIVE_ADDRESS, env.state.user << 4 | env.state.drive)

}

env.state.user
}

Expand Down Expand Up @@ -432,7 +439,7 @@ pub fn search_first(env: &mut BdosEnvironment, fcb_address: u16) -> u8 {
// entry, allocated or free, belonging to any user number. This latter
// function is not normally used by application programs, but it allows
// complete flexibility to scan all current directory values. If the dr
// field is not a question mark, the s2 byte is automatically zeroed.
// field is not a question mark, the s2 byte is automatically zeroed.
let fcb = Fcb::new(fcb_address);
if env.call_trace {
print!("[[DIR start {}]]", fcb.get_name_for_log(env));
Expand All @@ -447,7 +454,7 @@ pub fn search_next(env: &mut BdosEnvironment) -> u8 {
// The Search Next function is similar to the Search First function, except
// that the directory scan continues from the last matched entry. Similar to
// Function 17, Function 18 returns the decimal value 255 in A when no more
// directory items match.
// directory items match.
search_nth(env).unwrap_or(FILE_NOT_FOUND)
}

Expand Down
17 changes: 9 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn main() {
.arg(Arg::with_name("ccp")
.long("ccp")
.value_name("ccp")
.help("Alternative CPP bynary, it must be compiled with CCP_BASE=$f000"))
.help("Alternative CPP binary, it must be compiled with CCP_BASE=$f000"))
.arg(Arg::with_name("disk_a").long("disk-a").value_name("path").short("a").default_value(".").help("directory to map disk A:"))
.arg(Arg::with_name("disk_b").long("disk-b").value_name("path").short("b").help("directory to map disk B:"))
.arg(Arg::with_name("disk_c").long("disk-c").value_name("path").short("c").help("directory to map disk C:"))
Expand Down Expand Up @@ -123,7 +123,7 @@ fn main() {
Some("adm3a") => Box::new(Adm3aToAnsi::new()),
Some("ansi") => Box::new(Transparent::new()),
_ => {
eprintln!("Unkown terminal emulattion. Choose \"adm3a\" or \"ansi\".");
eprintln!("Unkown terminal emulation. Choose \"adm3a\" or \"ansi\".");
return;
}
};
Expand Down Expand Up @@ -219,7 +219,7 @@ fn main() {
if !use_tpa {
// Upon entry to a transient program, the CCP leaves the stack pointer
// set to an eight-level stack area with the CCP return address pushed
// onto the stack, leaving seven levels before overflow occurs.
// onto the stack, leaving seven levels before overflow occurs.
if binary_address == TPA_BASE_ADDRESS {
let mut sp = TPA_STACK_ADDRESS;
// Push 0x0000
Expand All @@ -235,7 +235,7 @@ fn main() {
// the operator following the program name. The first position contains
// the number of characters, with the characters themselves following
// the character count. The characters are translated to upper-case
// ASCII with uninitialized memory following the last valid character.
// ASCII with uninitialized memory following the last valid character.
Fcb::new(FCB1_ADDRESS).set_name_direct(&mut machine, " . ".to_string());
Fcb::new(FCB2_ADDRESS).set_name_direct(&mut machine, " . ".to_string());
match params {
Expand Down Expand Up @@ -306,7 +306,7 @@ fn main() {
er = bdos.execute(&mut bios, &mut machine, cpu.registers(),
call_trace || call_trace_all, call_trace && ! call_trace_all);
}

match er {
ExecutionResult::Continue => (),
ExecutionResult::Stop => {
Expand Down Expand Up @@ -346,13 +346,14 @@ fn main() {
machine.poke(binary_address + i as u16, binary[i]);
}
cpu.registers().set_pc(binary_address);
cpu.registers().set8(Reg8::C, 0); // Reset user and drive
let user_drive = machine.peek(CCP_USER_DRIVE_ADDRESS);
cpu.registers().set8(Reg8::C, user_drive);
bdos.reset(&mut machine); // Reset Bdos
} else {
break;
}
}


}

Expand All @@ -364,4 +365,4 @@ fn main() {
}
}
}
}
}

0 comments on commit f4183d3

Please sign in to comment.