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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
diff --git a/README.md b/README.md
index b9e708c..01aa299 100644
--- a/README.md
+++ b/README.md
@@ -29,10 +29,13 @@ Usage
-comment Emit comments
-call Emit callers
-access Emit accessors
+ -extern Emit labels for out-of-range addresses
+ -rangelabels Emit labels for ranges instead of base+offset
-verbose Print info to STDERR
-dump Print options in format for -a
-a FILE Read options from FILE. Lines are: OPTION VALUE
+ Addresses may include a range, e.g. table=$300+F
Addresses may include xex segment number, e.g. 3:1FAE
Examples
diff --git a/dis b/dis
index 13090f4..83a3be2 100755
--- a/dis
+++ b/dis
@@ -41,7 +41,7 @@ use constant {
sub state {
return {
- #mem => [map [0], 0 .. 0x10000],
+ mem => [map [0], 0 .. 0x10000],
segnum => 0,
};
}
@@ -79,10 +79,10 @@ sub labels {
(?:\+([0-9a-fA-F]+))? # optional range in hex
/x;
$match or die "ERROR: Unrecognized $opt address: $value\n";
- my $label = $1;
my $segnum = $2 || 0;
my $base = hex($3);
my $range = hex($4||0);
+ my $label = $1 || sprintf "u%2X", $base;
for my $off (0 .. $range) {
my $addr = $base + $off;
if (($addr & 0xFFFF) != $addr) {
@@ -92,6 +92,7 @@ sub labels {
if (defined $state->{$opt}{$segnum}{$addr}) {
warn sprintf "WARNING: Duplicate $opt: $value: %X\n",
$addr;
+ next;
}
$state->{$opt}{$segnum}{$addr} =
$off ? $rangelabels ? sprintf "${label}_%X", $off :
@@ -194,14 +195,18 @@ sub trace {
my $targ = rel($i, $i1);
trace($state, $targ, $byte->[LABEL], $i);
} elsif ($mode =~ /Ind|Z-Page/) {
- my $tlabel = $mem->[$i1][LABEL];
+ my $data = $mem->[$i1];
+ my $pre = $data->[SEGNUM] ? sprintf "s$data->[SEGNUM]" : "";
+ my $tlabel = $data->[LABEL] ||= $pre . sprintf "l%02X", $i1;
push @{$byte->[TARGETS]}, $tlabel if $tlabel;
- push @{$mem->[$i1][ACCESSORS]}, seglabel($state, $i);
+ push @{$data->[ACCESSORS]}, seglabel($state, $i);
} elsif ($mode =~ /Absolute/) {
my $addr = addr($i1, $i2);
- my $tlabel = $mem->[$addr][LABEL];
+ my $data = $mem->[$addr];
+ my $pre = $data->[SEGNUM] ? sprintf "s$data->[SEGNUM]" : "";
+ my $tlabel = $data->[LABEL] ||= $pre . sprintf "l%04X", $addr;
push @{$byte->[TARGETS]}, $tlabel if $tlabel;
- push @{$mem->[$addr][ACCESSORS]}, seglabel($state, $i);
+ push @{$data->[ACCESSORS]}, seglabel($state, $i);
}
$i += $len[$code];
}
@@ -214,23 +219,24 @@ sub extern {
return if not $opts->{extern};
return if not $opts->{labels};
my @labels;
- for my $opt (qw(code data vector)) {
- for my $labels (values %{$state->{$opt}||{}}) {
- for my $addr (sort {$a <=> $b} keys %$labels) {
- my $label = $labels->{$addr} or next;
- next if $opts->{labelled}{$label};
- next if not $opts->{referenced}{$label};
- next if $label =~ /\+/;
- my $accessors = $state->{mem}[$addr][ACCESSORS];
- my $access = "";
- if ($accessors and $opts->{access}) {
- $access = "\t\t; " . join " ", "Access:", uniq @$accessors;
- }
- push @labels, [$addr,
- sprintf "$labels->{$addr} equ \$%X$access\n", $addr];
- }
+ for (my $addr = 0; $addr < 0x10000; ++$addr) {
+ my $label = $state->{mem}[$addr][LABEL] or next;
+ next if $opts->{labelled}{$label};
+ next if not $opts->{referenced}{$label};
+ next if $label =~ /\+/;
+ my $comment = "";
+ my $accessors = $state->{mem}[$addr][ACCESSORS];
+ if ($accessors and $opts->{access}) {
+ $comment .= "\t\t; " . join " ", "Access:", uniq @$accessors;
}
+ my $callers = $state->{mem}[$addr][CALLERS];
+ if ($callers and $opts->{call}) {
+ $comment .= "\t\t; " . join " ", "Callers:", uniq @$callers;
+ }
+ push @labels, [$addr,
+ sprintf "$label equ \$%X$comment\n", $addr];
}
+ print "##EXTERN##\n";
print map $_->[1], sort { $a->[0] <=> $b->[0] } @labels;
}
@@ -286,8 +292,6 @@ sub dis {
my $targ = $imm8 = $imm16 = $rel = $targets->[-1];
$targ =~ s/\+.*//;
$opts->{referenced}{$targ}++;
- # Use z: if label is not predeclared in zero-page
- $imm8 = "z:$imm8" if not defined $mem->[$i1][VALUE];
} elsif ($mode eq "Immediate" and $state->{constant}{$segnum}{$i1}) {
$imm8 = $state->{constant}{$segnum}{$i1};
$opts->{referenced}{$imm8}++;
@@ -522,7 +526,7 @@ sub raw {
my ($stream, $opts) = @_;
my $start = hex($opts->{org}||0);
my $end = $start + (length $stream) - 1;
- printf " opt h-\n";
+ printf " opt h-\n" unless $opts->{headers};
printf " org \$%04X\n", $start;
my $state = state();
layer($state, $start, $end, $stream);
@@ -616,6 +620,7 @@ sub main {
call!
access!
extern!
+ headers!
verbose!
dump!
arg|a=s@
@@ -650,6 +655,13 @@ sub main {
warn "WARNING: Truncating file at 1M\n";
}
+ if ($opts{extern} and open my $pipe, "-|") {
+ $_ = do { local $/; <$pipe> };
+ s/(.*)##EXTERN##\n(.*)/$2$1/s;
+ print;
+ exit 0;
+ }
+
if ($opts{type} eq "xex") {
xex($stream, \%opts);
} elsif ($opts{type} eq "prg") {
diff --git a/sid.dop b/sid.dop
index 0a85ddf..ea19fab 100644
--- a/sid.dop
+++ b/sid.dop
@@ -28,4 +28,4 @@ data SIDPADX=$D419
data SIDPADY=$D41A
data SIDOSCIL=$D41B
data SIDENVEL=$D41C
-data SID=$D41D+D2
+data SID=$D41D+E2
diff --git a/sys.dop b/sys.dop
index 96c7266..a875e15 100644
--- a/sys.dop
+++ b/sys.dop
@@ -339,7 +339,7 @@ data COLOR2=$2C6
data COLOR3=$2C7
data COLOR4=$2C8 ;BACKGROUND
;($2C9 - $2DF SPARE)
-data GLBABS=$2E0 ;GLOBAL VARIABLES
+data GLBABS=$2E0+2 ;GLOBAL VARIABLES
;($2E0 - $2E3 SPARE)
data RAMSIZ=$2E4 ;RAM SIZE (HI BYTE ONLY)
data MEMTOP=$2E5+1 ;TOP OF AVAILABLE MEMORY
|