aboutsummaryrefslogtreecommitdiff
path: root/mklevelinfo.pl
blob: 66401f8f016d4b0f8dc0ad11666a7d47be7f7ad0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/perl -w

%struct = (
	0 => [ 2, 'desc', "first 2 bytes are level number in screencodes" ],
	2 => [ 2, 'sub0', "a subroutine" ],
	4 => [ 2, 'sub1', "a subroutine" ],
	6 => [ 2, 'sub2', "a subroutine" ],
	8 => [ 2, 'sub3', "a subroutine" ],
	10 => [ 1, 'num_bombs', "number of bombs to pick up on this level" ],
	11 => [ 1, 'bullet_max', '0 = no bullets, range 0-4.' ],
	12 => [ 1, 'y_start', 'jumpman starting Y position' ],
	13 => [ 1, 'x_start', 'jumpman starting X position' ],
	14 => [ 1, 'fudge_x', 'fudge factor for bomb locations, always $00' ],
	15 => [ 1, 'fudge_y', 'fudge factor for bomb locations, always $06' ],
	16 => [ 1, 'points_per_bomb', 'points awarded per bomb pickup (always $64 aka 100)' ],
	17 => [ 2, 'time_bonus', 'amount of time bonus at start of level' ],
	19 => [ 1, 'offs', 'always $00' ],
	20 => [ 2, 'unkn_table0', 'pointer to ROM table or $06xx' ],
	22 => [ 2, 'map', 'used to draw the level initially (see also map_changes)' ],
	24 => [ 2, 'map_bombs', 'start of bombs in map data (which must come last!)' ],
	26 => [ 2, 'bomblist', 'addr of list of bombs, indexed by player position on coarse 8x8 grid. 2 bytes each, 1st is coarse-grid position, 2nd is: hi 4 bits = change_map index, lo 4 = indirect sub (unused). terminated by $FF.' ],
	28 => [ 2, 'map_changes', 'address of list of addresses of map data, used for changing the map when certain bombs are picked up' ],
	30 => [ 2, 'indirect_subs', 'pointer to list of indirect subs, always $0000 in this game' ],
	32 => [ 2, 'sub_bomb', 'called when a bomb is picked up. $06E6 for most levels (just an RTS), or else a ROM subroutine' ],
	34 => [ 2, 'init', 'called at start of level, $06E6 for some levels, or else a ROM subroutine' ],
	36 => [ 2, 'sub6', 'always $9740 aka game_main_loop' ],
	38 => [ 2, 'sub_eol', 'called at end of level (all bombs picked up). $06E6 for all but level08' ],
	40 => [ 6, 'offs', 'all zeroes' ],
	46 => [ 1, 'colpf3', 'color for missiles (aka 5th player)' ],
	47 => [ 1, 'colpf0', 'color for girders and up-ropes' ],
	48 => [ 1, 'colpf1', 'color for ladders and down-ropes' ],
	49 => [ 1, 'colpf2', 'color for bombs' ],
	50 => [ 5, 'offs', 'unknown' ],
	55 => [ 3, 'offs', 'unknown, always $00 $00 $00' ],
	58 => [ 2, 'offs', 'unknown, not a ROM address' ],
	60 => [ 4, 'offs', 'unknown, level06 (walls) has $ff $ff $ff $ff, all others $00 $00 $00 $00' ],
);

sub mkaddr {
	return sprintf("\$%04x", $_[0]);
}

sub mknum {
	return sprintf("%02d", $_[0]);
}

sub mkrange {
	my ($level, $label, $start, $len, $type, $comment) = @_;
	my $sa = mkaddr($start);
	my $ea = mkaddr($start + $len - 1);
	my $llab;
	if($level >= 0) {
		my $ll = sprintf("%02d", $level + 1);
		$llab = "level$ll";
	} else {
		if($level == -609) {
			$llab = "cur_level";
		} else {
			$llab = "work_level";
		}
		my $l = <<EOF;
label { name "${llab}_$label"; addr $sa; size $len; comment "$comment"; };
EOF
		return $l;
	}
	my $range = <<EOF;
range { name "${llab}_$label"; start $sa; end $ea; type $type; comment "$comment"; };
EOF
	return $range;
}

@lvnames = (
		"Nothing To It",
		"Electrocution",
		"Dumbwaiter",
		"Hellstones",
		"Figurits Revenge",
		"Walls",
		"Zig-Zag",
		"Spellbound",
		"Blackout",
		"HereThereEverywhere",
		"Hatchlings",
		"Hurricane"
);

for $level (-610,-609,0..11) {
	$addr = 0xa000 + $level * 0x40;
	for $offset (sort { $a <=> $b } keys %struct) {
		my ($size, $label, $comment) = @{$struct{$offset}};
		$comment = "Descriptor for $lvnames[$level]. $comment" if $level >= 0 && $offset == 0;
		if($level == 0 && $offset == 0) {
			$comment = "64-byte level descriptors, 12 of them (1 per level). " . $comment;
		}

		$type = 'bytetable';
		if(($label eq 'bomblist') or ($label eq 'init') or ($label =~ /^sub/) or ($label =~ /^map/) or ($label =~ /^unkn_table/)) {
			$type = 'addrtable';
		}

		if($label eq 'time_bonus') {
			$type = 'wordtable';
		}

		if($label eq 'offs') {
			$label .= "_" . mknum($offset);
		}

		print mkrange($level, $label, $addr + $offset, $size, $type, $comment);
	}
	print "\n";
}