aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2016-09-05 02:43:23 -0400
committerB. Watson <yalhcru@gmail.com>2016-09-05 02:43:23 -0400
commiteb9c8f2cf6d47c2495f36aeef638a4e1d2c35f4b (patch)
tree616af80f7814d314665b3c9d0723d2eee4f00734
parentbd22b14a194c56beea44caa28f38df6dce499b54 (diff)
downloadjumpmanjr-eb9c8f2cf6d47c2495f36aeef638a4e1d2c35f4b.tar.gz
renderlevels.pl, first pass at a level-renderer
-rw-r--r--.gitignore1
-rw-r--r--renderlevels.pl121
2 files changed, 122 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 2591a01..ade14ca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,4 @@ tmp.lbl
1.pl
2.pl
atari???.png
+level??.png
diff --git a/renderlevels.pl b/renderlevels.pl
new file mode 100644
index 0000000..8d0140c
--- /dev/null
+++ b/renderlevels.pl
@@ -0,0 +1,121 @@
+#!/usr/bin/perl -w
+
+# render jumpman junior levels to PNG files, by reading the graphics
+# and map data from the ROM image. input is 'jumpman.rom' in the current
+# directory, output is level01.png through level12.png in the current dir.
+
+# this code won't win any beauty contests, but it does work.
+
+$verbose = 0; # 0 = quiet, 2 = very chatty
+
+use Image::Magick;
+use bytes;
+
+sub getbyte {
+ return ord(substr($rom, $_[0], 1));
+}
+
+sub getword {
+ return getbyte($_[0]) + 256 * getbyte($_[0] + 1);
+}
+
+sub getdelta {
+ return $_[0] < 128 ? ($_[0]) : ($_[0] - 256);
+}
+
+# placeholder colors. ideally we'd have a full Atari palette, and read
+# the color register values from the level desc in the rom.
+%palette = (
+ 0 => [ 0x0000, 0x0000, 0x0000 ], # background
+ 1 => [ 0x0000, 0x0000, 0x8000 ], # girders, up-ropes
+ 2 => [ 0x0000, 0x8000, 0x0000 ], # ladders, down-ropes
+ 3 => [ 0x8000, 0x0000, 0x8000 ], # bombs
+);
+
+sub draw {
+ my ($img, $shape, $dx, $dy, $xpos, $ypos, $copies) = @_;
+ warn sprintf "drawing shape %04x at $xpos, $ypos, $copies copies, delta ($dx, $dy)\n", $shape if $verbose > 1;
+ while($copies--) {
+ my $width;
+ my $addr = $shape;
+ while(($width = getbyte($addr++)) != 0xff) {
+ my $xoffs = getdelta(getbyte($addr++));
+ my $yoffs = getdelta(getbyte($addr++));
+ for(my $p = 0; $p < $width; $p++) {
+ my $pixel = getbyte($addr++);
+ my $color = $palette{$pixel};
+ $img->SetPixel(x => $xpos + $xoffs + $p, y => $ypos + $yoffs, color => $color);
+ }
+ }
+ $xpos += $dx;
+ $ypos += $dy;
+ }
+}
+
+open ROM, "<jumpmanjr.rom" or die $!;
+if((read ROM, $rom, 0x4000, 0x8000) != 0x4000) {
+ die "couldn't read ROM\n";
+}
+
+for my $level (1..12) {
+ my $img = Image::Magick->new;
+ $img->Set(size => '160x100');
+ $img->ReadImage('canvas:black');
+
+ my $desc = 0xa000 + 0x40 * ($level - 1) + 22;
+ my $mapaddr = getword($desc);
+
+ if($level == 9) {
+ # show real map for blackout, not the blank one.
+ # the bombs are still invisible though.
+ $mapaddr = 0xb000;
+ }
+
+ warn sprintf("level $level, map pointer at \$%04x, points to \$%04x\n", $desc, $mapaddr) if $verbose;
+
+ # don't initialize these, we want warnings if some level
+ # tries to draw without selecting shape and direction.
+ my $shape;
+ my $copies;
+ my $dx;
+ my $dy;
+ my $xpos;
+ my $ypos;
+
+ while(1) {
+ my $opcode = getbyte($mapaddr);
+ if($opcode eq 0xff) {
+ warn sprintf " got end opcode (\$ff) at \$%04x\n", $mapaddr if $verbose > 1;
+ last;
+ }
+
+ my $operand1 = getbyte($mapaddr + 1);
+ my $operand2 = getbyte($mapaddr + 2);
+ my $opword = getword($mapaddr + 1);
+ warn sprintf "%04x: %02x %02x %02x\n", $mapaddr, $opcode, $operand1, $operand2 if $verbose > 1;
+ $mapaddr += 3;
+
+ if($opcode == 0xfe) {
+ $shape = $opword;
+ warn sprintf "set shape %04x\n", $shape if $verbose > 1;
+ } elsif($opcode == 0xfd) {
+ $dx = getdelta($operand1);
+ $dy = getdelta($operand2);
+ warn "set delta X $dx, delta Y $dy\n" if $verbose > 1;
+ } elsif($opcode == 0xfc) {
+ $mapaddr = $opword;
+ next;
+ } else {
+ $xpos = $opcode;
+ $ypos = $operand1;
+ $copies = $operand2;
+ draw($img, $shape, $dx, $dy, $xpos, $ypos, $copies);
+ }
+ }
+
+ my $pngfile = sprintf("level%02d.png", $level);
+ open my $out, ">$pngfile";
+ $img->Write(file => $out, filename => $pngfile);
+ close $out;
+ warn "wrote $pngfile\n";
+}