maug
Quick and dirty C mini-augmentation library.
Loading...
Searching...
No Matches
retroviw.h
Go to the documentation of this file.
1
2#ifndef RETROVIW_H
3#define RETROVIW_H
4
28
29#ifndef RETROFLAT_VIEWPORT_TRACE_LVL
30# define RETROFLAT_VIEWPORT_TRACE_LVL 0
31#endif /* !RETROFLAT_VIEWPORT_TRACE_LVL */
32
38#define RETROFLAT_VIEWPORT_FLAG_FULLSCREEN 0x01
39
49 uint8_t flags;
126 int16_t world_tile_x;
127 int16_t world_tile_y;
128 int16_t world_tile_w;
129 int16_t world_tile_h;
130#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
131 MAUG_MHANDLE refresh_grid_h;
140#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
141};
142
143#ifndef DOCUMENTATION
144
145# define retroflat_viewport_world_x_generic() \
146 (g_retroflat_state->viewport.world_x)
147
148# define retroflat_viewport_world_y_generic() \
149 (g_retroflat_state->viewport.world_y)
150
151# define retroflat_viewport_world_tile_x_generic() \
152 (g_retroflat_state->viewport.world_tile_x)
153
154# define retroflat_viewport_world_tile_y_generic() \
155 (g_retroflat_state->viewport.world_tile_y)
156
157# define retroflat_viewport_world_tile_w_generic() \
158 (g_retroflat_state->viewport.world_tile_w)
159
160# define retroflat_viewport_world_tile_h_generic() \
161 (g_retroflat_state->viewport.world_tile_h)
162
163# define retroflat_viewport_world_w_generic() \
164 (g_retroflat_state->viewport.world_w)
165
166# define retroflat_viewport_world_h_generic() \
167 (g_retroflat_state->viewport.world_h)
168
169# define retroflat_viewport_screen_tile_w_generic() \
170 (g_retroflat_state->viewport.screen_tile_w)
171
172# define retroflat_viewport_screen_tile_h_generic() \
173 (g_retroflat_state->viewport.screen_tile_h)
174
175# define retroflat_viewport_screen_w_generic() \
176 (g_retroflat_state->viewport.screen_w)
177
178# define retroflat_viewport_screen_h_generic() \
179 (g_retroflat_state->viewport.screen_h)
180
181# define retroflat_viewport_screen_w_remainder_generic() \
182 (g_retroflat_state->viewport.screen_w_remainder)
183
184# define retroflat_viewport_screen_h_remainder_generic() \
185 (g_retroflat_state->viewport.screen_h_remainder)
186
187# define retroflat_viewport_set_world_generic( w, h ) \
188 debug_printf( 1, "setting viewport world size to %d x %d...", \
189 (int16_t)(w), (int16_t)(h) ); \
190 (g_retroflat_state->viewport.world_w) = (w); \
191 (g_retroflat_state->viewport.world_h) = (h); \
192 (g_retroflat_state->viewport.world_tile_w) = (w) / RETROFLAT_TILE_W; \
193 (g_retroflat_state->viewport.world_tile_h) = (h) / RETROFLAT_TILE_H;
194
195# define retroflat_viewport_screen_x_generic( world_x ) \
196 (g_retroflat_state->viewport.screen_x + \
197 ((world_x) - retroflat_viewport_world_x()))
198
199# define retroflat_viewport_screen_y_generic( world_y ) \
200 (g_retroflat_state->viewport.screen_y + \
201 ((world_y) - retroflat_viewport_world_y()))
202
203# define retroflat_viewport_screen_get_x_generic() \
204 (g_retroflat_state->viewport.screen_x)
205
206# define retroflat_viewport_screen_get_y_generic() \
207 (g_retroflat_state->viewport.screen_y)
208
209#define retroflat_viewport_grid_tile( x_tile, y_tile ) \
210 (g_retroflat_state->viewport.refresh_grid[ \
211 ((y_tile) * (g_retroflat_state->viewport.screen_tile_w + 2)) + \
212 (x_tile)])
213
214void retroflat_viewport_set_world_pos_generic(
216
217MERROR_RETVAL retroflat_viewport_set_refresh_generic(
219
220uint8_t retroflat_viewport_move_x_generic( retroflat_pxxy_t x );
221
222uint8_t retroflat_viewport_move_y_generic( retroflat_pxxy_t y );
223
224MERROR_RETVAL retroflat_viewport_set_pos_size_generic(
227
228# ifndef RETROFLAT_NO_VIEWPORT_REFRESH
229uint8_t retroflat_viewport_tile_is_stale(
230 int x_tile, int y_tile, retroflat_tile_t tile_id );
231# endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
232
233#endif /* !DOCUMENTATION */
234
250 retroflat_pxxy_t range, retroflat_pxxy_t speed );
251
260 struct RETROFLAT_BITMAP* bitmap,
261 int16_t instance,
265
272
279
286
287#ifdef RETROFLAT_VIEWPORT_TRACE_CONSTRAIN
288
289# define retroflat_viewport_constrain_px( x, y, bmp, retact ) \
290 if( \
291 x >= retroflat_bitmap_w( bmp ) || y >= retroflat_bitmap_h( bmp ) || \
292 0 > x || 0 > y \
293 ) { \
294 error_printf( "attempted draw at %d, %d, out of bounds %d x %d", \
295 x, y, retroflat_bitmap_w( bmp ), retroflat_bitmap_h( bmp ) ); \
296 retact; \
297 }
298
299#else
300
312# define retroflat_viewport_constrain_px( x, y, bmp, retact ) \
313 if( \
314 x >= retroflat_bitmap_w( bmp ) || y >= retroflat_bitmap_h( bmp ) || \
315 0 > x || 0 > y \
316 ) { \
317 retact; \
318 }
319
320#endif /* RETROFLAT_TRACE_CONSTRAIN */
321
322#if defined( RETROFLAT_SOFT_VIEWPORT ) || defined( DOCUMENTATION )
323
324# define retroflat_viewport_world_tile_x() \
325 retroflat_viewport_world_tile_x_generic()
326
327# define retroflat_viewport_world_tile_y() \
328 retroflat_viewport_world_tile_y_generic()
329
330# define retroflat_viewport_world_tile_w() \
331 retroflat_viewport_world_tile_w_generic()
332
333# define retroflat_viewport_world_tile_h() \
334 retroflat_viewport_world_tile_h_generic()
339# define retroflat_viewport_world_x() retroflat_viewport_world_x_generic()
340
345# define retroflat_viewport_world_y() retroflat_viewport_world_y_generic()
346
351# define retroflat_viewport_world_w() \
352 retroflat_viewport_world_w_generic()
353
358# define retroflat_viewport_world_h() \
359 retroflat_viewport_world_h_generic()
360
365# define retroflat_viewport_screen_tile_w() \
366 retroflat_viewport_screen_tile_w_generic()
367
372# define retroflat_viewport_screen_tile_h() \
373 retroflat_viewport_screen_tile_h_generic()
374
379# define retroflat_viewport_screen_w() \
380 retroflat_viewport_screen_w_generic()
381
386# define retroflat_viewport_screen_h() \
387 retroflat_viewport_screen_h_generic()
388
394# define retroflat_viewport_screen_w_remainder() \
395 retroflat_viewport_screen_w_remainder_generic()
396
402# define retroflat_viewport_screen_h_remainder() \
403 retroflat_viewport_screen_h_remainder_generic()
404
412# define retroflat_viewport_set_world( w, h ) \
413 retroflat_viewport_set_world_generic( w, h )
414
419# define retroflat_viewport_set_world_pos( x, y ) \
420 retroflat_viewport_set_world_pos_generic( x, y )
421
427# define retroflat_viewport_set_pos_size( x_px, y_px, w_px, h_px ) \
428 retroflat_viewport_set_pos_size_generic( x_px, y_px, w_px, h_px )
429
435# define retroflat_viewport_screen_x( world_x ) \
436 retroflat_viewport_screen_x_generic( world_x )
437
443# define retroflat_viewport_screen_y( world_y ) \
444 retroflat_viewport_screen_y_generic( world_y )
445
450# define retroflat_viewport_screen_get_x() \
451 retroflat_viewport_screen_get_x_generic()
452
457# define retroflat_viewport_screen_get_y() \
458 retroflat_viewport_screen_get_y_generic()
459
468# define retroflat_viewport_move_x( x ) \
469 retroflat_viewport_move_x_generic( x )
470
479# define retroflat_viewport_move_y( y ) \
480 retroflat_viewport_move_y_generic( y )
481
482# define retroflat_viewport_hw_border_x() (0)
483
484# define retroflat_viewport_hw_border_y() (0)
485
486#endif /* RETROFLAT_SOFT_VIEWPORT || DOCUMENTATION */
487
488#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
489
497# define retroflat_viewport_lock_refresh() \
498 if( NULL == g_retroflat_state->viewport.refresh_grid ) { \
499 maug_mlock( \
500 g_retroflat_state->viewport.refresh_grid_h, \
501 g_retroflat_state->viewport.refresh_grid ); \
502 maug_cleanup_if_null_lock( retroflat_tile_t*, \
503 g_retroflat_state->viewport.refresh_grid ); \
504 }
505
513# define retroflat_viewport_unlock_refresh() \
514 if( NULL != g_retroflat_state->viewport.refresh_grid ) { \
515 maug_munlock( \
516 g_retroflat_state->viewport.refresh_grid_h, \
517 g_retroflat_state->viewport.refresh_grid ); \
518 }
519
531# define retroflat_viewport_set_refresh( x, y, tid ) \
532 retroflat_viewport_set_refresh_generic( x, y, tid )
533
534#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
535 /* maug_retroflt_viewport */
537 /* maug_retroflt */
539
540#elif defined( RETROVIW_C )
541
542void retroflat_viewport_set_world_pos_generic(
544) {
545 int x_tile = (x >> RETROFLAT_TILE_W_BITS);
546 int y_tile = (y >> RETROFLAT_TILE_H_BITS);
547#if RETROFLAT_VIEWPORT_TRACE_LVL > 0
548 debug_printf(
549 RETROFLAT_VIEWPORT_TRACE_LVL,
550 "setting viewport world pos to %d, %d (tile %d, %d)...",
551 x, y, x_tile, y_tile );
552#endif /* RETROFLAT_VIEWPORT_TRACE_LVL */
553 g_retroflat_state->viewport.world_x = x;
554 g_retroflat_state->viewport.world_y = y;
555 g_retroflat_state->viewport.world_tile_x = x_tile;
556 g_retroflat_state->viewport.world_tile_y = y_tile;
557}
558
559/* === */
560
561#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
562
563MERROR_RETVAL retroflat_viewport_set_refresh_generic(
565) {
566 int x_tile = 0;
567 int y_tile = 0;
568
569 /* Add +1 tile to make off-screen "-1" tile positive. */
570 x_tile = x_px / RETROFLAT_TILE_W;
571 y_tile = y_px / RETROFLAT_TILE_H;
572
573 if(
574 RETROFLAT_STATE_FLAG_HWSCROLLING ==
575 (RETROFLAT_STATE_FLAG_HWSCROLLING & g_retroflat_state->retroflat_flags) &&
576 RETROFLAT_VIEWPORT_FLAG_FULLSCREEN ==
577 (RETROFLAT_VIEWPORT_FLAG_FULLSCREEN & g_retroflat_state->viewport.flags)
578 ) {
579 /*
580 x_tile++;
581 y_tile++;
582 */
583 }
584
585#if RETROFLAT_VIEWPORT_GRID_TRACE_LVL > 0
586 debug_printf( RETROFLAT_VIEWPORT_GRID_TRACE_LVL,
587 "setting x_tile: %d, y_tile: %d (%d, %d) to: %d",
588 x_tile, y_tile, x_px, y_px, tid );
589#endif /* RETROFLAT_VIEWPORT_GRID_TRACE_LVL */
590
591 assert( NULL != g_retroflat_state->viewport.refresh_grid );
592 if(
593 /* Expand the range by -1 to account for just off-screen tile. */
594 0 > x_tile || 0 > y_tile ||
595 g_retroflat_state->viewport.screen_tile_w + 2 <= x_tile ||
596 g_retroflat_state->viewport.screen_tile_h + 2 <= y_tile
597 ) {
598#if RETROFLAT_VIEWPORT_TRACE_LVL > 0
599 error_printf( "invalid viewport refresh coord: %d, %d", x_tile, y_tile );
600 debug_printf( RETROFLAT_VIEWPORT_TRACE_LVL,
601 "viewport is %dx%d tiles!",
602 g_retroflat_state->viewport.screen_tile_w + 2,
603 g_retroflat_state->viewport.screen_tile_h + 2 );
604#endif /* RETROFLAT_VIEWPORT_TRACE_LVL */
605 return MERROR_GUI;
606 }
607
608 retroflat_viewport_grid_tile( x_tile, y_tile ) = tid;
609
610 return MERROR_OK;
611}
612
613/* === */
614
615#endif /* RETROFLAT_NO_VIEWPORT_REFRESH */
616
617uint8_t retroflat_viewport_move_x_generic( retroflat_pxxy_t x ) {
618 retroflat_pxxy_t new_world_x = g_retroflat_state->viewport.world_x + x;
619
620 /* Keep the viewport in the world arena. */
621 if(
622 0 <= new_world_x &&
623 g_retroflat_state->viewport.world_w >= new_world_x +
624 g_retroflat_state->viewport.screen_w
625 ) {
626 g_retroflat_state->viewport.world_x += x;
627 g_retroflat_state->viewport.world_tile_x =
628 g_retroflat_state->viewport.world_x >> RETROFLAT_TILE_W_BITS;
629 return 1;
630 }
631
632 return 0;
633}
634
635/* === */
636
637uint8_t retroflat_viewport_move_y_generic( retroflat_pxxy_t y ) {
638 retroflat_pxxy_t new_world_y = g_retroflat_state->viewport.world_y + y;
639
640 /* Keep the viewport in the world arena. */
641 if(
642 0 <= new_world_y &&
643 g_retroflat_state->viewport.world_h >= new_world_y +
644 g_retroflat_state->viewport.screen_h
645 ) {
646 g_retroflat_state->viewport.world_y += y;
647 g_retroflat_state->viewport.world_tile_y =
648 g_retroflat_state->viewport.world_y >> RETROFLAT_TILE_H_BITS;
649 return 1;
650 }
651
652 return 0;
653}
654
655/* === */
656
657uint8_t retroflat_viewport_focus(
660) {
661 uint8_t moved = 0,
662 new_moved = 0;
663 int16_t new_pt = 0;
664
665 /* Test if the screen is scrolling east/west. */
666 new_pt = x1 - retroflat_viewport_world_x();
667 if( new_pt > (retroflat_screen_w() >> 1) + range ) {
668 new_moved = retroflat_viewport_move_x(
669 gc_retroflat_offsets8_x[RETROFLAT_DIR8_EAST] * speed );
670 if( !moved && new_moved ) {
671 moved = new_moved;
672 }
673 } else if( new_pt < (retroflat_screen_w() >> 1) - range ) {
674 new_moved = retroflat_viewport_move_x(
675 gc_retroflat_offsets8_x[RETROFLAT_DIR8_WEST] * speed );
676 if( !moved && new_moved ) {
677 moved = new_moved;
678 }
679 }
680
681 /* Test if the screen is scrolling north/south. */
682 new_pt = y1 - retroflat_viewport_world_y();
683 if( new_pt > (retroflat_screen_h() >> 1) + range ) {
684 new_moved = retroflat_viewport_move_y(
685 gc_retroflat_offsets8_y[RETROFLAT_DIR8_SOUTH] * speed );
686 if( !moved && new_moved ) {
687 moved = new_moved;
688 }
689 } else if( new_pt < (retroflat_screen_h() >> 1) - range ) {
690 new_moved = retroflat_viewport_move_y(
691 gc_retroflat_offsets8_y[RETROFLAT_DIR8_NORTH] * speed );
692 if( !moved && new_moved ) {
693 moved = new_moved;
694 }
695 }
696
697 return moved;
698}
699
700/* === */
701
702MERROR_RETVAL retroflat_viewport_set_pos_size_generic(
705) {
706 MERROR_RETVAL retval = MERROR_OK;
707 int x_tile = 0, y_tile = 0;
708
709 if( w_px == retroflat_screen_w() && h_px == retroflat_screen_h() ) {
710 debug_printf( 1, "fullscreen viewport; hardware scrolling enabled!" );
711 g_retroflat_state->viewport.flags |= RETROFLAT_VIEWPORT_FLAG_FULLSCREEN;
712 } else {
713 g_retroflat_state->viewport.flags &= ~RETROFLAT_VIEWPORT_FLAG_FULLSCREEN;
714 }
715
716 /* We're not adding the extra two tiles on each dimension here since this
717 * won't be used for indexing or allocation but rather pixel detection.
718 */
719 if(
720 RETROFLAT_STATE_FLAG_HWSCROLLING ==
721 (RETROFLAT_STATE_FLAG_HWSCROLLING & g_retroflat_state->retroflat_flags) &&
722 RETROFLAT_VIEWPORT_FLAG_FULLSCREEN ==
723 (RETROFLAT_VIEWPORT_FLAG_FULLSCREEN & g_retroflat_state->viewport.flags)
724 ) {
725 /* If fullscreen, allow arbitrary screen width/height since the hardware
726 * scrolling should compensate for that.
727 */
728 g_retroflat_state->viewport.screen_w = w_px;
729 g_retroflat_state->viewport.screen_h = h_px;
730 g_retroflat_state->viewport.screen_w_remainder = 0;
731 g_retroflat_state->viewport.screen_h_remainder = 0;
732
733 } else {
734 /* If not fullscreen, constrain to tile boundaries. */
735 g_retroflat_state->viewport.screen_w =
736 ((w_px) / RETROFLAT_TILE_W) * RETROFLAT_TILE_W;
737 g_retroflat_state->viewport.screen_h =
738 ((h_px) / RETROFLAT_TILE_H) * RETROFLAT_TILE_H;
739 g_retroflat_state->viewport.screen_w_remainder =
740 (x_px) + (w_px) - g_retroflat_state->viewport.screen_w;
741 g_retroflat_state->viewport.screen_h_remainder =
742 (y_px) + (h_px) - g_retroflat_state->viewport.screen_h;
743 }
744
745 g_retroflat_state->viewport.screen_x = x_px;
746 g_retroflat_state->viewport.screen_y = y_px;
747 g_retroflat_state->viewport.screen_tile_w = w_px / RETROFLAT_TILE_W;
748 g_retroflat_state->viewport.screen_tile_h = h_px / RETROFLAT_TILE_H;
749
750 /* Compensate for tiles that are cut off. */
751 if( 0 != w_px % RETROFLAT_TILE_W ) {
752 g_retroflat_state->viewport.screen_tile_w++;
753 }
754
755 if( 0 != h_px % RETROFLAT_TILE_H ) {
756 g_retroflat_state->viewport.screen_tile_h++;
757 }
758
759 debug_printf( 1,
760 "setting viewport screen size to %d x %d (%d x %d tiles)...",
761 g_retroflat_state->viewport.screen_w,
762 g_retroflat_state->viewport.screen_h,
763 g_retroflat_state->viewport.screen_tile_w,
764 g_retroflat_state->viewport.screen_tile_h );
765
766#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
767 if( (MAUG_MHANDLE)NULL != g_retroflat_state->viewport.refresh_grid_h ) {
768 maug_mfree( g_retroflat_state->viewport.refresh_grid_h );
769 }
770 debug_printf( 1, "allocating refresh grid (%d tiles, %d+2x%d+2...)",
771 (g_retroflat_state->viewport.screen_tile_w + 2) *
772 (g_retroflat_state->viewport.screen_tile_h + 2),
773 g_retroflat_state->viewport.screen_tile_w,
774 g_retroflat_state->viewport.screen_tile_h );
775 maug_malloc_test(
776 g_retroflat_state->viewport.refresh_grid_h,
777 (g_retroflat_state->viewport.screen_tile_w + 2) *
778 (g_retroflat_state->viewport.screen_tile_h + 2),
779 sizeof( retroflat_tile_t ) );
780
781 retroflat_viewport_lock_refresh();
782 for(
783 y_tile = 0 ; retroflat_viewport_screen_tile_h() + 2 > y_tile ; y_tile++
784 ) {
785 for(
786 x_tile = 0 ; retroflat_viewport_screen_tile_w() + 2 > x_tile ; x_tile++
787 ) {
788 retroflat_viewport_grid_tile( x_tile, y_tile ) = -1;
789 }
790 }
791 retroflat_viewport_unlock_refresh();
792#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
793
794cleanup:
795
796 return retval;
797}
798
799/* === */
800
801#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
802
803uint8_t retroflat_viewport_tile_is_stale(
804 int x_tile, int y_tile, retroflat_tile_t tile_id
805) {
806 int row_tiles = g_retroflat_state->viewport.screen_tile_w + 2;
807
808 if(
809 RETROFLAT_STATE_FLAG_HWSCROLLING ==
810 (RETROFLAT_STATE_FLAG_HWSCROLLING & g_retroflat_state->retroflat_flags) &&
811 RETROFLAT_VIEWPORT_FLAG_FULLSCREEN ==
812 (RETROFLAT_VIEWPORT_FLAG_FULLSCREEN & g_retroflat_state->viewport.flags)
813 ) {
814 /* Turn negative index into positive. */
815 x_tile++;
816 y_tile++;
817 }
818
819#if RETROFLAT_VIEWPORT_GRID_TRACE_LVL > 0
820 debug_printf( RETROFLAT_VIEWPORT_GRID_TRACE_LVL,
821 "stale check x_tile: %d, y_tile: %d, idx: %d (%dx%d, %d total): %d vs %d",
822 x_tile, y_tile,
823 (y_tile * row_tiles) + x_tile,
824 g_retroflat_state->viewport.screen_tile_w + 2,
825 g_retroflat_state->viewport.screen_tile_h + 2,
826 (g_retroflat_state->viewport.screen_tile_w + 2) *
827 (g_retroflat_state->viewport.screen_tile_h + 2),
828 tile_id, retroflat_viewport_grid_tile( x_tile, y_tile ) );
829#endif /* RETROFLAT_VIEWPORT_GRID_TRACE_LVL */
830
831 return tile_id != retroflat_viewport_grid_tile( x_tile, y_tile );
832}
833
834#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
835
836/* === */
837
838MERROR_RETVAL retroflat_viewport_trim_px(
839 struct RETROFLAT_BITMAP* bitmap,
840 int16_t instance,
844) {
845 retroflat_pxxy_t trim_bottom = *d_y + *h;
846 retroflat_pxxy_t trim_right = *d_x + *w;
847 retroflat_pxxy_t viewport_bottom = 0;
848 retroflat_pxxy_t viewport_right = 0;
849 retroflat_pxxy_t viewport_left = 0;
850 retroflat_pxxy_t viewport_top = 0;
851
852 if(
853 /* On the screen, constrain to the edges of the viewport. */
854 retroflat_screen_buffer() == bitmap &&
855 /* Probably blitting a window or other element that can go anywhere. */
856 RETROFLAT_INSTANCE_NULL != instance &&
857 /* The viewport is not fullscreen, so constrain to its tighter limits. */
858 RETROFLAT_VIEWPORT_FLAG_FULLSCREEN !=
859 (RETROFLAT_VIEWPORT_FLAG_FULLSCREEN &
860 g_retroflat_state->viewport.flags)
861 ) {
862 viewport_left = retroflat_viewport_screen_get_x();
863 viewport_top = retroflat_viewport_screen_get_y();
864 viewport_bottom =
865 (retroflat_viewport_screen_get_y() + retroflat_viewport_screen_h());
866 viewport_right =
867 (retroflat_viewport_screen_get_x() + retroflat_viewport_screen_w());
868
869 } else {
870 /* Constrain to the edges of the arbitrary bitmap. */
871 viewport_bottom = retroflat_bitmap_h( bitmap );
872 viewport_right = retroflat_bitmap_w( bitmap );
873 }
874
875 if( viewport_bottom < *d_y || trim_bottom < viewport_top ) {
876#ifdef RETROFLAT_TRACE_CONSTRAIN
877 error_printf( "attempted to blit bitmap way out of bounds at %d, %d!",
878 *d_x, *d_y );
879#endif /* RETROFLAT_TRACE_CONSTRAIN */
880 return MERROR_GUI;
881
882 } else if( viewport_bottom <= trim_bottom ) {
883#ifdef RETROFLAT_TRACE_CONSTRAIN
884 error_printf(
885 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
886 SIZE_T_FMT,
887 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
888#endif /* RETROFLAT_TRACE_CONSTRAIN */
889 *h -= (trim_bottom - viewport_bottom);
890
891 } else if( viewport_top > *d_y ) {
892#ifdef RETROFLAT_TRACE_CONSTRAIN
893 error_printf(
894 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
895 SIZE_T_FMT,
896 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
897#endif /* RETROFLAT_TRACE_CONSTRAIN */
898 *h -= (viewport_top - *d_y);
899 if( NULL != s_y ) {
900 *s_y += (viewport_top - *d_y);
901 }
902 *d_y += (viewport_top - *d_y);
903 assert( viewport_top == *d_y );
904 }
905
906 if( viewport_right < *d_x || trim_right < viewport_left ) {
907#ifdef RETROFLAT_TRACE_CONSTRAIN
908 error_printf( "attempted to blit bitmap way out of bounds at %d, %d!",
909 *d_x, *d_y );
910#endif /* RETROFLAT_TRACE_CONSTRAIN */
911 return MERROR_GUI;
912
913 } else if( viewport_right <= trim_right ) {
914#ifdef RETROFLAT_TRACE_CONSTRAIN
915 error_printf(
916 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
917 SIZE_T_FMT,
918 trim_right - viewport_right, trim_right, viewport_right );
919#endif /* RETROFLAT_TRACE_CONSTRAIN */
920 *w -= (trim_right - viewport_right);
921
922 } else if( viewport_left > *d_x ) {
923#ifdef RETROFLAT_TRACE_CONSTRAIN
924 error_printf(
925 "trimming " SIZE_T_FMT " pixels to get " SIZE_T_FMT " under "
926 SIZE_T_FMT,
927 trim_bottom - viewport_bottom, trim_bottom, viewport_bottom );
928#endif /* RETROFLAT_TRACE_CONSTRAIN */
929 *w -= (viewport_left - *d_x);
930 if( NULL != s_x ) {
931 *s_x += (viewport_left - *d_x);
932 }
933 *d_x += (viewport_left - *d_x);
934 assert( viewport_left == *d_x );
935 }
936
937 if( 0 == w && 0 == h ) {
938 return MERROR_GUI;
939 }
940
941 return MERROR_OK;
942}
943
944/* === */
945
946#ifndef RETROFLAT_NO_VIEWPORT_REFRESH
947
948MERROR_RETVAL retroflat_viewport_clear_refresh( retroflat_pxxy_t y_max ) {
949 MERROR_RETVAL retval = MERROR_OK;
950 int x = 0, y = 0;
951
952#if RETROTILE_TRACE_LVL > 0
953 debug_printf( RETROTILE_TRACE_LVL,
954 "clearing " SIZE_T_FMT " vertical viewport pixels (" SIZE_T_FMT
955 " rows)...",
956 y_max, y_max / RETROFLAT_TILE_H );
957#endif /* RETROTILE_TRACE_LVL */
958
959 retroflat_viewport_lock_refresh();
960 for( y = 0 ; y_max > y ; y += RETROFLAT_TILE_H ) {
961 for(
962 x = 0 ; retroflat_viewport_screen_tile_w() > x ; x += RETROFLAT_TILE_W
963 ) {
964 retroflat_viewport_grid_tile( x, y ) = -1;
965 }
966 }
967
968cleanup:
969
970 retroflat_viewport_unlock_refresh();
971
972 return retval;
973}
974
975#if 0
976/* === */
977
978MERROR_RETVAL retroflat_viewport_shift_x( int8_t shift ) {
979 MERROR_RETVAL retval = MERROR_OK;
980 int y_tile;
981 /* Make some of these calculations appear less gnarly. */
982
983 if( 0 == shift ) {
984 error_printf( "null shift requested!" );
985 retval = MERROR_GUI;
986 goto cleanup;
987 }
988
989 /* Shift the adaptive refresh grid over accordingly, row by row. */
990 retroflat_viewport_lock_refresh();
991 for(
992 y_tile = 0;
993 (g_retroflat_state->viewport.screen_tile_h + 2) > y_tile;
994 y_tile++
995 ) {
996 if( 0 < shift ) {
997 /* Perform the (rightward) shift. */
998 /*
999 memmove(
1000 &(g_retroflat_state->viewport.refresh_grid[
1001 (y_tile * row_sz) + 1]),
1002 &(g_retroflat_state->viewport.refresh_grid[y_tile * row_sz]),
1003 row_sz - 1 );
1004 */
1005
1006 /* Mark the oncoming tile as dirty. */
1007 retroflat_viewport_grid_tile( 0, y_tile ) = -1;
1008
1009 } else {
1010 /* Perform the (leftward) shift. */
1011 /*
1012 memmove(
1013 &(g_retroflat_state->viewport.refresh_grid[y_tile * row_sz]),
1014 &(g_retroflat_state->viewport.refresh_grid[
1015 (y_tile * row_sz) + 1]),
1016 g_retroflat_state->viewport.screen_tile_w - 1 );
1017 */
1018
1019 /* Mark the oncoming tile as dirty. */
1020 retroflat_viewport_grid_tile( 0, y_tile ) = -1;
1021 }
1022 }
1023 retroflat_viewport_unlock_refresh();
1024
1025cleanup:
1026
1027 return retval;
1028}
1029
1030/* === */
1031
1032MERROR_RETVAL retroflat_viewport_shift_y( int8_t shift ) {
1033 MERROR_RETVAL retval = MERROR_OK;
1034 int y_tile;
1035 /* Make some of these calculations appear less gnarly. */
1036
1037 /* Shift the adaptive refresh grid up/down accordingly, row by row. */
1038 retroflat_viewport_lock_refresh();
1039 if( 0 < shift ) {
1040 for(
1041 /* Start on the next-to-last row. */
1042 y_tile = g_retroflat_state->viewport.screen_tile_h;
1043 0 <= y_tile;
1044 /* Move upwards. */
1045 y_tile--
1046 ) {
1047 /*
1048 memmove(
1049 &(g_retroflat_state->viewport.refresh_grid[
1050 (y_tile + 1) * row_sz]),
1051 &(g_retroflat_state->viewport.refresh_grid[
1052 y_tile * row_sz]),
1053 row_sz );
1054 */
1055
1056 }
1057
1058 /* Mark the oncoming tiles as dirty. */
1059 memset(
1060 &retroflat_viewport_grid_tile( 0, y_tile ),
1061 -1,
1062 (g_retroflat_state->viewport.screen_tile_w + 2) *
1063 sizeof( retroflat_tile_t ) );
1064
1065 } else {
1066 for(
1067 y_tile = 1;
1068 g_retroflat_state->viewport.screen_tile_h + 2 > y_tile;
1069 /* Move downwards. */
1070 y_tile++
1071 ) {
1072 /*
1073 memmove(
1074 &(g_retroflat_state->viewport.refresh_grid[
1075 (y_tile - 1) * row_sz]),
1076 &(g_retroflat_state->viewport.refresh_grid[
1077 y_tile * row_sz]),
1078 row_sz );
1079 */
1080
1081 }
1082
1083 /* Mark the oncoming tiles as dirty. */
1084 memset( &(g_retroflat_state->viewport.refresh_grid[0]), -1,
1085 (g_retroflat_state->viewport.screen_tile_w + 2) *
1086 sizeof( retroflat_tile_t ) );
1087 }
1088 retroflat_viewport_unlock_refresh();
1089
1090cleanup:
1091
1092 return retval;
1093}
1094#endif
1095
1096#endif /* !RETROFLAT_NO_VIEWPORT_REFRESH */
1097
1098#endif /* RETROVIW_C */
1099
uint16_t MERROR_RETVAL
Return type indicating function returns a value from this list.
Definition merror.h:28
#define RETROFLAT_INSTANCE_NULL
Pass to retroflat_blit_bitmap() instance arg if this is not a sprite (i.e. if it is a background tile...
Definition retroflt.h:620
MERROR_RETVAL retroflat_viewport_trim_px(struct RETROFLAT_BITMAP *bitmap, int16_t instance, retroflat_pxxy_t *s_x, retroflat_pxxy_t *s_y, retroflat_pxxy_t *d_x, retroflat_pxxy_t *d_y, retroflat_pxxy_t *w, retroflat_pxxy_t *h)
Chop w/h down to fit inside viewport or just fail if it's impossible.
MERROR_RETVAL retroflat_viewport_shift_viewport_x(int8_t shift)
Shift the viewport refresh grid 1 tile in the given direction.
MERROR_RETVAL retroflat_viewport_shift_viewport_y(int8_t shift)
Shift the viewport refresh grid 1 tile in the given direction.
uint8_t retroflat_viewport_focus(retroflat_pxxy_t x1, retroflat_pxxy_t y1, retroflat_pxxy_t range, retroflat_pxxy_t speed)
Move the viewport in a direction or combination thereof so that it's focusing the given x1/y1 within ...
MERROR_RETVAL retroflat_viewport_clear_refresh(retroflat_pxxy_t y_max)
Set all viewport refresh tiles as dirty, starting from 0 and moving downwards until reaching y_max.
int16_t retroflat_pxxy_t
Type used for surface pixel coordinates.
Definition retroflt.h:931
#define RETROTILE_TRACE_LVL
If defined, bring debug printf statements up to this level.
Definition retrotil.h:42
int16_t retroflat_tile_t
Value for an individual tile in a RETROTILE_LAYER.
Definition retroflt.h:19
The viewport data struct. There is generally only one of these, to which all helpers implicitly refer...
Definition retroviw.h:48
retroflat_pxxy_t world_x
The X offset, in pixels, of the viewport on the world tilemap. Should only be retrieved through retro...
Definition retroviw.h:67
retroflat_tile_t * refresh_grid
A grid of tile values representing the last-drawn values on-screen.
Definition retroviw.h:139
retroflat_pxxy_t screen_h
Viewport height in pixels. Should only be retrieved through retroflat_viewport_screen_w() and set thr...
Definition retroviw.h:97
retroflat_pxxy_t screen_h_remainder
Difference between viewport height and screen height in pixels. Should only be retrieved through retr...
Definition retroviw.h:111
retroflat_pxxy_t screen_y
Y position of the viewport in real screen memory in pixels. Should only be retrieved through retrofla...
Definition retroviw.h:61
retroflat_pxxy_t screen_x
X position of the viewport in real screen memory in pixels. Should only be retrieved through retrofla...
Definition retroviw.h:55
int16_t screen_tile_w
The number of tiles across that fit in the viewport. Should only be retrieved through retroflat_viewp...
Definition retroviw.h:118
retroflat_pxxy_t world_w
The width of the entire world tilemap in pixels. Should only be retrieved through retroflat_viewport_...
Definition retroviw.h:79
retroflat_pxxy_t world_y
The Y offset, in pixels, of the viewport on the world tilemap. Should only be retrieved through retro...
Definition retroviw.h:73
retroflat_pxxy_t screen_w_remainder
Difference between viewport width and screen width in pixels. Should only be retrieved through retrof...
Definition retroviw.h:104
retroflat_pxxy_t screen_w
Viewport width in pixels. Should only be retrieved through retroflat_viewport_screen_w() and set thro...
Definition retroviw.h:91
int16_t screen_tile_h
The number of tiles high that fit in the viewport. Should only be retrieved through retroflat_viewpor...
Definition retroviw.h:125
retroflat_pxxy_t world_h
The height of the entire world tilemap in pixels. Should only be retrieved through retroflat_viewport...
Definition retroviw.h:85