mirror of
https://github.com/G2-Games/minidisc-cli.git
synced 2025-05-02 17:52:54 -05:00
Added mappings file, implemented sanitize_full_width_title
This commit is contained in:
parent
4a7f95d081
commit
9aa09343c5
8 changed files with 457 additions and 109 deletions
|
@ -10,6 +10,7 @@ license = "AGPL-3.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rusb = "0.9.3"
|
rusb = "0.9.3"
|
||||||
|
translit = "0.5.0"
|
||||||
|
|
||||||
[dependencies.minidisc-rs]
|
[dependencies.minidisc-rs]
|
||||||
path = "minidisc-rs"
|
path = "minidisc-rs"
|
||||||
|
|
|
@ -16,4 +16,6 @@ encoding_rs = "0.8.33"
|
||||||
nofmt = "1.0.0"
|
nofmt = "1.0.0"
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
rusb = "0.9.3"
|
rusb = "0.9.3"
|
||||||
|
translit = "0.5.0"
|
||||||
|
unicode-jp = "0.4.0"
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use crate::netmd::query_utils::{format_query, scan_query};
|
|
||||||
use crate::netmd::utils::{length_after_encoding_to_jis, half_width_to_full_width_range};
|
|
||||||
use crate::netmd::base;
|
use crate::netmd::base;
|
||||||
|
use crate::netmd::query_utils::{format_query, scan_query, QueryValue};
|
||||||
|
use crate::netmd::utils::{
|
||||||
|
half_width_to_full_width_range, length_after_encoding_to_jis, sanitize_full_width_title,
|
||||||
|
};
|
||||||
use encoding_rs::*;
|
use encoding_rs::*;
|
||||||
|
use rusb;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use rusb;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum Action {
|
enum Action {
|
||||||
|
@ -182,7 +184,10 @@ impl NetMDInterface {
|
||||||
const MAX_INTERIM_READ_ATTEMPTS: u8 = 4;
|
const MAX_INTERIM_READ_ATTEMPTS: u8 = 4;
|
||||||
const INTERIM_RESPONSE_RETRY_INTERVAL: u32 = 100;
|
const INTERIM_RESPONSE_RETRY_INTERVAL: u32 = 100;
|
||||||
|
|
||||||
pub fn new(device: rusb::DeviceHandle<rusb::GlobalContext>, descriptor: rusb::DeviceDescriptor) -> Result<Self, Box<dyn Error>> {
|
pub fn new(
|
||||||
|
device: rusb::DeviceHandle<rusb::GlobalContext>,
|
||||||
|
descriptor: rusb::DeviceDescriptor,
|
||||||
|
) -> Result<Self, Box<dyn Error>> {
|
||||||
let net_md_device = base::NetMD::new(device, descriptor).unwrap();
|
let net_md_device = base::NetMD::new(device, descriptor).unwrap();
|
||||||
Ok(NetMDInterface { net_md_device })
|
Ok(NetMDInterface { net_md_device })
|
||||||
}
|
}
|
||||||
|
@ -204,15 +209,14 @@ impl NetMDInterface {
|
||||||
&DescriptorAction::OpenRead,
|
&DescriptorAction::OpenRead,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut query = format_query(
|
let mut query = format_query("1809 00 ff00 0000 0000".to_string(), vec![])?;
|
||||||
"1809 00 ff00 0000 0000".to_string(),
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
|
||||||
let res = scan_query(reply, "1809 00 1000 %?%? %?%? %w %b %b %b %b %w %*".to_string())?;
|
let res = scan_query(
|
||||||
|
reply,
|
||||||
|
"1809 00 1000 %?%? %?%? %w %b %b %b %b %w %*".to_string(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let _descriptor_length = res[0].to_i64().unwrap();
|
let _descriptor_length = res[0].to_i64().unwrap();
|
||||||
let _generation_id = res[1].to_i64().unwrap();
|
let _generation_id = res[1].to_i64().unwrap();
|
||||||
|
@ -268,7 +272,8 @@ impl NetMDInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
let manufacturer_dep_length = self.construct_multibyte(&buffer, 2, &mut buffer_offset);
|
let manufacturer_dep_length = self.construct_multibyte(&buffer, 2, &mut buffer_offset);
|
||||||
let _manufacturer_dep_data = &buffer[buffer_offset..buffer_offset + manufacturer_dep_length as usize];
|
let _manufacturer_dep_data =
|
||||||
|
&buffer[buffer_offset..buffer_offset + manufacturer_dep_length as usize];
|
||||||
|
|
||||||
self.change_descriptor_state(&Descriptor::DiscSubunitIdentifier, &DescriptorAction::Close);
|
self.change_descriptor_state(&Descriptor::DiscSubunitIdentifier, &DescriptorAction::Close);
|
||||||
|
|
||||||
|
@ -301,11 +306,7 @@ impl NetMDInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_descriptor_state(&self, descriptor: &Descriptor, action: &DescriptorAction) {
|
fn change_descriptor_state(&self, descriptor: &Descriptor, action: &DescriptorAction) {
|
||||||
let mut query = format_query(
|
let mut query = format_query("1808".to_string(), vec![]).unwrap();
|
||||||
"1808".to_string(),
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
).unwrap();
|
|
||||||
|
|
||||||
query.append(&mut descriptor.get_array());
|
query.append(&mut descriptor.get_array());
|
||||||
|
|
||||||
|
@ -388,8 +389,7 @@ impl NetMDInterface {
|
||||||
fn playback_control(&self, action: Action) -> Result<(), Box<dyn Error>> {
|
fn playback_control(&self, action: Action) -> Result<(), Box<dyn Error>> {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"18c3 00 %b 000000".to_string(),
|
"18c3 00 %b 000000".to_string(),
|
||||||
vec![Some(action as i64)],
|
vec![QueryValue::Number(action as i64)],
|
||||||
vec![],
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
@ -417,11 +417,7 @@ impl NetMDInterface {
|
||||||
|
|
||||||
//TODO: Implement fix for LAM-1
|
//TODO: Implement fix for LAM-1
|
||||||
pub fn stop(&self) -> Result<(), Box<dyn Error>> {
|
pub fn stop(&self) -> Result<(), Box<dyn Error>> {
|
||||||
let mut query = format_query(
|
let mut query = format_query("18c5 ff 00000000".to_string(), vec![])?;
|
||||||
"18c5 ff 00000000".to_string(),
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
|
||||||
|
@ -434,7 +430,6 @@ impl NetMDInterface {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"ff 010c ffff ffff ffff ffff ffff ffff".to_string(),
|
"ff 010c ffff ffff ffff ffff ffff ffff".to_string(),
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
|
||||||
)?;
|
)?;
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
|
||||||
|
@ -447,7 +442,6 @@ impl NetMDInterface {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"ff 0100 ffff ffff ffff ffff ffff ffff".to_string(),
|
"ff 0100 ffff ffff ffff ffff ffff ffff".to_string(),
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
@ -466,12 +460,14 @@ impl NetMDInterface {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1809 8001 0230 8800 0030 8804 00 ff00 00000000".to_string(),
|
"1809 8001 0230 8800 0030 8804 00 ff00 00000000".to_string(),
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
|
||||||
let res = scan_query(reply, "1809 8001 0230 8800 0030 8804 00 1000 00090000 %x".to_string())?;
|
let res = scan_query(
|
||||||
|
reply,
|
||||||
|
"1809 8001 0230 8800 0030 8804 00 1000 00090000 %x".to_string(),
|
||||||
|
)?;
|
||||||
|
|
||||||
self.change_descriptor_state(&Descriptor::OperatingStatusBlock, &DescriptorAction::Close);
|
self.change_descriptor_state(&Descriptor::OperatingStatusBlock, &DescriptorAction::Close);
|
||||||
|
|
||||||
|
@ -497,7 +493,6 @@ impl NetMDInterface {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1809 8001 0330 8802 0030 8805 0030 8806 00 ff00 00000000".to_string(),
|
"1809 8001 0330 8802 0030 8805 0030 8806 00 ff00 00000000".to_string(),
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
@ -535,8 +530,7 @@ impl NetMDInterface {
|
||||||
);
|
);
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1809 8001 0330 %w 0030 8805 0030 %w 00 ff00 00000000".to_string(),
|
"1809 8001 0330 %w 0030 8805 0030 %w 00 ff00 00000000".to_string(),
|
||||||
vec![Some(p1 as i64), Some(p2 as i64)],
|
vec![QueryValue::Number(p1 as i64), QueryValue::Number(p2 as i64)],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -569,7 +563,6 @@ impl NetMDInterface {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1809 8001 0430 8802 0030 8805 0030 0003 0030 0002 00 ff00 00000000".to_string(),
|
"1809 8001 0430 8802 0030 8805 0030 0003 0030 0002 00 ff00 00000000".to_string(),
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -595,14 +588,14 @@ impl NetMDInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eject_disc(&self) -> Result<(), Box<dyn Error>> {
|
pub fn eject_disc(&self) -> Result<(), Box<dyn Error>> {
|
||||||
let mut query = format_query("18c1 ff 6000".to_string(), vec![], vec![]).unwrap();
|
let mut query = format_query("18c1 ff 6000".to_string(), vec![]).unwrap();
|
||||||
|
|
||||||
let _reply = self.send_query(&mut query, false, false)?;
|
let _reply = self.send_query(&mut query, false, false)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_eject_disc(&self) -> Result<bool, Box<dyn Error>> {
|
pub fn can_eject_disc(&self) -> Result<bool, Box<dyn Error>> {
|
||||||
let mut query = format_query("18c1 ff 6000".to_string(), vec![], vec![]).unwrap();
|
let mut query = format_query("18c1 ff 6000".to_string(), vec![]).unwrap();
|
||||||
|
|
||||||
match self.send_query(&mut query, true, false) {
|
match self.send_query(&mut query, true, false) {
|
||||||
Ok(_) => Ok(true),
|
Ok(_) => Ok(true),
|
||||||
|
@ -614,8 +607,7 @@ impl NetMDInterface {
|
||||||
pub fn go_to_track(&self, track_number: u16) -> Result<u16, Box<dyn Error>> {
|
pub fn go_to_track(&self, track_number: u16) -> Result<u16, Box<dyn Error>> {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1850 ff010000 0000 %w".to_string(),
|
"1850 ff010000 0000 %w".to_string(),
|
||||||
vec![Some(track_number as i64)],
|
vec![QueryValue::Number(track_number as i64)],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -639,13 +631,12 @@ impl NetMDInterface {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1850 ff000000 0000 %w %B%B%B%B".to_string(),
|
"1850 ff000000 0000 %w %B%B%B%B".to_string(),
|
||||||
vec![
|
vec![
|
||||||
Some(track_number as i64),
|
QueryValue::Number(track_number as i64),
|
||||||
Some(hour as i64),
|
QueryValue::Number(hour as i64),
|
||||||
Some(minute as i64),
|
QueryValue::Number(minute as i64),
|
||||||
Some(second as i64),
|
QueryValue::Number(second as i64),
|
||||||
Some(frame as i64),
|
QueryValue::Number(frame as i64),
|
||||||
],
|
],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -661,8 +652,7 @@ impl NetMDInterface {
|
||||||
fn _track_change(&self, direction: Track) -> Result<(), Box<dyn Error>> {
|
fn _track_change(&self, direction: Track) -> Result<(), Box<dyn Error>> {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1850 ff10 00000000 %w".to_string(),
|
"1850 ff10 00000000 %w".to_string(),
|
||||||
vec![Some(direction as i64)],
|
vec![QueryValue::Number(direction as i64)],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -687,7 +677,7 @@ impl NetMDInterface {
|
||||||
|
|
||||||
/* Content access and control */
|
/* Content access and control */
|
||||||
pub fn erase_disc(&self) -> Result<(), Box<dyn Error>> {
|
pub fn erase_disc(&self) -> Result<(), Box<dyn Error>> {
|
||||||
let mut query = format_query("1840 ff 0000".to_string(), vec![], vec![]).unwrap();
|
let mut query = format_query("1840 ff 0000".to_string(), vec![]).unwrap();
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
scan_query(reply, "1840 00 0000".to_string())?;
|
scan_query(reply, "1840 00 0000".to_string())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -698,7 +688,7 @@ impl NetMDInterface {
|
||||||
pub fn disc_flags(&self) -> Result<u8, Box<dyn Error>> {
|
pub fn disc_flags(&self) -> Result<u8, Box<dyn Error>> {
|
||||||
self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::OpenRead);
|
self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::OpenRead);
|
||||||
let mut query =
|
let mut query =
|
||||||
format_query("1806 01101000 ff00 0001000b".to_string(), vec![], vec![]).unwrap();
|
format_query("1806 01101000 ff00 0001000b".to_string(), vec![]).unwrap();
|
||||||
|
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
|
||||||
|
@ -715,7 +705,6 @@ impl NetMDInterface {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1806 02101001 3000 1000 ff00 00000000".to_string(),
|
"1806 02101001 3000 1000 ff00 00000000".to_string(),
|
||||||
vec![],
|
vec![],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -752,18 +741,20 @@ impl NetMDInterface {
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1806 02201801 00%b 3000 0a00 ff00 %w%w".to_string(),
|
"1806 02201801 00%b 3000 0a00 ff00 %w%w".to_string(),
|
||||||
vec![
|
vec![
|
||||||
wchar_value.into(),
|
QueryValue::Number(wchar_value),
|
||||||
(remaining as i64).into(),
|
QueryValue::Number(remaining as i64),
|
||||||
(done as i64).into(),
|
QueryValue::Number(done as i64),
|
||||||
],
|
],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
let res = scan_query(reply, "1806 02201801 00%? 3000 0a00 1000 %w0000 %?%?000a %w %*".to_string())?;
|
let res = scan_query(
|
||||||
|
reply,
|
||||||
|
"1806 02201801 00%? 3000 0a00 1000 %w0000 %?%?000a %w %*".to_string(),
|
||||||
|
)?;
|
||||||
|
|
||||||
chunksize = res[0].to_i64().unwrap() as i32;
|
chunksize = res[0].to_i64().unwrap() as i32;
|
||||||
total = res[1].to_i64().unwrap() as i32;
|
total = res[1].to_i64().unwrap() as i32;
|
||||||
|
@ -771,7 +762,10 @@ impl NetMDInterface {
|
||||||
|
|
||||||
chunksize -= 6;
|
chunksize -= 6;
|
||||||
} else {
|
} else {
|
||||||
let res = scan_query(reply, "1806 02201801 00%? 3000 0a00 1000 %w%?%? %*".to_string())?;
|
let res = scan_query(
|
||||||
|
reply,
|
||||||
|
"1806 02201801 00%? 3000 0a00 1000 %w%?%? %*".to_string(),
|
||||||
|
)?;
|
||||||
chunksize = res[0].to_i64().unwrap() as i32;
|
chunksize = res[0].to_i64().unwrap() as i32;
|
||||||
chunk = SHIFT_JIS.decode(&res[1].to_vec().unwrap()).0.into();
|
chunk = SHIFT_JIS.decode(&res[1].to_vec().unwrap()).0.into();
|
||||||
}
|
}
|
||||||
|
@ -872,8 +866,6 @@ impl NetMDInterface {
|
||||||
// TODO: Do some error handling here
|
// TODO: Do some error handling here
|
||||||
assert!(track_min <= track_max);
|
assert!(track_min <= track_max);
|
||||||
|
|
||||||
println!("{}, {}", track_min, track_max);
|
|
||||||
|
|
||||||
let mut track_list: Vec<u16> = Vec::new();
|
let mut track_list: Vec<u16> = Vec::new();
|
||||||
for track in track_min - 1..track_max {
|
for track in track_min - 1..track_max {
|
||||||
if track_dict.contains_key(&track) {
|
if track_dict.contains_key(&track) {
|
||||||
|
@ -898,7 +890,6 @@ impl NetMDInterface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{:#?}", result);
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,8 +902,7 @@ impl NetMDInterface {
|
||||||
|
|
||||||
let mut query = format_query(
|
let mut query = format_query(
|
||||||
"1806 022018%b %w 3000 0a00 ff00 00000000".to_string(),
|
"1806 022018%b %w 3000 0a00 ff00 00000000".to_string(),
|
||||||
vec![wchar_value.into(), (track as i64).into()],
|
vec![QueryValue::Number(wchar_value), QueryValue::Number(track as i64)],
|
||||||
vec![],
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -939,24 +929,55 @@ impl NetMDInterface {
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_disc_title(&self, title: String, wchar: bool) -> Result<(), Box<dyn Error>> {
|
pub fn set_disc_title(&self, title: String, wchar: bool) -> Result<String, Box<dyn Error>> {
|
||||||
let current_title = self._disc_title(wchar)?;
|
let current_title = self._disc_title(wchar)?;
|
||||||
if current_title == title {
|
if current_title == title {
|
||||||
return Ok(())
|
return Ok(current_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
let old_len = length_after_encoding_to_jis(current_title);
|
let new_title: Vec<u8>;
|
||||||
let new_len = length_after_encoding_to_jis(title);
|
let old_len = length_after_encoding_to_jis(¤t_title);
|
||||||
|
|
||||||
let wchar_value = match wchar {
|
let wchar_value = match wchar {
|
||||||
true => {
|
true => {
|
||||||
|
new_title = sanitize_full_width_title(&title, false);
|
||||||
|
1
|
||||||
},
|
},
|
||||||
false => {
|
false => {
|
||||||
|
new_title = Vec::new();
|
||||||
}
|
0
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
let new_len = new_title.len();
|
||||||
|
|
||||||
|
if self.net_md_device.vendor_id() == &0x04dd {
|
||||||
|
self.change_descriptor_state(&Descriptor::AudioUTOC1TD, &DescriptorAction::OpenWrite)
|
||||||
|
} else {
|
||||||
|
self.change_descriptor_state(&Descriptor::DiscTitleTD, &DescriptorAction::Close);
|
||||||
|
self.change_descriptor_state(&Descriptor::DiscTitleTD, &DescriptorAction::OpenWrite)
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut query = format_query(
|
||||||
|
"1807 02201801 00%b 3000 0a00 5000 %w 0000 %w %*".to_string(),
|
||||||
|
vec![
|
||||||
|
QueryValue::Number(wchar_value),
|
||||||
|
QueryValue::Number(new_len as i64),
|
||||||
|
QueryValue::Number(old_len as i64),
|
||||||
|
QueryValue::Array(new_title),
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let reply = self.send_query(&mut query, false, false);
|
||||||
|
|
||||||
|
if self.net_md_device.vendor_id() == &0x04dd {
|
||||||
|
self.change_descriptor_state(&Descriptor::AudioUTOC1TD, &DescriptorAction::Close)
|
||||||
|
} else {
|
||||||
|
self.change_descriptor_state(&Descriptor::DiscTitleTD, &DescriptorAction::Close);
|
||||||
|
self.change_descriptor_state(&Descriptor::DiscTitleTD, &DescriptorAction::OpenRead);
|
||||||
|
self.change_descriptor_state(&Descriptor::DiscTitleTD, &DescriptorAction::Close);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(String::from_utf8(sanitize_full_width_title(&title, true)).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
273
minidisc-rs/src/netmd/mappings.rs
Normal file
273
minidisc-rs/src/netmd/mappings.rs
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub const MAPPINGS_JP: Lazy<HashMap<String, String>> = Lazy::new(|| {vec![
|
||||||
|
("!".to_string(), "!".to_string()),
|
||||||
|
("\"".to_string(), """.to_string()),
|
||||||
|
("#".to_string(), "#".to_string()),
|
||||||
|
("$".to_string(), "$".to_string()),
|
||||||
|
("%".to_string(), "%".to_string()),
|
||||||
|
("&".to_string(), "&".to_string()),
|
||||||
|
("'".to_string(), "'".to_string()),
|
||||||
|
("(".to_string(), "(".to_string()),
|
||||||
|
(")".to_string(), ")".to_string()),
|
||||||
|
("*".to_string(), "*".to_string()),
|
||||||
|
("+".to_string(), "+".to_string()),
|
||||||
|
(",".to_string(), ",".to_string()),
|
||||||
|
("-".to_string(), "-".to_string()),
|
||||||
|
(".".to_string(), ".".to_string()),
|
||||||
|
("/".to_string(), "/".to_string()),
|
||||||
|
(":".to_string(), ":".to_string()),
|
||||||
|
(";".to_string(), ";".to_string()),
|
||||||
|
("<".to_string(), "<".to_string()),
|
||||||
|
("=".to_string(), "=".to_string()),
|
||||||
|
(">".to_string(), ">".to_string()),
|
||||||
|
("?".to_string(), "?".to_string()),
|
||||||
|
("@".to_string(), "@".to_string()),
|
||||||
|
("A".to_string(), "A".to_string()),
|
||||||
|
("B".to_string(), "B".to_string()),
|
||||||
|
("C".to_string(), "C".to_string()),
|
||||||
|
("D".to_string(), "D".to_string()),
|
||||||
|
("E".to_string(), "E".to_string()),
|
||||||
|
("F".to_string(), "F".to_string()),
|
||||||
|
("G".to_string(), "G".to_string()),
|
||||||
|
("H".to_string(), "H".to_string()),
|
||||||
|
("I".to_string(), "I".to_string()),
|
||||||
|
("J".to_string(), "J".to_string()),
|
||||||
|
("K".to_string(), "K".to_string()),
|
||||||
|
("L".to_string(), "L".to_string()),
|
||||||
|
("M".to_string(), "M".to_string()),
|
||||||
|
("N".to_string(), "N".to_string()),
|
||||||
|
("O".to_string(), "O".to_string()),
|
||||||
|
("P".to_string(), "P".to_string()),
|
||||||
|
("Q".to_string(), "Q".to_string()),
|
||||||
|
("R".to_string(), "R".to_string()),
|
||||||
|
("S".to_string(), "S".to_string()),
|
||||||
|
("T".to_string(), "T".to_string()),
|
||||||
|
("U".to_string(), "U".to_string()),
|
||||||
|
("V".to_string(), "V".to_string()),
|
||||||
|
("W".to_string(), "W".to_string()),
|
||||||
|
("X".to_string(), "X".to_string()),
|
||||||
|
("Y".to_string(), "Y".to_string()),
|
||||||
|
("Z".to_string(), "Z".to_string()),
|
||||||
|
("[".to_string(), "[".to_string()),
|
||||||
|
("\\".to_string(), "\".to_string()),
|
||||||
|
("]".to_string(), "]".to_string()),
|
||||||
|
("^".to_string(), "^".to_string()),
|
||||||
|
("_".to_string(), "_".to_string()),
|
||||||
|
("`".to_string(), "`".to_string()),
|
||||||
|
("a".to_string(), "a".to_string()),
|
||||||
|
("b".to_string(), "b".to_string()),
|
||||||
|
("c".to_string(), "c".to_string()),
|
||||||
|
("d".to_string(), "d".to_string()),
|
||||||
|
("e".to_string(), "e".to_string()),
|
||||||
|
("f".to_string(), "f".to_string()),
|
||||||
|
("g".to_string(), "g".to_string()),
|
||||||
|
("h".to_string(), "h".to_string()),
|
||||||
|
("i".to_string(), "i".to_string()),
|
||||||
|
("j".to_string(), "j".to_string()),
|
||||||
|
("k".to_string(), "k".to_string()),
|
||||||
|
("l".to_string(), "l".to_string()),
|
||||||
|
("m".to_string(), "m".to_string()),
|
||||||
|
("n".to_string(), "n".to_string()),
|
||||||
|
("o".to_string(), "o".to_string()),
|
||||||
|
("p".to_string(), "p".to_string()),
|
||||||
|
("q".to_string(), "q".to_string()),
|
||||||
|
("r".to_string(), "r".to_string()),
|
||||||
|
("s".to_string(), "s".to_string()),
|
||||||
|
("t".to_string(), "t".to_string()),
|
||||||
|
("u".to_string(), "u".to_string()),
|
||||||
|
("v".to_string(), "v".to_string()),
|
||||||
|
("w".to_string(), "w".to_string()),
|
||||||
|
("x".to_string(), "x".to_string()),
|
||||||
|
("y".to_string(), "y".to_string()),
|
||||||
|
("z".to_string(), "z".to_string()),
|
||||||
|
("{".to_string(), "{".to_string()),
|
||||||
|
("|".to_string(), "|".to_string()),
|
||||||
|
("}".to_string(), "}".to_string()),
|
||||||
|
("~".to_string(), "~".to_string()),
|
||||||
|
(" ".to_string(), "\u{3000}".to_string()),
|
||||||
|
("0".to_string(), "0".to_string()),
|
||||||
|
("1".to_string(), "1".to_string()),
|
||||||
|
("2".to_string(), "2".to_string()),
|
||||||
|
("3".to_string(), "3".to_string()),
|
||||||
|
("4".to_string(), "4".to_string()),
|
||||||
|
("5".to_string(), "5".to_string()),
|
||||||
|
("6".to_string(), "6".to_string()),
|
||||||
|
("7".to_string(), "7".to_string()),
|
||||||
|
("8".to_string(), "8".to_string()),
|
||||||
|
("9".to_string(), "9".to_string()),
|
||||||
|
("ァ".to_string(), "ァ".to_string()),
|
||||||
|
("ア".to_string(), "ア".to_string()),
|
||||||
|
("ィ".to_string(), "ィ".to_string()),
|
||||||
|
("イ".to_string(), "イ".to_string()),
|
||||||
|
("ゥ".to_string(), "ゥ".to_string()),
|
||||||
|
("ウ".to_string(), "ウ".to_string()),
|
||||||
|
("ェ".to_string(), "ェ".to_string()),
|
||||||
|
("エ".to_string(), "エ".to_string()),
|
||||||
|
("ォ".to_string(), "ォ".to_string()),
|
||||||
|
("オ".to_string(), "オ".to_string()),
|
||||||
|
("カ".to_string(), "カ".to_string()),
|
||||||
|
("ガ".to_string(), "ガ".to_string()),
|
||||||
|
("キ".to_string(), "キ".to_string()),
|
||||||
|
("ギ".to_string(), "ギ".to_string()),
|
||||||
|
("ク".to_string(), "ク".to_string()),
|
||||||
|
("グ".to_string(), "グ".to_string()),
|
||||||
|
("ケ".to_string(), "ケ".to_string()),
|
||||||
|
("ゲ".to_string(), "ゲ".to_string()),
|
||||||
|
("コ".to_string(), "コ".to_string()),
|
||||||
|
("ゴ".to_string(), "ゴ".to_string()),
|
||||||
|
("サ".to_string(), "サ".to_string()),
|
||||||
|
("ザ".to_string(), "ザ".to_string()),
|
||||||
|
("シ".to_string(), "シ".to_string()),
|
||||||
|
("ジ".to_string(), "ジ".to_string()),
|
||||||
|
("ス".to_string(), "ス".to_string()),
|
||||||
|
("ズ".to_string(), "ズ".to_string()),
|
||||||
|
("セ".to_string(), "セ".to_string()),
|
||||||
|
("ゼ".to_string(), "ゼ".to_string()),
|
||||||
|
("ソ".to_string(), "ソ".to_string()),
|
||||||
|
("ゾ".to_string(), "ゾ".to_string()),
|
||||||
|
("タ".to_string(), "タ".to_string()),
|
||||||
|
("ダ".to_string(), "ダ".to_string()),
|
||||||
|
("チ".to_string(), "チ".to_string()),
|
||||||
|
("ヂ".to_string(), "ヂ".to_string()),
|
||||||
|
("ッ".to_string(), "ッ".to_string()),
|
||||||
|
("ツ".to_string(), "ツ".to_string()),
|
||||||
|
("ヅ".to_string(), "ヅ".to_string()),
|
||||||
|
("テ".to_string(), "テ".to_string()),
|
||||||
|
("デ".to_string(), "デ".to_string()),
|
||||||
|
("ト".to_string(), "ト".to_string()),
|
||||||
|
("ド".to_string(), "ド".to_string()),
|
||||||
|
("ナ".to_string(), "ナ".to_string()),
|
||||||
|
("ニ".to_string(), "ニ".to_string()),
|
||||||
|
("ヌ".to_string(), "ヌ".to_string()),
|
||||||
|
("ネ".to_string(), "ネ".to_string()),
|
||||||
|
("ノ".to_string(), "ノ".to_string()),
|
||||||
|
("ハ".to_string(), "ハ".to_string()),
|
||||||
|
("バ".to_string(), "バ".to_string()),
|
||||||
|
("パ".to_string(), "パ".to_string()),
|
||||||
|
("ヒ".to_string(), "ヒ".to_string()),
|
||||||
|
("ビ".to_string(), "ビ".to_string()),
|
||||||
|
("ピ".to_string(), "ピ".to_string()),
|
||||||
|
("フ".to_string(), "フ".to_string()),
|
||||||
|
("ブ".to_string(), "ブ".to_string()),
|
||||||
|
("プ".to_string(), "プ".to_string()),
|
||||||
|
("ヘ".to_string(), "ヘ".to_string()),
|
||||||
|
("ベ".to_string(), "ベ".to_string()),
|
||||||
|
("ペ".to_string(), "ペ".to_string()),
|
||||||
|
("ホ".to_string(), "ホ".to_string()),
|
||||||
|
("ボ".to_string(), "ボ".to_string()),
|
||||||
|
("ポ".to_string(), "ポ".to_string()),
|
||||||
|
("マ".to_string(), "マ".to_string()),
|
||||||
|
("ミ".to_string(), "ミ".to_string()),
|
||||||
|
("ム".to_string(), "ム".to_string()),
|
||||||
|
("メ".to_string(), "メ".to_string()),
|
||||||
|
("モ".to_string(), "モ".to_string()),
|
||||||
|
("ャ".to_string(), "ャ".to_string()),
|
||||||
|
("ヤ".to_string(), "ヤ".to_string()),
|
||||||
|
("ュ".to_string(), "ュ".to_string()),
|
||||||
|
("ユ".to_string(), "ユ".to_string()),
|
||||||
|
("ョ".to_string(), "ョ".to_string()),
|
||||||
|
("ヨ".to_string(), "ヨ".to_string()),
|
||||||
|
("ラ".to_string(), "ラ".to_string()),
|
||||||
|
("リ".to_string(), "リ".to_string()),
|
||||||
|
("ル".to_string(), "ル".to_string()),
|
||||||
|
("レ".to_string(), "レ".to_string()),
|
||||||
|
("ロ".to_string(), "ロ".to_string()),
|
||||||
|
("ワ".to_string(), "ワ".to_string()),
|
||||||
|
("ヲ".to_string(), "ヲ".to_string()),
|
||||||
|
("ン".to_string(), "ン".to_string()),
|
||||||
|
("ー".to_string(), "ー".to_string()),
|
||||||
|
("ヮ".to_string(), "ヮ".to_string()),
|
||||||
|
("ヰ".to_string(), "ヰ".to_string()),
|
||||||
|
("ヱ".to_string(), "ヱ".to_string()),
|
||||||
|
("ヵ".to_string(), "ヵ".to_string()),
|
||||||
|
("ヶ".to_string(), "ヶ".to_string()),
|
||||||
|
("ヴ".to_string(), "ヴ".to_string()),
|
||||||
|
("ヽ".to_string(), "ヽ".to_string()),
|
||||||
|
("ヾ".to_string(), "ヾ".to_string()),
|
||||||
|
("・".to_string(), "・".to_string()),
|
||||||
|
("「".to_string(), "「".to_string()),
|
||||||
|
("」".to_string(), "」".to_string()),
|
||||||
|
("。".to_string(), "。".to_string()),
|
||||||
|
("、".to_string(), "、".to_string())
|
||||||
|
].into_iter().collect()});
|
||||||
|
|
||||||
|
pub const MAPPINGS_RU: Lazy<HashMap<String, String>> = Lazy::new(|| {vec![
|
||||||
|
("а".to_string(), "a".to_string()),
|
||||||
|
("б".to_string(), "b".to_string()),
|
||||||
|
("в".to_string(), "v".to_string()),
|
||||||
|
("г".to_string(), "g".to_string()),
|
||||||
|
("д".to_string(), "d".to_string()),
|
||||||
|
("е".to_string(), "e".to_string()),
|
||||||
|
("ё".to_string(), "e".to_string()),
|
||||||
|
("ж".to_string(), "zh".to_string()),
|
||||||
|
("з".to_string(), "z".to_string()),
|
||||||
|
("и".to_string(), "i".to_string()),
|
||||||
|
("й".to_string(), "i".to_string()),
|
||||||
|
("к".to_string(), "k".to_string()),
|
||||||
|
("л".to_string(), "l".to_string()),
|
||||||
|
("м".to_string(), "m".to_string()),
|
||||||
|
("н".to_string(), "n".to_string()),
|
||||||
|
("о".to_string(), "o".to_string()),
|
||||||
|
("п".to_string(), "p".to_string()),
|
||||||
|
("р".to_string(), "r".to_string()),
|
||||||
|
("с".to_string(), "s".to_string()),
|
||||||
|
("т".to_string(), "t".to_string()),
|
||||||
|
("у".to_string(), "u".to_string()),
|
||||||
|
("ф".to_string(), "f".to_string()),
|
||||||
|
("х".to_string(), "kh".to_string()),
|
||||||
|
("ц".to_string(), "tc".to_string()),
|
||||||
|
("ч".to_string(), "ch".to_string()),
|
||||||
|
("ш".to_string(), "sh".to_string()),
|
||||||
|
("щ".to_string(), "shch".to_string()),
|
||||||
|
("ъ".to_string(), "".to_string()),
|
||||||
|
("ы".to_string(), "y".to_string()),
|
||||||
|
("ь".to_string(), "'".to_string()),
|
||||||
|
("э".to_string(), "e".to_string()),
|
||||||
|
("ю".to_string(), "iu".to_string()),
|
||||||
|
("я".to_string(), "ia".to_string()),
|
||||||
|
("А".to_string(), "A".to_string()),
|
||||||
|
("Б".to_string(), "B".to_string()),
|
||||||
|
("В".to_string(), "V".to_string()),
|
||||||
|
("Г".to_string(), "G".to_string()),
|
||||||
|
("Д".to_string(), "D".to_string()),
|
||||||
|
("Е".to_string(), "E".to_string()),
|
||||||
|
("Ё".to_string(), "E".to_string()),
|
||||||
|
("Ж".to_string(), "Zh".to_string()),
|
||||||
|
("З".to_string(), "Z".to_string()),
|
||||||
|
("И".to_string(), "I".to_string()),
|
||||||
|
("Й".to_string(), "I".to_string()),
|
||||||
|
("К".to_string(), "K".to_string()),
|
||||||
|
("Л".to_string(), "L".to_string()),
|
||||||
|
("М".to_string(), "M".to_string()),
|
||||||
|
("Н".to_string(), "N".to_string()),
|
||||||
|
("О".to_string(), "O".to_string()),
|
||||||
|
("П".to_string(), "P".to_string()),
|
||||||
|
("Р".to_string(), "R".to_string()),
|
||||||
|
("С".to_string(), "S".to_string()),
|
||||||
|
("Т".to_string(), "T".to_string()),
|
||||||
|
("У".to_string(), "U".to_string()),
|
||||||
|
("Ф".to_string(), "F".to_string()),
|
||||||
|
("Х".to_string(), "Kh".to_string()),
|
||||||
|
("Ц".to_string(), "Tc".to_string()),
|
||||||
|
("Ч".to_string(), "Ch".to_string()),
|
||||||
|
("Ш".to_string(), "Sh".to_string()),
|
||||||
|
("Щ".to_string(), "Shch".to_string()),
|
||||||
|
("Ъ".to_string(), "".to_string()),
|
||||||
|
("Ы".to_string(), "Y".to_string()),
|
||||||
|
("Ь".to_string(), "'".to_string()),
|
||||||
|
("Э".to_string(), "E".to_string()),
|
||||||
|
("Ю".to_string(), "Iu".to_string()),
|
||||||
|
("Я".to_string(), "Ia".to_string())
|
||||||
|
].into_iter().collect()});
|
||||||
|
|
||||||
|
pub const MAPPINGS_DE: Lazy<HashMap<String, String>> = Lazy::new(|| {vec![
|
||||||
|
("Ä".to_string(), "Ae".to_string()),
|
||||||
|
("ä".to_string(), "ae".to_string()),
|
||||||
|
("Ö".to_string(), "Oe".to_string()),
|
||||||
|
("ö".to_string(), "oe".to_string()),
|
||||||
|
("Ü".to_string(), "Ue".to_string()),
|
||||||
|
("ü".to_string(), "ue".to_string()),
|
||||||
|
("ß".to_string(), "ss".to_string())
|
||||||
|
].into_iter().collect()});
|
|
@ -2,3 +2,4 @@ mod base;
|
||||||
pub mod interface;
|
pub mod interface;
|
||||||
mod query_utils;
|
mod query_utils;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod mappings;
|
||||||
|
|
|
@ -25,11 +25,31 @@ const FORMAT_TYPE_LEN_DICT: Lazy<HashMap<char, i32>> = Lazy::new(|| {
|
||||||
|
|
||||||
const DEBUG: bool = false;
|
const DEBUG: bool = false;
|
||||||
|
|
||||||
|
pub enum QueryValue {
|
||||||
|
Number(i64),
|
||||||
|
Array(Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueryValue {
|
||||||
|
pub fn to_vec(&self) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||||
|
match self {
|
||||||
|
QueryValue::Array(a) => Ok(a.to_vec()),
|
||||||
|
_ => Err("QueryValue type mismatch! Expected Vec<u8>, got i64".into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_i64(&self) -> Result<i64, Box<dyn Error>> {
|
||||||
|
match self {
|
||||||
|
QueryValue::Number(a) => Ok(*a),
|
||||||
|
_ => Err("QueryValue type mismatch! Expected i64, got Vec<u8>".into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Formats a query using a standard input to send to the player
|
/// Formats a query using a standard input to send to the player
|
||||||
pub fn format_query(
|
pub fn format_query(
|
||||||
format: String,
|
format: String,
|
||||||
args: Vec<Option<i64>>,
|
args: Vec<QueryValue>,
|
||||||
array_args: Vec<Vec<u8>>,
|
|
||||||
) -> Result<Vec<u8>, Box<dyn Error>> {
|
) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||||
if DEBUG {
|
if DEBUG {
|
||||||
println!("SENT>>> F: {}", format);
|
println!("SENT>>> F: {}", format);
|
||||||
|
@ -38,7 +58,6 @@ pub fn format_query(
|
||||||
let mut result: Vec<u8> = Vec::new();
|
let mut result: Vec<u8> = Vec::new();
|
||||||
let mut half: Option<char> = None;
|
let mut half: Option<char> = None;
|
||||||
let mut arg_stack = args.into_iter();
|
let mut arg_stack = args.into_iter();
|
||||||
let mut array_arg_stack = array_args.into_iter();
|
|
||||||
let mut endianness_override: Option<char> = None;
|
let mut endianness_override: Option<char> = None;
|
||||||
|
|
||||||
let mut escaped = false;
|
let mut escaped = false;
|
||||||
|
@ -49,10 +68,10 @@ pub fn format_query(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
escaped = false;
|
escaped = false;
|
||||||
let value = arg_stack.next().unwrap().unwrap();
|
|
||||||
|
|
||||||
match character {
|
match character {
|
||||||
character if FORMAT_TYPE_LEN_DICT.contains_key(&character) => {
|
character if FORMAT_TYPE_LEN_DICT.contains_key(&character) => {
|
||||||
|
let value = arg_stack.next().unwrap().to_i64().unwrap();
|
||||||
match character {
|
match character {
|
||||||
'b' => result.push(value as u8),
|
'b' => result.push(value as u8),
|
||||||
'w' => {
|
'w' => {
|
||||||
|
@ -72,7 +91,7 @@ pub fn format_query(
|
||||||
endianness_override = None;
|
endianness_override = None;
|
||||||
}
|
}
|
||||||
character if character == 'x' || character == 's' || character == 'z' => {
|
character if character == 'x' || character == 's' || character == 'z' => {
|
||||||
let mut array_value = array_arg_stack.next().unwrap();
|
let mut array_value = arg_stack.next().unwrap().to_vec().unwrap();
|
||||||
|
|
||||||
let mut array_length = array_value.len();
|
let mut array_length = array_value.len();
|
||||||
|
|
||||||
|
@ -90,10 +109,11 @@ pub fn format_query(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
character if character == '*' => {
|
character if character == '*' => {
|
||||||
let mut array_value = array_arg_stack.next().unwrap();
|
let mut array_value = arg_stack.next().unwrap().to_vec().unwrap();
|
||||||
result.append(&mut array_value);
|
result.append(&mut array_value);
|
||||||
}
|
}
|
||||||
character if character == 'B' || character == 'W' => {
|
character if character == 'B' || character == 'W' => {
|
||||||
|
let value = arg_stack.next().unwrap().to_i64().unwrap();
|
||||||
let converted = utils::int_to_bcd(value as i32);
|
let converted = utils::int_to_bcd(value as i32);
|
||||||
if character == 'W' {
|
if character == 'W' {
|
||||||
result.push(((converted >> 8) & 0xFF) as u8);
|
result.push(((converted >> 8) & 0xFF) as u8);
|
||||||
|
@ -124,33 +144,12 @@ pub fn format_query(
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum QueryResults {
|
|
||||||
Number(i64),
|
|
||||||
Array(Vec<u8>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl QueryResults {
|
|
||||||
pub fn to_vec(&self) -> Result<Vec<u8>, Box<dyn Error>> {
|
|
||||||
match self {
|
|
||||||
QueryResults::Array(a) => Ok(a.to_vec()),
|
|
||||||
_ => Err("Result was a number".into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_i64(&self) -> Result<i64, Box<dyn Error>> {
|
|
||||||
match self {
|
|
||||||
QueryResults::Number(a) => Ok(*a),
|
|
||||||
_ => Err("Result was a number".into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Scans a result using a standard input to recieve from the player
|
/// Scans a result using a standard input to recieve from the player
|
||||||
pub fn scan_query(
|
pub fn scan_query(
|
||||||
query_result: Vec<u8>,
|
query_result: Vec<u8>,
|
||||||
format: String,
|
format: String,
|
||||||
) -> Result<Vec<QueryResults>, Box<dyn Error>> {
|
) -> Result<Vec<QueryValue>, Box<dyn Error>> {
|
||||||
let mut result: Vec<QueryResults> = Vec::new();
|
let mut result: Vec<QueryValue> = Vec::new();
|
||||||
|
|
||||||
let initial_length = query_result.len();
|
let initial_length = query_result.len();
|
||||||
let mut input_stack = query_result.into_iter();
|
let mut input_stack = query_result.into_iter();
|
||||||
|
@ -162,8 +161,6 @@ pub fn scan_query(
|
||||||
// TODO: Find out what this is
|
// TODO: Find out what this is
|
||||||
input_stack.next();
|
input_stack.next();
|
||||||
|
|
||||||
let mut bloop = 0;
|
|
||||||
|
|
||||||
for character in format.chars() {
|
for character in format.chars() {
|
||||||
if escaped {
|
if escaped {
|
||||||
if endianness_override.is_none() && ['<', '>'].contains(&character) {
|
if endianness_override.is_none() && ['<', '>'].contains(&character) {
|
||||||
|
@ -183,22 +180,22 @@ pub fn scan_query(
|
||||||
'b' => {
|
'b' => {
|
||||||
let new_value =
|
let new_value =
|
||||||
u8::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
|
u8::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
|
||||||
result.push(QueryResults::Number(new_value as i64));
|
result.push(QueryValue::Number(new_value as i64));
|
||||||
}
|
}
|
||||||
'w' => {
|
'w' => {
|
||||||
let new_value =
|
let new_value =
|
||||||
i16::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
|
i16::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
|
||||||
result.push(QueryResults::Number(new_value as i64));
|
result.push(QueryValue::Number(new_value as i64));
|
||||||
}
|
}
|
||||||
'd' => {
|
'd' => {
|
||||||
let new_value =
|
let new_value =
|
||||||
i32::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
|
i32::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
|
||||||
result.push(QueryResults::Number(new_value as i64));
|
result.push(QueryValue::Number(new_value as i64));
|
||||||
}
|
}
|
||||||
'q' => {
|
'q' => {
|
||||||
let new_value =
|
let new_value =
|
||||||
i64::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
|
i64::from_be_bytes(utils::get_bytes(&mut input_stack).unwrap());
|
||||||
result.push(QueryResults::Number(new_value));
|
result.push(QueryValue::Number(new_value));
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -213,7 +210,7 @@ pub fn scan_query(
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
result_buffer.push(input_stack.next().unwrap());
|
result_buffer.push(input_stack.next().unwrap());
|
||||||
}
|
}
|
||||||
result.push(QueryResults::Array(result_buffer))
|
result.push(QueryValue::Array(result_buffer))
|
||||||
}
|
}
|
||||||
character if character == '*' || character == '#' => {
|
character if character == '*' || character == '#' => {
|
||||||
let mut result_buffer: Vec<u8> = Vec::new();
|
let mut result_buffer: Vec<u8> = Vec::new();
|
||||||
|
@ -222,16 +219,16 @@ pub fn scan_query(
|
||||||
result_buffer.push(entry);
|
result_buffer.push(entry);
|
||||||
input_stack.next();
|
input_stack.next();
|
||||||
}
|
}
|
||||||
result.push(QueryResults::Array(result_buffer));
|
result.push(QueryValue::Array(result_buffer));
|
||||||
}
|
}
|
||||||
character if character == 'B' => {
|
character if character == 'B' => {
|
||||||
let v = input_stack.next().unwrap();
|
let v = input_stack.next().unwrap();
|
||||||
result.push(QueryResults::Number(utils::bcd_to_int(v as i32) as i64));
|
result.push(QueryValue::Number(utils::bcd_to_int(v as i32) as i64));
|
||||||
}
|
}
|
||||||
character if character == 'W' => {
|
character if character == 'W' => {
|
||||||
let v = (input_stack.next().unwrap() as i32) << 8
|
let v = (input_stack.next().unwrap() as i32) << 8
|
||||||
| input_stack.next().unwrap() as i32;
|
| input_stack.next().unwrap() as i32;
|
||||||
result.push(QueryResults::Number(utils::bcd_to_int(v) as i64));
|
result.push(QueryValue::Number(utils::bcd_to_int(v) as i64));
|
||||||
}
|
}
|
||||||
_ => return Err(format!("Unrecognized format char {}", character).into()),
|
_ => return Err(format!("Unrecognized format char {}", character).into()),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use std::collections::hash_map::HashMap;
|
|
||||||
use encoding_rs::SHIFT_JIS;
|
use encoding_rs::SHIFT_JIS;
|
||||||
|
use kana::{ascii2wide, combine, half2kana};
|
||||||
|
use std::collections::hash_map::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use crate::netmd::mappings::{MAPPINGS_JP, MAPPINGS_RU, MAPPINGS_DE};
|
||||||
|
|
||||||
pub fn bcd_to_int(mut bcd: i32) -> i32 {
|
pub fn bcd_to_int(mut bcd: i32) -> i32 {
|
||||||
let mut value = 0;
|
let mut value = 0;
|
||||||
|
@ -68,8 +70,51 @@ pub fn get_bytes<const S: usize>(
|
||||||
Ok(bytes)
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn length_after_encoding_to_jis(string: String) -> usize {
|
pub fn length_after_encoding_to_jis(string: &String) -> usize {
|
||||||
let new_string = SHIFT_JIS.encode(&string);
|
let new_string = SHIFT_JIS.encode(string);
|
||||||
|
|
||||||
new_string.0.len()
|
new_string.0.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn validate_shift_jis(sjis_string: &Vec<u8>) -> Result<(), Box<dyn Error>> {
|
||||||
|
let (_, _, had_errors) = SHIFT_JIS.decode(sjis_string);
|
||||||
|
|
||||||
|
if had_errors {
|
||||||
|
Err("Not valid SHIFT-JIS".into())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This function is bad, probably should do the string sanitization in the frontend
|
||||||
|
pub fn sanitize_full_width_title(title: &String, just_remap: bool) -> Vec<u8> {
|
||||||
|
let new_title: String = title
|
||||||
|
.chars()
|
||||||
|
.map(|character| {
|
||||||
|
match MAPPINGS_JP.get(&character.to_string()) {
|
||||||
|
Some(string) => string.clone(),
|
||||||
|
None => character.to_string().clone()
|
||||||
|
}.to_string()
|
||||||
|
})
|
||||||
|
.map(|character| {
|
||||||
|
match MAPPINGS_RU.get(&character.to_string()) {
|
||||||
|
Some(string) => string.clone(),
|
||||||
|
None => character.to_string().clone()
|
||||||
|
}.to_string()
|
||||||
|
})
|
||||||
|
.map(|character| {
|
||||||
|
match MAPPINGS_DE.get(&character.to_string()) {
|
||||||
|
Some(string) => string.clone(),
|
||||||
|
None => character.to_string().clone()
|
||||||
|
}.to_string()
|
||||||
|
})
|
||||||
|
.collect::<String>();
|
||||||
|
|
||||||
|
if just_remap {
|
||||||
|
return new_title.into();
|
||||||
|
};
|
||||||
|
|
||||||
|
let sjis_string = SHIFT_JIS.encode(&new_title).0;
|
||||||
|
|
||||||
|
return sjis_string.into();
|
||||||
|
}
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -1,3 +1,5 @@
|
||||||
|
use std::thread::sleep_ms;
|
||||||
|
|
||||||
use minidisc_rs::netmd::interface;
|
use minidisc_rs::netmd::interface;
|
||||||
use rusb;
|
use rusb;
|
||||||
|
|
||||||
|
@ -29,9 +31,15 @@ fn main() {
|
||||||
player_controller.net_md_device.device_name().clone().unwrap()
|
player_controller.net_md_device.device_name().clone().unwrap()
|
||||||
);
|
);
|
||||||
println!("Track Count: {:?}", player_controller.track_count().unwrap());
|
println!("Track Count: {:?}", player_controller.track_count().unwrap());
|
||||||
println!("Disc Title: {} | {}", player_controller.disc_title(false).unwrap(), player_controller.disc_title(true).unwrap());
|
|
||||||
|
|
||||||
//println!("TEST CASE: {:?}", player_controller.disc_subunit_identifier());
|
println!("TEST CASE: {:?}", player_controller.set_disc_title("latvia ハハハ!はいはいです".to_string(), false));
|
||||||
|
println!("TEST CASE: {:?}", player_controller.set_disc_title("latvia ハハハ!はいはいです".to_string(), true));
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(2));
|
||||||
|
println!(
|
||||||
|
"Disc Title: {} | {}",
|
||||||
|
player_controller.disc_title(false).unwrap(),
|
||||||
|
player_controller.disc_title(true).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
let _ = player_controller.play();
|
let _ = player_controller.play();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue