/[VRac]/Screen.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /Screen.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 142 - (show annotations)
Sun Aug 5 01:31:41 2007 UTC (16 years, 8 months ago) by dpavlin
File size: 5850 byte(s)
request a bunch of flags to help with zoom. It doesn't seem to help on my
machine, but can't hurn either...
1 package Screen;
2
3 # Dobrica Pavlinusic, <dpavlin@rot13.org> 07/30/07 17:58:55 CEST
4
5 use strict;
6 use warnings;
7
8 use SDL::App;
9 use SDL::Rect;
10 use SDL::Color;
11 use SDL::Constants;
12
13 use Carp qw/confess/;
14 use Data::Dump qw/dump/;
15
16 use Exporter 'import';
17 our @EXPORT = qw'$white $black';
18
19 use base qw(Class::Accessor Prefs);
20 __PACKAGE__->mk_accessors(qw(app event));
21
22 =head1 NAME
23
24 Screen - simulated 256*256 pixels monochrome screen using SDL
25
26 =head2 open_screen
27
28 Open simulated screen
29
30 =cut
31
32 our $app;
33
34 sub open_screen {
35 my $self = shift;
36
37 $self->prefs;
38
39 if ( ! $self->scale ) {
40 $self->scale( 1 );
41 warn "using default unscaled display\n";
42 }
43
44 $app = SDL::App->new(
45 -width => 256 * $self->scale + ( $self->show_mem ? 256 : 0 ),
46 -height => 256 * $self->scale,
47 -depth => 16,
48 -flags=>SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWACCEL,
49 );
50 #$app->grab_input( SDL_GRAB_QUERY );
51 $app->grab_input( SDL_GRAB_OFF );
52
53 $self->app( $app );
54
55 my $event = SDL::Event->new();
56 $self->event( $event );
57
58 warn "# created SDL::App\n";
59 }
60
61 our $white = SDL::Color->new( -r => 0xff, -g => 0xff, -b => 0xff );
62 our $black = SDL::Color->new( -r => 0x80, -g => 0x80, -b => 0x80 );
63
64 my $red = SDL::Color->new( -r => 0xff, -g => 0x00, -b => 0x00 );
65 my $green = SDL::Color->new( -r => 0x00, -g => 0xff, -b => 0x00 );
66 my $blue = SDL::Color->new( -r => 0x00, -g => 0x00, -b => 0xff );
67
68 my $rect_mem = SDL::Rect->new( -x => 256, -y => 0, -width => 256, -height => 256 );
69
70 =head2 mem_xy
71
72 Helper to return x and y coordinates in memory map
73
74 my ( $x,$y ) = $screen->mem_xy( $address );
75
76 =cut
77
78 sub mem_xy {
79 my $self = shift;
80 my $offset = shift;
81 my $x = $offset & 0xff;
82 $x += 256 * $self->scale;
83 my $y = $offset >> 8;
84 return ($x,$y);
85 }
86
87 =head2 mmap_pixel
88
89 Draw pixel in memory map
90
91 $self->mmap_pixel( $addr, $r, $g, $b );
92
93 =cut
94
95 # keep accesses to memory
96 my $_mem_stat;
97
98 sub mmap_pixel {
99 my ( $self, $addr, $r, $g, $b ) = @_;
100 return unless $self->show_mem && $self->app;
101
102 my ( $x, $y ) = $self->mem_xy( $addr );
103 warn sprintf "## mem %04x %02x %02x %02d*%02d\n", $addr, $r, $g, $x, $y if $self->debug;
104
105 my $col = SDL::Color->new( -r => $r, -g => $g, -b => $b );
106 $self->app->pixel( $x, $y, $col );
107
108 $_mem_stat++;
109 if ( $_mem_stat % 1000 == 0 ) {
110 $self->app->sync;
111 }
112 }
113
114
115 =head2 sync
116
117 $self->sync;
118
119 =cut
120
121 sub sync {
122 $app->sync;
123 }
124
125 =head2 render_vram
126
127 Render one frame of video ram
128
129 $self->render_vram;
130
131 =cut
132
133 sub render_vram {
134 my $self = shift;
135
136 confess "please implement $self::render_vram";
137 }
138
139
140 =head2 render_frame
141
142 Render one frame of video ram
143
144 $self->render_frame( $vram_sdl_surface );
145
146 =cut
147
148 sub render_frame {
149 my $self = shift;
150
151 my $vram = shift;
152 confess "need SDL::Surface as argument" unless ref($vram) eq 'SDL::Surface';
153
154 $vram->display_format;
155
156 my $scale = $self->scale || confess "no scale?";
157
158 my $rect = SDL::Rect->new( -x => 0, -y => 0, -width => 256 * $scale, -height => 256 * $scale );
159 my $rect_screen = SDL::Rect->new( -x => 0, -y => 0, -width => 256 * $scale, -height => 256 * $scale );
160
161 if ( $scale > 1 ) {
162 use SDL::Tool::Graphic;
163 # last parametar is anti-alias
164 my $zoomed = SDL::Tool::Graphic->zoom( $vram, $self->scale, $self->scale, 1 );
165 $zoomed->blit( $rect, $app, $rect_screen );
166 } else {
167 $vram->blit( $rect, $app, $rect_screen );
168 }
169
170 $app->sync;
171 }
172
173
174 =head2 render_mem
175
176 $self->render_mem( @mem );
177
178 =cut
179
180 sub render_mem {
181 my $self = shift;
182
183 return unless $self->show_mem;
184
185 my $pixels = pack("C*", @_);
186
187 my $vram = SDL::Surface->new(
188 -width => 256,
189 -height => 256,
190 -depth => 8, # 1 bit per pixel
191 -pitch => 256, # bytes per line
192 -from => $pixels,
193 -Rmask => 0xffff00ff,
194 -Gmask => 0xffff00ff,
195 -Bmask => 0xffff00ff,
196 );
197
198 $vram->display_format;
199
200 my $rect = SDL::Rect->new( -x => 0, -y => 0, -width => 256, -height => 256 );
201 $vram->blit( $rect, $app, $rect_mem );
202
203 $app->sync;
204 }
205
206 =head2 key_pressed
207
208 Check SDL event loop if there are any pending keys
209
210 my $key = $self->key_pressed;
211
212 if ( $self->key_pressed( 1 ) ) {
213 # just to check other events, don't process
214 # key
215 }
216
217 =cut
218
219 my $pending_key;
220 my $run_for = 2000;
221
222 my $key_down;
223
224 sub key_down {
225 my $self = shift;
226 my $key = shift;
227 warn "key_down($key) = ",$key_down->{$key}, "\n" if $self->debug;
228 return $key_down->{$key};
229 }
230
231 sub key_pressed {
232 my $self = shift;
233
234 # don't take key, just pull event
235 my $just_checking = shift || 0;
236
237 my $event = $self->event || confess "no event?";
238
239 $event->poll || return $pending_key;
240
241 my $type = $event->type();
242
243 exit if ($type == SDL_QUIT);
244
245 my $k = $pending_key;
246
247 if ($type == SDL_KEYDOWN) {
248 $k = $event->key_name();
249 $key_down->{$k}++;
250 if ( $k eq 'escape' ) {
251 $run_for = $self->cli;
252 warn "will check event loop every $run_for cycles\n";
253 $pending_key = '~';
254 } else {
255 warn "SDL_KEYDOWN ($type) = '$k'", $just_checking ? ' fake' : '', "\n";
256 $pending_key = $k;
257 }
258 } elsif ( $type == SDL_KEYUP ) {
259 my $up = $event->key_name();
260 $key_down->{$up} = 0;
261 warn "SDL_KEYUP ($type) = '$up'", $just_checking ? ' fake' : '', "\n";
262 undef $pending_key;
263 }
264
265 warn "key_pressed = $pending_key\n" if $pending_key;
266
267 return $pending_key;
268 }
269
270 =head2 loop
271
272 Implement CPU run for C<$run_run> cycles inside SDL event loop
273
274 $self->loop( sub {
275 my $run_for = shift;
276 CPU::exec( $run_for );
277 $self->render_vram;
278 } );
279
280 =cut
281
282 sub loop {
283 my $self = shift;
284 my $exec = shift;
285
286 confess "need coderef as argument" unless ref($exec) eq 'CODE';
287 my $event = SDL::Event->new();
288
289 while ( 1 ) {
290 $self->key_pressed( 1 );
291 $exec->($run_for);
292 }
293 }
294
295 =head1 SEE ALSO
296
297 L<Orao> is sample implementation using this module
298
299 =head1 AUTHOR
300
301 Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>
302
303 =head1 COPYRIGHT & LICENSE
304
305 Copyright 2007 Dobrica Pavlinusic, All Rights Reserved.
306
307 This program is free software; you can redistribute it and/or modify it
308 under the same terms as Perl itself.
309
310 =cut
311 1;

  ViewVC Help
Powered by ViewVC 1.1.26