-
Notifications
You must be signed in to change notification settings - Fork 0
/
01_plotonscreen.pl
241 lines (161 loc) · 7.48 KB
/
01_plotonscreen.pl
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/local/bin/perl
use strict;
use warnings;
use Test::More;
use Acme::6502;
use lib '.';
use symbols;
use Data::Dumper;
use Carp; $SIG{__DIE__} = sub { Carp::confess @_ };
use PadWalker;
my $symbols = symbols::symbols('newbies.lst');
diag sprintf ".plotonscreen = %x\n", $symbols->{'.plotonscreen'};
diag sprintf ".plot9 = %x\n", $symbols->{'.plot9'};
my $cpu = Acme::6502->new();
$cpu->load_rom( 'newbies.bin', 0xf000 );
$cpu->write_8( $symbols->INTIM, 76 ); # stuff the timer
sub run_cpu {
$cpu->run(10000, sub {
my ($pc, $inst, $a, $x, $y, $s, $p) = @_;
# diag sprintf "pc = %x inst = %x x = %s", $pc, $inst, $x;
if( $pc == $symbols->{'.plot9'} ) {
${ PadWalker::peek_my(1)->{'$ic'} } = 0;
}
});
}
my $view = $symbols->view;
my $viewsize = 0xff - $view;
#
# draw one initial line
#
diag 'drawing one initial line';
$cpu->write_8( $symbols->curplat, 0 ); # controls what color the line drawn will be
$cpu->write_8( $symbols->lastline, 0xff );
$cpu->write_8( $symbols->SWCHB, 0b00000010 ); # select switch off (apparently 0 indicates it is being pressed)
ok my $expected_width = $cpu->read_8( $symbols->perspectivetable + 10 ), 'there is an expected width';
ok my $expected_color = $cpu->read_8( $symbols->level0 + 0 + 3 ), 'there is an expected color';
is $cpu->read_8( $symbols->view + 50 ), 0, "is line 50 blank to start with?";
# Y gets the distance, which we use to figure out which size of line to draw
# X gets the scan line to draw at
$cpu->set_pc($symbols->{'.plotonscreen'} || die);
$cpu->set_y( 10 );
$cpu->set_x( 50 );
run_cpu();
my $line = $cpu->read_8( $symbols->view + 50 );
is $line & 0b11100000, $expected_color, "line drawn with expected color";
is $line & 0b00011111, $expected_width, "line drawn with expected width";
is $cpu->read_8( $symbols->lastline ), 50, "lastline recorded";
is count_lines_drawn(), 1, "one line drawn";
is count_lines_drawn($expected_color), 1, "and it's the right color";
#
# draw a second line as part of the same platform
#
diag 'second line in the same platform';
$cpu->write_8( $symbols->INTIM, 10 ); # enough time left on the timer
ok $expected_width = $cpu->read_8( $symbols->perspectivetable + 9 ), 'there is an expected width';
$cpu->set_pc($symbols->{'.plotonscreen'} || die);
$cpu->set_y( 9 );
$cpu->set_x( 53 );
run_cpu();
$line = $cpu->read_8( $symbols->view + 53 );
is $line & 0b11100000, $expected_color, "line drawn with expected color";
is $line & 0b00011111, $expected_width, "line drawn with expected width";
is $cpu->read_8( $symbols->lastline ), 53, "lastline recorded";
is count_lines_drawn(), 4, "four lines drawn";
is count_lines_drawn_by_color($expected_color), 4, "and they're the right color";
#
# draw a third line as part of the same platform
#
diag 'third line in the same platform';
ok $expected_width = $cpu->read_8( $symbols->perspectivetable + 8 ), 'there is an expected width';
$cpu->set_pc($symbols->{'.plotonscreen'} || die);
$cpu->set_y( 8 );
$cpu->set_x( 57 );
run_cpu();
$line = $cpu->read_8( $symbols->view + 57 );
is $line & 0b11100000, $expected_color, "line drawn with expected color";
is $line & 0b00011111, $expected_width, "line drawn with expected width";
is $cpu->read_8( $symbols->lastline ), 57, "lastline recorded";
is count_lines_drawn(), 8, "eight lines drawn";
is count_lines_drawn_by_color($expected_color), 8, "and they're the right color";
#
# try to draw a 2nd platform over top of part of the first where Z buffering should not allow it to be drawn
#
diag 'drawing a line from a second platform that should be further away in the Z buffer';
$cpu->write_8( $symbols->curplat, 4 ); # controls what color the line drawn will be; this number is a multiple of four
$cpu->write_8( $symbols->lastline, 0xff );
ok my $expected_width_2 = $cpu->read_8( $symbols->perspectivetable + 17 ), 'there is an expected width'; # 17 in is width 8 right now by the way
ok my $expected_color_2 = $cpu->read_8( $symbols->level0 + 4 + 3 ), 'there is an expected color';
isnt $expected_color, $expected_color_2, "second platformis to be a different color than the first";
$cpu->set_pc($symbols->{'.plotonscreen'} || die);
$cpu->set_y( 17 ); # much further away
$cpu->set_x( 52 ); # previously, lines 50-57 have been plotted; aim for somewhere in the middle of that
run_cpu();
$line = $cpu->read_8( $symbols->view + 52 );
isnt $line & 0b11100000, $expected_color_2, "line not drawn with requested color";
isnt $line & 0b00011111, $expected_width_2, "line not drawn with requested width";
is $cpu->read_8( $symbols->lastline ), 52, "lastline not updated";
is count_lines_drawn(), 8, "still eight lines drawn";
is count_lines_drawn_by_color($expected_color), 8, "and they're the right color (that of the first platform)";
ok ! count_lines_drawn_by_color($expected_color_2), "no lines drawn with the second platforms color";
#
# try to draw a 3rd platform over top of part of the first where Z buffering should allow it to be drawn
#
diag 'drawing a line from a third platform that should be closer in the Z buffer';
$cpu->write_8( $symbols->curplat, 8 ); # controls what color the line drawn will be; this number is a multiple of four
$cpu->write_8( $symbols->lastline, 0xff );
ok my $expected_width_3 = $cpu->read_8( $symbols->perspectivetable + 7 ), 'there is an expected width';
ok my $expected_color_3 = $cpu->read_8( $symbols->level0 + 8 + 3 ), 'there is an expected color';
isnt $expected_color, $expected_color_2, "second platformis to be a different color than the first";
$cpu->set_pc($symbols->{'.plotonscreen'} || die);
$cpu->set_y( 7 ); # closer
$cpu->set_x( 54 ); # previously, lines 50-57 have been plotted; aim for somewhere in the middle of that
run_cpu();
$line = $cpu->read_8( $symbols->view + 54 );
is $line & 0b11100000, $expected_color_3, "line drawn with requested color";
is $line & 0b00011111, $expected_width_3, "line drawn with requested width";
is $cpu->read_8( $symbols->lastline ), 54, "lastline updated";
is count_lines_drawn(), 8, "still eight lines drawn";
is count_lines_drawn_by_color($expected_color), 7, "7 of them are the color of the first platform";
is count_lines_drawn_by_color($expected_color_3), 1, "one lines drawn with the third platforms color";
#
# add a second line to the 3rd platform
#
diag 'drawing a line from a second line on the third platform';
$cpu->set_pc($symbols->{'.plotonscreen'} || die);
$cpu->set_y( 7 ); # closer still
$cpu->set_x( 60 ); # draw down below what's been drawn so far
run_cpu();
$line = $cpu->read_8( $symbols->view + 60 );
is $line & 0b11100000, $expected_color_3, "line drawn with requested color";
is $cpu->read_8( $symbols->lastline ), 60, "lastline updated";
is count_lines_drawn(), 11, "eleven lines drawn now";
is count_lines_drawn_by_color($expected_color), 4, "4 of them are the color of the first platform";
is count_lines_drawn_by_color($expected_color_3), 7, "seven lines drawn with the third platforms color now";
#
# util routines
#
sub count_lines_drawn {
my $num = 0;
for my $i ( 0 .. $viewsize - 1 ) {
$num++ if $cpu->read_8( $view + $i );
}
return $num;
}
sub count_lines_drawn_by_color {
my $num = 0;
my $color = shift;
for my $i ( 0 .. $viewsize - 1 ) {
my $line = $cpu->read_8( $view + $i );
$num++ if $color == ( $line & 0b11100000 );
}
return $num;
}
sub dump_screen {
for my $i ( 0 .. $viewsize - 1 ) {
my $line = $cpu->read_8( $view + $i );
diag sprintf "%03d (%02x) %08b\n", $i, $view+$i, $line;
}
}
# dump_screen();
done_testing();