ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
put_tilemap_inline.c
Go to the documentation of this file.
1/*****************************************************************************
2 * ugBASIC - an isomorphic BASIC language compiler for retrocomputers *
3 *****************************************************************************
4 * Copyright 2021-2026 Marco Spedaletti (asimov@mclink.it)
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *----------------------------------------------------------------------------
18 * Concesso in licenza secondo i termini della Licenza Apache, versione 2.0
19 * (la "Licenza"); è proibito usare questo file se non in conformità alla
20 * Licenza. Una copia della Licenza è disponibile all'indirizzo:
21 *
22 * http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Se non richiesto dalla legislazione vigente o concordato per iscritto,
25 * il software distribuito nei termini della Licenza è distribuito
26 * "COSÌ COM'È", SENZA GARANZIE O CONDIZIONI DI ALCUN TIPO, esplicite o
27 * implicite. Consultare la Licenza per il testo specifico che regola le
28 * autorizzazioni e le limitazioni previste dalla medesima.
29 ****************************************************************************/
30
31/****************************************************************************
32 * INCLUDE SECTION
33 ****************************************************************************/
34
35#include "../../ugbc.h"
36
37/****************************************************************************
38 * CODE SECTION
39 ****************************************************************************/
40
41extern char DATATYPE_AS_STRING[][16];
42
43void put_tilemap_inline( Environment * _environment, char * _tilemap, int _flags, char * _dx, char * _dy, char * _layer, int _padding_tile ) {
44
46
47 Variable * tilemap = variable_retrieve( _environment, _tilemap );
48 Variable * dx = NULL;
49 Variable * dy = NULL;
50 Variable * layer = NULL;
51
52 if ( _dx ) {
53 dx = variable_retrieve_or_define( _environment, _dx, VT_BYTE, 0 );
54 }
55
56 if ( _dy ) {
57 dy = variable_retrieve_or_define( _environment, _dy, VT_BYTE, 0 );
58 }
59
60 if ( _layer ) {
61 layer = variable_retrieve( _environment, _layer );
62 }
63
64 if ( tilemap->type != VT_TILEMAP ) {
66 }
67
68 Variable * tileset = variable_retrieve( _environment, tilemap->tileset->name );
69
70 int size = tilemap->mapWidth * tilemap->mapHeight;
71 int screenWidthAsTiles = ( _environment->screenWidth / tileset->frameWidth );
72 int screenHeightAsTiles = ( _environment->screenHeight / tileset->frameHeight );
73 int deltaFrameRow = tilemap->mapWidth > screenWidthAsTiles ? ( tilemap->mapWidth - screenWidthAsTiles ) : 0;
74 int deltaFrameScreen = size - ( tilemap->mapWidth * screenHeightAsTiles );
75
76 Variable * index = NULL;
77
78 if ( tilemap->size > 255 ) {
79 index = variable_temporary( _environment, VT_WORD, "(index)" );
80 } else {
81 index = variable_temporary( _environment, VT_BYTE, "(index)" );
82 }
83
84 // Starting index from 0 (zero).
85
86 variable_store( _environment, index->name, 0 );
87
88 // If a starting point has been given, we must increase the
89 // index to match the first tile to draw.
90
91 if ( dx && dy ) {
92 Variable * mapWidth = variable_temporary( _environment, VT_BYTE, "(map width)");
93 variable_store( _environment, mapWidth->name, tilemap->mapWidth );
94 index = variable_add( _environment, index->name, variable_mul( _environment, dy->name, mapWidth->name )->name );
95 index = variable_add( _environment, index->name, dx->name );
96 }
97
98 Variable * y = variable_temporary( _environment, VT_POSITION, "(y)" );
99 Variable * x = variable_temporary( _environment, VT_POSITION, "(x)" );
100 Variable * fx = variable_temporary( _environment, VT_BYTE, "(fx)" );
101 Variable * frame = variable_temporary( _environment, VT_BYTE, "(frame)" );
102 Variable * padding = variable_temporary( _environment, VT_BYTE, "(padding)" );
103 Variable * padding2 = variable_temporary( _environment, VT_BYTE, "(padding2)" );
104 Variable * padFrame = variable_temporary( _environment, VT_BYTE, "(pad frame)" );
105
106 // Set up the padding tile.
107
108 variable_store( _environment, padFrame->name, _padding_tile );
109
110 // For each layer (actually, a normal map has just one layer).
111
112 for( int layerIndex = 0; layerIndex < tilemap->mapLayers; ++layerIndex ) {
113
114 // If a specific layer is selected, we must point to that layer.
115
116 if ( _layer ) {
117 Variable * sizeSize = variable_temporary( _environment, VT_WORD, "(size)");
118 variable_store( _environment, sizeSize->name, size );
119 variable_move( _environment, variable_add( _environment, index->name, variable_mul( _environment, layer->name, sizeSize->name )->name )->name, index->name );
120 }
121
122 // Let's start from the start of the screen.
123
124 variable_store( _environment, y->name, 0 );
125
126 char labelLoopY[MAX_TEMPORARY_STORAGE]; sprintf( labelLoopY, "%sy%4.4x", label, layerIndex );
127 char labelLoopX[MAX_TEMPORARY_STORAGE]; sprintf( labelLoopX, "%sx%4.4x", label, layerIndex );
128 char labelExit[MAX_TEMPORARY_STORAGE]; sprintf( labelExit, "%se%4.4x", label, layerIndex );
129 char labelExitX[MAX_TEMPORARY_STORAGE]; sprintf( labelExitX, "%sex%4.4x", label, layerIndex );
130 char labelExitX2[MAX_TEMPORARY_STORAGE]; sprintf( labelExitX2, "%sexx%4.4x", label, layerIndex );
131 char labelPadding[MAX_TEMPORARY_STORAGE]; sprintf( labelPadding, "%spad%4.4x", label, layerIndex );
132 char labelPadding2[MAX_TEMPORARY_STORAGE]; sprintf( labelPadding2, "%spady%4.4x", label, layerIndex );
133 char labelDonePutImage[MAX_TEMPORARY_STORAGE]; sprintf( labelDonePutImage, "%sdop%4.4x", label, layerIndex );
134 char labelExitFrame[MAX_TEMPORARY_STORAGE]; sprintf( labelExitFrame, "%sfr%4.4x", label, layerIndex );
135 char labelSkipFxCheck[MAX_TEMPORARY_STORAGE]; sprintf( labelSkipFxCheck, "%sskipx%4.4x", label, layerIndex );
136 char labelSkipIndexCheck[MAX_TEMPORARY_STORAGE]; sprintf( labelSkipIndexCheck, "%sskipy%4.4x", label, layerIndex );
137
138 // Disable vertical padding.
139
140 variable_store( _environment, padding2->name, 0 );
141
142 // --------------------------------------------------------------------------
143 // Y loop
144 // --------------------------------------------------------------------------
145
146 cpu_label( _environment, labelLoopY );
147
148 // Let's start from the left from the screen.
149
150 variable_store( _environment, x->name, 0 );
151
152 // Set the count of frames drawed on the horizontal
153 // line to zero (0).
154
155 variable_store( _environment, fx->name, 0 );
156
157 // If a delta position is given, the count of horizontal frames
158 // drawed must be increased by delta position.
159
160 if ( dx ) {
161 variable_move( _environment, dx->name, fx->name );
162 }
163
164 // Disable horizontal padding.
165
166 variable_store( _environment, padding->name, 0 );
167
168 // --------------------------------------------------------------------------
169 // Begin X loop
170 // --------------------------------------------------------------------------
171
172 cpu_label( _environment, labelLoopX );
173
174 // If the horizontal padding is enabled, we must skip to draw the padding tile.
175
176 cpu_compare_and_branch_8bit_const( _environment, padding->realName, 1, labelPadding, 1 );
177
178 // If the vertical padding is enabled, we must skip to draw the padding tile.
179
180 cpu_compare_and_branch_8bit_const( _environment, padding2->realName, 1, labelPadding, 1 );
181
182 // Take the tile from the map and increase the index.
183
184 if ( tilemap->size > 255 ) {
185 cpu_move_8bit_indirect2_16bit( _environment, tilemap->realName, index->realName, frame->realName );
186 cpu_inc_16bit( _environment, index->realName );
187 } else {
188 cpu_move_8bit_indirect2_8bit( _environment, tilemap->realName, index->realName, frame->realName );
189 cpu_inc( _environment, index->realName );
190 }
191
192 // In case the frame read from the map is 0xff, it means that that specific
193 // frame has not to be drawn, so we exit from this frame drawing.
194
195 cpu_compare_and_branch_8bit_const( _environment, frame->realName, 0xff, labelExitFrame, 1 );
196
197 // --- DRAW TILE --
198
199 put_image( _environment, tileset->name, x->name, y->name, NULL, NULL, frame->name, NULL, _flags );
200 cpu_jump( _environment, labelDonePutImage );
201
202 // --- DRAW PADDING TILE --
203
204 cpu_label( _environment, labelPadding );
205 put_image( _environment, tileset->name, x->name, y->name, NULL, NULL, padFrame->name, NULL, _flags );
206
207 // From here and ahead, we drawed the tile so we must calculate the
208 // next conditions and actions to do. We arrive here both if we drawed
209 // a TILE, a PADDING TILE or if we skipped the drawing.
210
211 cpu_label( _environment, labelDonePutImage ); cpu_label( _environment, labelExitFrame );
212
213 // Increase the horizontal frames drawed count.
214
215 cpu_inc( _environment, fx->realName );
216
217 // Increase the next X position to draw to.
218
219 variable_add_inplace( _environment, x->name, tileset->frameWidth );
220
221 // If the horizontal padding is enabled, we must move to the skip fx check,
222 // since the horizontal padding is enabled by reaching the horizontal limit.
223
224 cpu_compare_and_branch_8bit_const( _environment, padding->realName, 1, labelSkipFxCheck, 1 );
225
226 // We must check if the horizontal limit is reached. In this case, we must
227 // enable horizontal padding by moving to the specific routine.
228
229 Variable * check = variable_less_than_const( _environment, fx->name, tilemap->mapWidth, 0 );
230 cpu_compare_and_branch_8bit_const( _environment, check->realName, 0x0, labelExitX, 1 );
231
232 // Both if the horizontal limit has been reached or not, we must check if the
233 // screen limit has been reached. If the screen limit has not been reached,
234 // we must repeat the X loop. Otherwise, we exit from the X loop.
235
236 cpu_label( _environment, labelSkipFxCheck );
237 check = variable_less_than_const( _environment, x->name, ( _environment->screenWidth), 0 );
238 cpu_compare_and_branch_8bit_const( _environment, check->realName, 0xff, labelLoopX, 1 );
239 cpu_jump( _environment, labelExitX2 );
240
241 // --- ENABLE HORIZONTAL PADDING ---
242 cpu_label( _environment, labelExitX );
243 variable_store( _environment, padding->name, 1 );
244 cpu_jump( _environment, labelSkipFxCheck );
245
246 // --------------------------------------------------------------------------
247 // End X loop
248 // --------------------------------------------------------------------------
249
250 cpu_label( _environment, labelExitX2 );
251
252 // Disable horizontal padding.
253
254 variable_store( _environment, padding->name, 0 );
255
256 // If the screen is narrower than the map, we must move ahead the
257 // index by the calculated delta frame row.
258
259 if ( deltaFrameRow > 0 ) {
260 variable_add_inplace( _environment, index->name, deltaFrameRow );
261 }
262
263 // Move to the next row to draw.
264
265 variable_add_inplace( _environment, y->name, tileset->frameHeight );
266
267 // If we reach the limit of ther map size, we enable the vertical padding.
268
269 check = variable_less_than_const( _environment, index->name, tilemap->size, 0 );
270 cpu_compare_and_branch_8bit_const( _environment, check->realName, 0x00, labelPadding2, 1 );
271
272 // Both if the vertical padding is enabled or not, we must check if the
273 // screen vertical limit has been reached. If not, we repeat the Y loop.
274
275 cpu_label( _environment, labelSkipIndexCheck );
276 check = variable_less_than_const( _environment, y->name, (_environment->screenHeight ), 0 );
277 cpu_compare_and_branch_8bit_const( _environment, check->realName, 0xff, labelLoopY, 1 );
278 cpu_jump( _environment, labelExit );
279
280 // --- ENABLE VERTICAL PADDING ---
281 cpu_label( _environment, labelPadding2 );
282 variable_store( _environment, padding2->name, 1 );
283 cpu_jump( _environment, labelSkipIndexCheck );
284
285 // --------------------------------------------------------------------------
286 // End Y loop
287 // --------------------------------------------------------------------------
288
289 cpu_label( _environment, labelExit );
290
291 if ( _layer ) {
292 break;
293 }
294 if ( deltaFrameScreen ) {
295 variable_add_inplace( _environment, index->name, deltaFrameScreen );
296 }
297
298 _flags = _flags | FLAG_TRANSPARENCY;
299
300 }
301
302}
void cpu_inc(Environment *_environment, char *_variable)
Definition 6309.c:4555
void cpu_move_8bit_indirect2_8bit(Environment *_environment, char *_value, char *_offset, char *_source)
Definition 6309.c:5307
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_move_8bit_indirect2_16bit(Environment *_environment, char *_value, char *_offset, char *_source)
Definition 6309.c:5323
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
void cpu_inc_16bit(Environment *_environment, char *_variable)
Definition 6309.c:4565
void cpu_compare_and_branch_8bit_const(Environment *_environment, char *_source, int _destination, char *_label, int _positive)
CPU 6309: emit code to compare two 8 bit values and jump if they are equal/different
Definition 6309.c:876
Variable * variable_add(Environment *_environment, char *_source, char *_destination)
Add two variable and return the sum of them.
Variable * variable_retrieve(Environment *_environment, char *_name)
void variable_add_inplace(Environment *_environment, char *_source, int _destination)
Variable * variable_less_than_const(Environment *_environment, char *_source, int _destination, int _equal)
Variable * variable_retrieve_or_define(Environment *_environment, char *_name, VariableType _type, int _value)
Variable * variable_move(Environment *_environment, char *_source, char *_destination)
Store the value of a variable inside another variable by converting it.
Variable * variable_mul(Environment *_environment, char *_source, char *_destination)
Make a multiplication between two variable and return the product of them.
Variable * variable_temporary(Environment *_environment, VariableType _type, char *_meaning)
Define a temporary variable.
Variable * variable_store(Environment *_environment, char *_destination, unsigned int _value)
Store a direct value to a variable.
int size
Definition _optimizer.c:678
void put_image(Environment *_environment, char *_image, char *_x1, char *_y1, char *_x2, char *_y2, char *_frame, char *_sequence, int _flags)
Emit ASM code for PUT IMAGE [image] AT [int],[int].
Definition put_image.c:53
void put_tilemap_inline(Environment *_environment, char *_tilemap, int _flags, char *_dx, char *_dy, char *_layer, int _padding_tile)
int screenHeight
Definition ugbc.h:2860
int screenWidth
Definition ugbc.h:2855
char * name
Definition ugbc.h:979
int frameWidth
Definition ugbc.h:1162
int frameHeight
Definition ugbc.h:1164
char * realName
Definition ugbc.h:982
#define CRITICAL_CANNOT_PUT_TILEMAP_FOR_NON_TILEMAP(v)
Definition ugbc.h:3642
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
#define FLAG_TRANSPARENCY
Definition ugbc.h:4567
struct _Variable Variable
Structure of a single variable.
struct _Environment Environment
Structure of compilation environment.
@ VT_WORD
Definition ugbc.h:455
@ VT_POSITION
Definition ugbc.h:468
@ VT_TILEMAP
Definition ugbc.h:525
@ VT_BYTE
Definition ugbc.h:450
#define MAKE_LABEL
Definition ugbc.h:3351
char DATATYPE_AS_STRING[][16]