1 #include <rl_map.h>
2 #include <rl_memory.h>
3 #include <rl_backgrnd.h>
4 
5 #include <string.h>
6 
7 #include <rl_endian.c>
8 
destroy(const rl_map_t * map)9 static rl_map_t* destroy( const rl_map_t* map )
10 {
11   if ( map )
12   {
13     for ( int i = map->num_layers - 1; i >= 0; --i )
14     {
15       rl_free( (void*)map->layers[ i ] );
16     }
17 
18     if ( map->layer0 )
19     {
20       rl_free( (void*)map->layer0 );
21     }
22 
23     rl_free( (void*)map );
24   }
25 
26   return NULL;
27 }
28 
alloc_zero(size_t size)29 static void* alloc_zero( size_t size )
30 {
31   void* ptr = rl_malloc( size );
32 
33   if ( ptr )
34   {
35     memset( ptr, 0, size );
36   }
37 
38   return ptr;
39 }
40 
rl_map_create(const void * data,size_t size,const rl_tileset_t * tileset,const rl_imageset_t * imageset)41 rl_map_t* rl_map_create( const void* data, size_t size, const rl_tileset_t* tileset, const rl_imageset_t* imageset )
42 {
43   union
44   {
45     const void*     restrict v;
46     const uint8_t*  restrict u8;
47     const uint16_t* restrict u16;
48     const uint32_t* restrict u32;
49   }
50   ptr;
51 
52   ptr.v = data;
53 
54   int width      = ne16( *ptr.u16++ );
55   int height     = ne16( *ptr.u16++ );
56   int num_layers = ne16( *ptr.u16++ );
57   int flags      = ne16( *ptr.u16++ );
58 
59   rl_map_t* map = (rl_map_t*)alloc_zero( sizeof( rl_map_t ) + ( num_layers - 1 ) * sizeof( rl_layern_t* ) );
60 
61   if ( !map )
62   {
63     return NULL;
64   }
65 
66   map->width      = width;
67   map->height     = height;
68   map->num_layers = num_layers;
69   map->flags      = flags;
70   map->tileset    = tileset;
71   map->imageset   = imageset;
72 
73   map->layer0 = (rl_layer0_t*)alloc_zero( width * height * sizeof( uint16_t ) );
74 
75   if ( !map->layer0 )
76   {
77     return destroy( map );
78   }
79 
80   uint16_t* restrict ndx = (uint16_t*)( (uint8_t*)map->layer0 + sizeof( rl_layer0_t ) );
81   const uint16_t* restrict end = ndx + width * height;
82 
83   while ( ndx < end )
84   {
85     *ndx++ = ne16( *ptr.u16++ );
86   }
87 
88   for ( int i = 1; i < num_layers; i++ )
89   {
90     map->layers[ i - 1 ] = (rl_layern_t*)alloc_zero( width * height * sizeof( uint16_t ) );
91 
92     if ( !map->layers[ i - 1 ] )
93     {
94       return destroy( map );
95     }
96 
97     ndx = (uint16_t*)( (uint8_t*)map->layers[ i - 1 ] + sizeof( rl_layern_t ) );
98     end = ndx + width * height;
99 
100     while ( ndx < end )
101     {
102       *ndx++ = ne16( *ptr.u16++ );
103     }
104   }
105 
106   int numqw = ( width * height + 31 ) / 32;
107   uint32_t* restrict collision = (uint32_t*)rl_malloc( numqw * sizeof( uint32_t ) );
108 
109   if ( !collision )
110   {
111     return destroy( map );
112   }
113 
114   map->collision = collision;
115   const uint32_t* restrict coll_end = collision + numqw;
116 
117   while ( collision < coll_end )
118   {
119     *collision++ = ne32( *ptr.u32++ );
120   }
121 
122   return map;
123 }
124 
rl_map_destroy(const rl_map_t * map)125 void rl_map_destroy( const rl_map_t* map )
126 {
127   destroy( map );
128 }
129 
rl_map_blit0_nobg(const rl_map_t * map,int x,int y)130 void rl_map_blit0_nobg( const rl_map_t* map, int x, int y )
131 {
132   int bg_width, bg_height;
133   rl_backgrnd_fb( &bg_width, &bg_height );
134 
135   const rl_tileset_t* tileset = map->tileset;
136 
137   int ts_width  = tileset->width;
138   int ts_height = tileset->height;
139 
140   int dx = -( x % ts_width );
141   int dy = -( y % ts_height );
142 
143   int max_x = dx + bg_width + ts_width;
144   int max_y = dy + bg_height + ts_height;
145 
146   x /= ts_width;
147   y /= ts_height;
148 
149   int pitch = map->width;
150   const uint16_t* restrict ndx = map->layer0->indices + y * pitch + x;
151 
152   for ( y = dy; y < max_y; y += ts_height )
153   {
154     const uint16_t* restrict next = ndx + pitch;
155 
156     for ( x = dx; x < max_x; x += ts_width )
157     {
158       rl_tileset_blit_nobg( tileset, *ndx++, x, y );
159     }
160 
161     ndx = next;
162   }
163 }
164 
rl_map_blitn_nobg(const rl_map_t * map,int index,int x,int y)165 void rl_map_blitn_nobg( const rl_map_t* map, int index, int x, int y )
166 {
167   int bg_width, bg_height;
168   rl_backgrnd_fb( &bg_width, &bg_height );
169 
170   const rl_imageset_t* imageset = map->imageset;
171 
172   int ts_width  = map->tileset->width;
173   int ts_height = map->tileset->height;
174 
175   int dx = -( x % ts_width );
176   int dy = -( y % ts_height );
177 
178   int max_x = dx + bg_width + ts_width;
179   int max_y = dy + bg_height + ts_height;
180 
181   x /= ts_width;
182   y /= ts_height;
183 
184   int pitch = map->width;
185   const uint16_t* restrict ndx = map->layers[ --index ]->indices + y * pitch + x;
186 
187   for ( y = dy; y < max_y; y += ts_height )
188   {
189     const uint16_t* restrict next = ndx + pitch;
190 
191     for ( x = dx; x < max_x; x += ts_width )
192     {
193       index = *ndx++;
194 
195       if ( index )
196       {
197         rl_image_blit_nobg( imageset->images[ index - 1 ], x, y );
198       }
199     }
200 
201     ndx = next;
202   }
203 }
204