Skip to content

Commit 5cc272a

Browse files
thenorilihlorenzi
authored andcommitted
add output format for the game "Turing Complete"
Players of the game "Turing Complete" often use customasm to design a richer assembly language than the game provides and then copy the resulting binary into the game. This change introduces an annotated format compatible with the Turing Complete assembly editor, using '#' for comments and '0x' or '0b' to prefix data groups. This change also removes some trailing whitespace.
1 parent 5331f8f commit 5cc272a

File tree

4 files changed

+307
-140
lines changed

4 files changed

+307
-140
lines changed

src/driver.rs

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ pub enum OutputFormat
4444
LogiSim8,
4545
LogiSim16,
4646
AddressSpan,
47-
47+
TCGame {
48+
base: usize,
49+
group: usize,
50+
},
51+
4852
Symbols,
4953
SymbolsMesenMlb,
5054
}
@@ -56,20 +60,20 @@ pub fn drive_from_commandline(
5660
-> Result<(), ()>
5761
{
5862
util::enable_windows_ansi_support();
59-
63+
6064
let mut report = diagn::Report::new();
61-
65+
6266
let maybe_command = parse_command(
6367
&mut report,
6468
args);
6569

6670
if let Ok(command) = maybe_command
67-
{
71+
{
6872
let maybe_result = assemble_with_command(
6973
&mut report,
7074
fileserver,
7175
&command);
72-
76+
7377
report.print_all(
7478
&mut std::io::stderr(),
7579
fileserver,
@@ -98,7 +102,7 @@ pub fn drive(
98102
let command = parse_command(
99103
report,
100104
args)?;
101-
105+
102106
let maybe_result = assemble_with_command(
103107
report,
104108
fileserver,
@@ -119,7 +123,7 @@ fn assemble_with_command(
119123
print_usage(command.use_colors);
120124
return Ok(asm::AssemblyResult::new());
121125
}
122-
126+
123127
if command.show_version
124128
{
125129
print_version_full();
@@ -173,7 +177,7 @@ fn assemble_with_command(
173177
{
174178
println!("");
175179
}
176-
180+
177181
println!(
178182
"{}",
179183
String::from_utf8_lossy(&formatted));
@@ -193,15 +197,15 @@ fn assemble_with_command(
193197
}
194198
}
195199
}
196-
200+
197201
if !command.quiet
198202
{
199203
println!(
200204
"resolved in {} iteration{}",
201205
iterations_taken,
202206
if iterations_taken == 1 { "" } else { "s" });
203207
}
204-
208+
205209
Ok(assembly)
206210
}
207211

@@ -211,7 +215,7 @@ fn make_opts() -> getopts::Options
211215
let asm_opts = asm::AssemblyOptions::new();
212216

213217
let mut opts = getopts::Options::new();
214-
218+
215219
opts.optopt(
216220
"f", "format",
217221
"The format of the output file.\n\
@@ -224,7 +228,7 @@ fn make_opts() -> getopts::Options
224228
"FILE",
225229
getopts::HasArg::Maybe,
226230
getopts::Occur::Optional);
227-
231+
228232
opts.opt(
229233
"t", "iters",
230234
&format!(
@@ -233,7 +237,7 @@ fn make_opts() -> getopts::Options
233237
"NUM",
234238
getopts::HasArg::Maybe,
235239
getopts::Occur::Optional);
236-
240+
237241
opts.optflag(
238242
"p", "print",
239243
"Print the output to the screen instead of writing to a file.");
@@ -248,14 +252,14 @@ fn make_opts() -> getopts::Options
248252
"VALUE",
249253
getopts::HasArg::Yes,
250254
getopts::Occur::Multi);
251-
255+
252256
opts.opt(
253257
"", "color",
254258
"Style the output with colors. [on/off]",
255259
"VALUE",
256260
getopts::HasArg::Maybe,
257261
getopts::Occur::Optional);
258-
262+
259263
opts.optflag(
260264
"", "debug-iters",
261265
"Print debug info for the resolution iterations.");
@@ -275,7 +279,7 @@ fn make_opts() -> getopts::Options
275279
opts.optflag(
276280
"h", "help",
277281
"Display this information.");
278-
282+
279283
opts
280284
}
281285

@@ -360,7 +364,7 @@ fn parse_command(
360364

361365
command.opts.optimize_instruction_matching &=
362366
!parsed.opt_present("debug-no-optimize-matcher");
363-
367+
364368
if parsed.opt_present("color")
365369
{
366370
command.use_colors = {
@@ -376,7 +380,7 @@ fn parse_command(
376380
}
377381
};
378382
}
379-
383+
380384
if let Some(t) = parsed.opt_str("t")
381385
{
382386
command.opts.max_iterations = {
@@ -456,18 +460,18 @@ fn derive_output_filename(
456460

457461
let mut output_filename = std::path::PathBuf::from(input_filename);
458462
output_filename.set_extension(extension);
459-
463+
460464
let output_filename = output_filename
461465
.to_string_lossy()
462466
.into_owned()
463467
.replace("\\", "/");
464-
468+
465469
if output_filename == input_filename
466470
{
467471
report.error("cannot derive safe output filename");
468472
return Err(());
469473
}
470-
474+
471475
Ok(output_filename)
472476
}
473477

@@ -491,7 +495,7 @@ pub fn parse_output_format(
491495
.collect::<Vec<_>>();
492496

493497
let param_id = param_split[0];
494-
498+
495499
if param_split.len() == 1
496500
{
497501
params.insert(param_id.to_string(), "".to_string());
@@ -542,7 +546,7 @@ pub fn parse_output_format(
542546
format_id,
543547
param_id,
544548
value));
545-
549+
546550
Err(())
547551
}
548552
}
@@ -558,6 +562,11 @@ pub fn parse_output_format(
558562
[2, 4, 8, 16, 32, 64, 128].contains(&base)
559563
};
560564

565+
let check_2_or_16 = &mut |base: usize| -> bool
566+
{
567+
[2, 16].contains(&base)
568+
};
569+
561570
let format = {
562571
match format_id
563572
{
@@ -583,7 +592,7 @@ pub fn parse_output_format(
583592

584593
"bindump" => OutputFormat::BinDump,
585594
"hexdump" => OutputFormat::HexDump,
586-
595+
587596
"mif" => OutputFormat::Mif,
588597
"intelhex" => OutputFormat::IntelHex,
589598

@@ -600,7 +609,17 @@ pub fn parse_output_format(
600609
"logisim16" => OutputFormat::LogiSim16,
601610

602611
"addrspan" => OutputFormat::AddressSpan,
603-
612+
613+
"tcgame" => OutputFormat::TCGame {
614+
base: get_arg_usize("base", 16, check_2_or_16)?,
615+
group: get_arg_usize("group", 2, check_nonzero)?,
616+
},
617+
618+
"tcgamebin" => OutputFormat::TCGame {
619+
base: 2,
620+
group: 8,
621+
},
622+
604623
"symbols" => OutputFormat::Symbols,
605624
"mesen-mlb" => OutputFormat::SymbolsMesenMlb,
606625

@@ -682,16 +701,16 @@ fn parse_define_arg(
682701
None,
683702
diagn::Span::new_dummy(),
684703
if has_negative_sign { split[1].get(1..).unwrap() } else { split[1] });
685-
686-
704+
705+
687706
use std::ops::Neg;
688707

689708
match maybe_value
690709
{
691710
Ok(value) =>
692711
expr::Value::make_integer(
693712
if has_negative_sign { value.neg() } else { value }),
694-
713+
695714
Err(()) =>
696715
{
697716
report.error(
@@ -726,10 +745,13 @@ pub fn format_output(
726745
{
727746
OutputFormat::Binary =>
728747
return output.format_binary(),
729-
748+
730749
OutputFormat::Annotated { base, group } =>
731750
output.format_annotated(fileserver, base, group),
732-
751+
752+
OutputFormat::TCGame { base, group } =>
753+
output.format_tcgame(fileserver, base, group),
754+
733755
OutputFormat::BinStr => output.format_binstr(),
734756
OutputFormat::HexStr => output.format_hexstr(),
735757

@@ -750,9 +772,9 @@ pub fn format_output(
750772

751773
OutputFormat::LogiSim8 => output.format_logisim(8),
752774
OutputFormat::LogiSim16 => output.format_logisim(16),
753-
775+
754776
OutputFormat::AddressSpan => output.format_addrspan(fileserver),
755-
777+
756778
OutputFormat::Symbols => decls.symbols.format_default(decls, defs),
757779
OutputFormat::SymbolsMesenMlb => decls.symbols.format_mesen_mlb(decls, defs),
758780
}

src/usage_help.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,7 @@ Examples:
6161

6262
* `annotated,base:16,group:2`
6363
Annotates the output data with snippets
64-
of the source code.
65-
64+
of the source code.
6665
* `annotatedbin`
6766
Same as: `annotated,base:2,group:8`
6867

@@ -87,5 +86,15 @@ Examples:
8786

8887
* `addrspan`
8988

89+
* `tcgame,base:16,group:2`
90+
Annotates the output data with snippets
91+
of the source code in a format compatible
92+
with the assembly editor for the game
93+
"Turing Complete". Supports base 2 and 16.
94+
Comments out annotations with `#` and prefixes
95+
each group with `0x` or `0b`.
96+
* `tcgamebin`
97+
Same as: `tcgame,base:2,group:8`
98+
9099
* `symbols`
91100
* `mesen-mlb`

0 commit comments

Comments
 (0)