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