Skip to content
This repository has been archived by the owner on Apr 10, 2024. It is now read-only.

Commit

Permalink
Introduced IGS screen & terminal mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
mkrueger committed Feb 10, 2024
1 parent dc01a2a commit e81b1c3
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 45 deletions.
2 changes: 1 addition & 1 deletion src/com/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl ComRawImpl {
pub fn connect(connection_data: &OpenConnectionData) -> TermComResult<Self> {
let addr = connection_data.address.to_string();

let Some(a) = connection_data.address.to_socket_addrs().unwrap().next() else {
let Some(a) = connection_data.address.to_socket_addrs()?.next() else {
return Err(Box::new(io::Error::new(ErrorKind::InvalidInput, format!("Invalid address: {addr}"))));
};

Expand Down
5 changes: 3 additions & 2 deletions src/com/telnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ impl ComTelnetImpl {
if !addr.contains(':') {
addr += ":23";
}
let Some(a) = connection_data.address.to_socket_addrs().unwrap().next() else {
let Some(a) = connection_data.address.to_socket_addrs()?.next() else {
return Err(Box::new(io::Error::new(ErrorKind::InvalidInput, format!("Invalid address: {addr}"))));
};

Expand Down Expand Up @@ -362,6 +362,7 @@ impl ComTelnetImpl {
Terminal::Ascii => buf.extend_from_slice(b"RAW"),
Terminal::Avatar => buf.extend_from_slice(b"AVATAR"),
Terminal::Rip => buf.extend_from_slice(b"RIP"),
Terminal::IGS => buf.extend_from_slice(b"IGS"),
}
buf.extend([telnet_cmd::Iac, telnet_cmd::SE]);

Expand Down Expand Up @@ -492,7 +493,7 @@ impl Com for ComTelnetImpl {
}

fn read_data(&mut self) -> TermComResult<Option<Vec<u8>>> {
let mut buf: [u8; 262144] = [0; 1024 * 256];
let mut buf: [u8; 262_144] = [0; 1024 * 256];
self.tcp_stream.set_nonblocking(true)?;
match self.tcp_stream.read(&mut buf) {
Ok(size) => {
Expand Down
31 changes: 19 additions & 12 deletions src/data/addresses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ use crate::ui::screen_modes::ScreenMode;
use crate::TerminalResult;
use chrono::{Duration, Utc};
use icy_engine::ansi::{BaudEmulation, MusicOption};
use icy_engine::igs::CommandExecutor;
use icy_engine::{ansi, ascii, atascii, avatar, petscii, rip, viewdata, BufferParser, UnicodeConverter};
use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
use regex::Regex;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::sync::Arc;
use std::{
fmt::Display,
fs::{self},
Expand All @@ -26,17 +28,19 @@ pub enum Terminal {
ATAscii,
ViewData,
Rip,
IGS,
}

impl Terminal {
pub const ALL: [Terminal; 7] = [
pub const ALL: [Terminal; 8] = [
Terminal::Ansi,
Terminal::Avatar,
Terminal::Ascii,
Terminal::PETscii,
Terminal::ATAscii,
Terminal::ViewData,
Terminal::Rip,
Terminal::IGS,
];

#[must_use]
Expand All @@ -60,13 +64,18 @@ impl Terminal {
let parser = rip::Parser::new(Box::new(parser), cache_directory);
Box::new(parser)
}
Terminal::IGS => {
let ig_executor: Arc<std::sync::Mutex<Box<dyn CommandExecutor>>> =
Arc::new(std::sync::Mutex::new(Box::<icy_engine::parsers::igs::DrawExecutor>::default()));
Box::new(icy_engine::igs::Parser::new(ig_executor))
}
}
}

#[must_use]
pub fn get_unicode_converter(&self) -> Box<dyn UnicodeConverter> {
match self {
Terminal::Ansi | Terminal::Avatar | Terminal::Ascii | Terminal::Rip => Box::<ascii::CP437Converter>::default(),
Terminal::Ansi | Terminal::Avatar | Terminal::Ascii | Terminal::Rip | Terminal::IGS => Box::<ascii::CP437Converter>::default(),
Terminal::PETscii => Box::<petscii::CharConverter>::default(),
Terminal::ATAscii => Box::<atascii::CharConverter>::default(),
Terminal::ViewData => Box::<viewdata::CharConverter>::default(),
Expand All @@ -83,7 +92,8 @@ impl Display for Terminal {
Terminal::PETscii => write!(f, "PETSCII"),
Terminal::ATAscii => write!(f, "ATASCII"),
Terminal::ViewData => write!(f, "VIEWDATA"),
Terminal::Rip => write!(f, "Rip"),
Terminal::Rip => write!(f, "RIPscrip"),
Terminal::IGS => write!(f, "IGS"),
}
}
}
Expand Down Expand Up @@ -174,7 +184,6 @@ pub struct Address {
pub ice_mode: bool,
pub ansi_music: MusicOption,
pub baud_emulation: BaudEmulation,
pub use_igs: bool,

pub font_name: Option<String>,
pub screen_mode: ScreenMode,
Expand Down Expand Up @@ -286,7 +295,6 @@ impl Address {
override_iemsi_settings: false,
iemsi_user: String::new(),
iemsi_password: String::new(),
use_igs: false,
}
}

Expand Down Expand Up @@ -579,6 +587,7 @@ fn parse_address(value: &Value) -> Address {
"atascii" => result.terminal_type = Terminal::ATAscii,
"viewdata" => result.terminal_type = Terminal::ViewData,
"rip" => result.terminal_type = Terminal::Rip,
"igs" => result.terminal_type = Terminal::IGS,
_ => {}
}
}
Expand All @@ -592,9 +601,6 @@ fn parse_address(value: &Value) -> Address {
}
}
}
if let Some(Value::Boolean(value)) = table.get("use_igs") {
result.use_igs = *value;
}

if let Some(Value::String(name)) = table.get("screen_mode") {
let lower_name = &name.to_lowercase();
Expand All @@ -604,6 +610,7 @@ fn parse_address(value: &Value) -> Address {
"antic" => result.screen_mode = ScreenMode::Antic,
"videotex" => result.screen_mode = ScreenMode::Videotex,
"rip" => result.screen_mode = ScreenMode::Rip,
"igs" => result.screen_mode = ScreenMode::Igs,
_ => {
if let Some(caps) = vga_regex.captures(lowercase) {
let mut width = 80;
Expand Down Expand Up @@ -680,10 +687,6 @@ fn store_address(file: &mut File, addr: &Address) -> TerminalResult<()> {
file.write_all(format!("baud_emulation = \"{}\"\n", addr.baud_emulation).as_bytes())?;
}

if addr.use_igs {
file.write_all(format!("use_igs = {}\n", addr.use_igs).as_bytes())?;
}

if addr.screen_mode != ScreenMode::default() {
file.write_all(format!("screen_mode = \"{:?}\"\n", addr.screen_mode).as_bytes())?;
}
Expand Down Expand Up @@ -774,6 +777,10 @@ fn parse_legacy_address(value: &Value) -> Address {
result.screen_mode = ScreenMode::Rip;
result.terminal_type = Terminal::Rip;
}
"Igs" => {
result.screen_mode = ScreenMode::Igs;
result.terminal_type = Terminal::IGS;
}
_ => {}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/features/iemsi_com.rs
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ fn encode_emsi(data: &[&str]) -> TerminalResult<Vec<u8>> {
#[cfg(test)]
mod tests {
#![allow(clippy::field_reassign_with_default)]
use crate::{Address, Options};
use crate::Address;

use super::*;

Expand Down
2 changes: 0 additions & 2 deletions src/ui/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ impl MainWindow {
sound_thread: Arc::new(eframe::epaint::mutex::Mutex::new(SoundThread::new())),
enabled: true,
terminal_type: None,
use_igs: false,
use_rip: false,
mouse_field: Vec::new(),
cache_directory: PathBuf::new(),
}));
Expand Down
23 changes: 5 additions & 18 deletions src/ui/buffer_update_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use crate::{
use egui::mutex::Mutex;
use icy_engine::{
ansi::{self, MusicOption},
igs::CommandExecutor,
rip::bgi::MouseField,
BufferParser, Caret,
};
Expand All @@ -33,9 +32,6 @@ pub struct BufferUpdateThread {
pub auto_transfer: Option<(TransferType, bool)>,
pub enabled: bool,

pub use_igs: bool,
pub use_rip: bool,

pub terminal_type: Option<(Terminal, MusicOption)>,

pub mouse_field: Vec<MouseField>,
Expand All @@ -58,6 +54,7 @@ impl BufferUpdateThread {
} else {
Vec::new()
};

Ok(data)
}
pub fn update_state(&mut self, ctx: &egui::Context, buffer_parser: &mut dyn BufferParser, data: &[u8]) -> TerminalResult<(u64, usize)> {
Expand Down Expand Up @@ -243,11 +240,6 @@ pub fn run_update_thread(ctx: &egui::Context, update_thread: Arc<Mutex<BufferUpd
let lock = &mut update_thread.lock();
if let Some((te, b)) = lock.terminal_type.take() {
buffer_parser = te.get_parser(b, lock.cache_directory.clone());
if lock.use_igs {
let ig_executor: Arc<std::sync::Mutex<Box<dyn CommandExecutor>>> =
Arc::new(std::sync::Mutex::new(Box::<icy_engine::parsers::igs::DrawExecutor>::default()));
buffer_parser = Box::new(icy_engine::igs::Parser::new(buffer_parser, ig_executor));
}
}
}
let update_state = update_thread.lock().update_state(&ctx, &mut *buffer_parser, &data[idx..]);
Expand All @@ -257,15 +249,10 @@ pub fn run_update_thread(ctx: &egui::Context, update_thread: Arc<Mutex<BufferUpd
idx = data.len();
}
Ok((sleep_ms, parsed_data)) => {
if update_thread.lock().use_igs {
update_thread.lock().buffer_view.lock().set_igs_executor(buffer_parser.get_picture_data());
}
if update_thread.lock().use_rip {
let data = buffer_parser.get_picture_data();
if data.is_some() {
update_thread.lock().mouse_field = buffer_parser.get_mouse_fields();
update_thread.lock().buffer_view.lock().set_reference_image(data);
}
let data = buffer_parser.get_picture_data();
if data.is_some() {
update_thread.lock().mouse_field = buffer_parser.get_mouse_fields();
update_thread.lock().buffer_view.lock().set_reference_image(data);
}
if sleep_ms > 0 {
thread::sleep(Duration::from_millis(sleep_ms));
Expand Down
9 changes: 8 additions & 1 deletion src/ui/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ pub struct Connection {

impl DataConnection for Connection {
fn is_data_available(&mut self) -> TerminalResult<bool> {
self.fill_buffer()?;
if let Err(err) = self.fill_buffer() {
log::error!("Error in is_data_available: {err}");
self.is_connected = false;
return Err(err);
}
Ok(!self.buf.is_empty())
}

Expand Down Expand Up @@ -124,6 +128,9 @@ impl Connection {
Err(err) => match err {
mpsc::TryRecvError::Empty => break,
mpsc::TryRecvError::Disconnected => {
if !self.is_connected {
break;
}
self.is_connected = false;
return Err(anyhow::anyhow!("disconnected: {err}"));
}
Expand Down
2 changes: 0 additions & 2 deletions src/ui/dialogs/dialing_directory_dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,8 +509,6 @@ impl DialogState {
});
ui.end_row();
});

ui.checkbox(&mut adr.use_igs, "Instant Graphics and Sound");
}

fn render_login_category(&mut self, ui: &mut egui::Ui) {
Expand Down
2 changes: 0 additions & 2 deletions src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,7 @@ impl MainWindow {
self.buffer_update_thread.lock().cache_directory = rip_cache;
}

self.buffer_update_thread.lock().use_igs = address.use_igs;
self.use_rip = matches!(address.terminal_type, crate::Terminal::Rip);
self.buffer_update_thread.lock().use_rip = self.use_rip;
self.buffer_update_thread.lock().terminal_type = Some((address.terminal_type, address.ansi_music));
self.buffer_update_thread.lock().auto_file_transfer.reset();
self.buffer_view.lock().set_igs_executor(None);
Expand Down
24 changes: 20 additions & 4 deletions src/ui/util/screen_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum ScreenMode {
Antic,
Videotex,
Rip,
Igs,
}

impl Default for ScreenMode {
Expand All @@ -34,7 +35,7 @@ impl ScreenMode {
}
}

pub const DEFAULT_MODES: [ScreenMode; 12] = [
pub const DEFAULT_MODES: [ScreenMode; 13] = [
ScreenMode::Vga(80, 25),
ScreenMode::Vga(80, 50),
ScreenMode::Vga(132, 37),
Expand All @@ -47,6 +48,7 @@ pub const DEFAULT_MODES: [ScreenMode; 12] = [
ScreenMode::Default,
ScreenMode::Rip,
ScreenMode::Videotex,
ScreenMode::Igs,
];

impl Display for ScreenMode {
Expand All @@ -65,7 +67,8 @@ impl Display for ScreenMode {
ScreenMode::Antic => write!(f, "ANTIC"),
ScreenMode::Videotex => write!(f, "VIDEOTEX"),
ScreenMode::Default => write!(f, "Default"),
ScreenMode::Rip => write!(f, "Rip"),
ScreenMode::Rip => write!(f, "RIPscrip"),
ScreenMode::Igs => write!(f, "Igs"),
}
}
}
Expand All @@ -74,7 +77,7 @@ impl ScreenMode {
pub fn get_input_mode(&self) -> BufferInputMode {
match self {
//ScreenMode::Cga(_, _) | ScreenMode::Ega(_, _) |
ScreenMode::Default | ScreenMode::Vga(_, _) | ScreenMode::Rip => BufferInputMode::CP437,
ScreenMode::Default | ScreenMode::Vga(_, _) | ScreenMode::Rip | ScreenMode::Igs => BufferInputMode::CP437,
ScreenMode::Vic => BufferInputMode::PETscii,
ScreenMode::Antic => BufferInputMode::ATAscii,
ScreenMode::Videotex => BufferInputMode::ViewData,
Expand All @@ -85,7 +88,7 @@ impl ScreenMode {
match self {
// ScreenMode::Cga(w, h) | ScreenMode::Ega(w, h) |
ScreenMode::Vga(w, h) => Size::new(*w, *h),
ScreenMode::Vic => Size::new(40, 25),
ScreenMode::Vic | ScreenMode::Igs => Size::new(40, 25),
ScreenMode::Antic | ScreenMode::Videotex => Size::new(40, 24),
ScreenMode::Default => Size::new(80, 25),
ScreenMode::Rip => Size::new(80, 44),
Expand Down Expand Up @@ -150,6 +153,17 @@ impl ScreenMode {
.set_font(0, BitFont::from_sauce_name("IBM VGA50").unwrap());
main_window.buffer_view.lock().get_buffer_mut().palette = Palette::dos_default();
}

ScreenMode::Igs => {
main_window.buffer_view.lock().get_buffer_mut().clear_font_table();
main_window
.buffer_view
.lock()
.get_buffer_mut()
.set_font(0, BitFont::from_bytes("", ATARI).unwrap());

main_window.buffer_view.lock().get_buffer_mut().palette = Palette::from_slice(&C64_DEFAULT_PALETTE);
}
}
main_window.buffer_view.lock().get_buffer_mut().layers[0].clear();
main_window.buffer_view.lock().get_buffer_mut().stop_sixel_threads();
Expand All @@ -162,6 +176,7 @@ impl ScreenMode {
ScreenMode::Vic => Color::new(0x37, 0x39, 0xC4),
ScreenMode::Antic => Color::new(0x09, 0x51, 0x83),
ScreenMode::Videotex => Color::new(0, 0, 0),
ScreenMode::Igs => Color::new(0, 0, 0),
}
}

Expand All @@ -172,6 +187,7 @@ impl ScreenMode {
ScreenMode::Vic => Color::new(0xB0, 0x3F, 0xB6),
ScreenMode::Antic => Color::new(0xFF, 0xFF, 0xFF),
ScreenMode::Videotex => Color::new(0xFF, 0xFF, 0xFF),
ScreenMode::Igs => Color::new(0xFF, 0xFF, 0xFF),
}
}
}

0 comments on commit e81b1c3

Please sign in to comment.