/[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

Annotation of /Screen.pm

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26