ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
movement.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
47/* <usermanual>
48@keyword MOVEMENT
49
50@english
51
52The ''MOVEMENT'' command allows you to define a movement of an object or a sprite,
53starting from a given ''ATLAS'' and giving a destination, that can be
54relative to the current position or absolute. Once defined, the
55movement, it can then be used at any time.
56
57In order for this to work, you need to indicate a variable prefix that will be
58associated with the trajectorty of the object that will have this movement.
59This can be indicated with the ''USING'' keyword.
60
61If the ''prefix'' is a variable of type ''SPRITE'', ''CSPRITE'' or ''MSPRITE'',
62this movement will be bounded to that object. Otherwise, the following logic
63will be applied.
64
65The relative movement lasts as the number of the frames contained in the
66''ATLAS'' given with the ''WITH'' keyword. The absolute movement, instead,
67depends on the original and destination position.
68
69This statement will generate a series of variables: on relative movements,
70'prefixSteps'' which will be decremented to zero when movement is ended;
71''prefixX'' and ''prefixY'', which will contain the position where
72the object is located actually. If a movement to a position is required,
73the ''prefixTX'' and ''prefixTY'' variables will contain the destination
74position, white ''prefixPath'' will be defined, to take track of the
75movement itself.
76
77@italian
78
79Il comando ''MOVEMENT'' consente di definire uno spostamento di un oggetto,
80partendo da un dato ''ATLAS'' e dando una destinazione, che può essere
81relativa alla posizione corrente o assoluta. Una volta definito, lo spostamento,
82può essere utilizzato in qualsiasi momento.
83
84Affinché ciò funzioni, è necessario indicare un prefisso di variabile che sarà
85associato alla traiettoria dell'oggetto che avrà questo spostamento. Questo può
86essere indicato con la parola chiave ''USING''.
87
88Se il ''prefix'' è una variabile di tipo ''SPRITE'', ''CSPRITE'' o ''MSPRITE'',
89questo movimento sarà vincolato a quell'oggetto. In caso contrario, verrà
90applicata la seguente logica.
91
92Lo spostamento relativo dura come il numero di frame contenuti nell''ATLAS'' dato
93con la parola chiave ''WITH''. Lo spostamento assoluto, invece, dipende dalla
94posizione di origine e di destinazione.
95
96Questa istruzione genererà una serie di variabili: sugli spostamenti relativi,
97''prefixSteps'' che verrà decrementato a zero quando lo spostamento sarà terminato;
98''prefixX'' e ''prefixY'', che conterranno la posizione in cui si trova effettivamente
99l'oggetto. Se è richiesto uno spostamento verso una posizione, le variabili
100''prefixTX'' e ''prefixTY'' conterranno la posizione di destinazione, mentre
101verrà definito ''prefixPath'' per tenere traccia dello spostamento stesso.
102
103@syntax [DEFINE] MOVEMENT id [rel] WITH atlas [DELAY delay] USING prefix
104@syntax rel: LEFT|RIGHT|UP|DOWN
105@syntax MOVEMENT id TO POSITION [DELAY delay] USING prefix
106@syntax MOVEMENT id STEADY USING prefix
107
108@example MOVEMENT left TLEFT WITH playerForward USING player
109
110</usermanual> */
111
112/* <usermanual>
113@keyword DEFINE MOVEMENT
114
115@english
116
117@italian
118
119@alias MOVEMENT
120
121</usermanual> */
122
123void movement( Environment * _environment, char * _identifier, char * _atlas, char * _prefix ) {
124
125#if defined(__gb__)
126 return;
127#endif
128
129 if ( _environment->procedureName ) {
131 }
132
133 Variable * atlas = NULL;
134
135 atlas = variable_retrieve( _environment, _atlas );
136
137 Variable * prefix = NULL;
138
139 int spriteLogic = 0;
140
141 if ( variable_exists( _environment, _prefix ) ) {
142 prefix = variable_retrieve( _environment, _prefix );
143 if ( prefix->type == VT_SPRITE || prefix->type == VT_MSPRITE ) {
144 spriteLogic = 1;
145 }
146 }
147
148 // DIM [prefix]Movement AS THREAD
149 char prefixMovement[MAX_TEMPORARY_STORAGE]; sprintf( prefixMovement, "%sMovement", _prefix );
150 Variable * prefixMovementVar = variable_define( _environment, prefixMovement, VT_THREAD, 0xff );
151
152 // DIM [prefix]X AS POSITION
153 char prefixX[MAX_TEMPORARY_STORAGE]; sprintf( prefixX, "%sX", _prefix );
154 Variable * prefixXVar = variable_define( _environment, prefixX, VT_POSITION, 0 );
155
156 // DIM [prefix]Y AS POSITION
157 char prefixY[MAX_TEMPORARY_STORAGE]; sprintf( prefixY, "%sY", _prefix );
158 Variable * prefixYVar = variable_define( _environment, prefixY, VT_POSITION, 0 );
159
160 // DIM [prefix]TX AS POSITION
161 char prefixTX[MAX_TEMPORARY_STORAGE]; sprintf( prefixTX, "%sTX", _prefix );
162 Variable * prefixTXVar;
163
164 // DIM [prefix]TY AS POSITION
165 char prefixTY[MAX_TEMPORARY_STORAGE]; sprintf( prefixTY, "%sTY", _prefix );
166 Variable * prefixTYVar;
167
168 // DIM [prefix]Sync AS BYTE
169 char prefixSync[MAX_TEMPORARY_STORAGE]; sprintf( prefixSync, "%sSync", _prefix );
170 Variable * prefixSyncVar = variable_define( _environment, prefixSync, VT_BYTE, 0 );;
171
172 // DIM [prefix]Next AS BYTE
173 char prefixNext[MAX_TEMPORARY_STORAGE]; sprintf( prefixNext, "%sNext", _prefix );
174 Variable * prefixNextVar = variable_define( _environment, prefixNext, VT_BYTE, 0 );;
175
176 // DIM [prefix]Steps AS BYTE
177 char prefixSteps[MAX_TEMPORARY_STORAGE]; sprintf( prefixSteps, "%sSteps", _prefix );
178 Variable * prefixStepsVar = NULL;
179 // DIM [prefix]Path AS PATH
180 char prefixPath[MAX_TEMPORARY_STORAGE]; sprintf( prefixPath, "%sPath", _prefix );
181 Variable * prefixPathVar = NULL;
182 if ( (_environment->movementDeltaX == 0) && (_environment->movementDeltaY == 0) ) {
183 prefixPathVar = variable_define( _environment, prefixPath, VT_PATH, 0 );
184 prefixTXVar = variable_define( _environment, prefixTX, VT_POSITION, 0 );
185 prefixTYVar = variable_define( _environment, prefixTY, VT_POSITION, 0 );
186 } else {
187 prefixStepsVar = variable_define( _environment, prefixSteps, VT_BYTE, 0 );
188 }
189
190 // PARALLEL PROCEDURE moveLeft
191 ((struct _Environment *)_environment)->parameters = 0;
192 ((struct _Environment *)_environment)->protothread = 1;
193 ((struct _Environment *)_environment)->emptyProcedure = 0;
194 begin_procedure( _environment, _identifier );
195
196 // SHARED [prefix]Movement
197 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixMovement );
198 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_THREAD;
199 ++((struct _Environment *)_environment)->parameters;
200
201 // SHARED [prefix]X
202 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixX );
203 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_POSITION;
204 ++((struct _Environment *)_environment)->parameters;
205
206 // SHARED [prefix]Y
207 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixY );
208 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_POSITION;
209 ++((struct _Environment *)_environment)->parameters;
210
211 // SHARED [prefix]Sync
212 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixSync );
213 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_BYTE;
214 ++((struct _Environment *)_environment)->parameters;
215
216 if ( (_environment->movementDeltaX == 0) && (_environment->movementDeltaY == 0) ) {
217 // SHARED [prefix]TX
218 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixTX );
219 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_POSITION;
220 ++((struct _Environment *)_environment)->parameters;
221
222 // SHARED [prefix]TY
223 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixTY );
224 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_POSITION;
225 ++((struct _Environment *)_environment)->parameters;
226
227 // SHARED [prefix]Path
228 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixPath );
229 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_PATH;
230 ++((struct _Environment *)_environment)->parameters;
231
232 }
233
234 // SHARED [prefix]Steps
235 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixSteps );
236 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_BYTE;
237 ++((struct _Environment *)_environment)->parameters;
238
239 // SHARED [prefix]Next
240 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefixNext );
241 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = VT_BYTE;
242 ++((struct _Environment *)_environment)->parameters;
243
244 // SHARED atlas
245 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( atlas->name );
246 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = atlas->type;
247 ++((struct _Environment *)_environment)->parameters;
248
249 if ( prefix ) {
250 // SHARED prefix
251 ((struct _Environment *)_environment)->parametersEach[((struct _Environment *)_environment)->parameters] = strdup( prefix->name );
252 ((struct _Environment *)_environment)->parametersTypeEach[((struct _Environment *)_environment)->parameters] = prefix->type;
253 ++((struct _Environment *)_environment)->parameters;
254 }
255
256 shared( _environment );
257
259
260 if ( (_environment->movementDeltaX == 2) && (_environment->movementDeltaY == 2) ) {
261
262 } else {
263
264 if ( (_environment->movementDeltaX == 0) && (_environment->movementDeltaY == 0) ) {
265 // t = CREATE PATH OP optional_x OP_COMMA optional_y TO expr OP_COMMA expr CP
266 variable_move( _environment, create_path( _environment, prefixXVar->name, prefixYVar->name, prefixTXVar->name, prefixTYVar->name )->name, prefixPathVar->name );
267 } else {
268 // [prefix]Steps = FRAMES( [atlas] )
269 if ( atlas->type == VT_IMAGES ) {
270 variable_store( _environment, prefixStepsVar->name, atlas->frameCount );
271 } else if ( VT_BITWIDTH( atlas->type ) > 1 ) {
272 if ( atlas->initializedByConstant ) {
273 variable_store( _environment, prefixStepsVar->name, atlas->value );
274 } else {
275 variable_move( _environment, atlas->name, prefixStepsVar->name );
276 }
277 } else {
279 }
280 }
281
282 char loopLabel[MAX_TEMPORARY_STORAGE]; sprintf( loopLabel, "%sloop", label );
283 char loopDoneLabel[MAX_TEMPORARY_STORAGE]; sprintf( loopDoneLabel, "%sdone", label );
284
285 cpu_compare_and_branch_8bit_const( _environment, prefixSyncVar->realName, 0x00, loopLabel, 1 );
286
287 char waitSyncLabel[MAX_TEMPORARY_STORAGE]; sprintf( waitSyncLabel, "%swaitsync", label );
288 cpu_label( _environment, waitSyncLabel );
289 cpu_compare_and_branch_8bit_const( _environment, variable_and_const( _environment, prefixNextVar->name, 0x01 )->realName, 0x01, loopLabel, 1 );
290 yield( _environment );
291 cpu_jump( _environment, waitSyncLabel );
292
293 // DO
294 cpu_label( _environment, loopLabel );
295
296 yield( _environment );
297
298 if ( (_environment->movementDeltaX == 0) && (_environment->movementDeltaY == 0) ) {
299 // TRAVEL t TO x, y
300 travel_path( _environment, prefixPathVar->name, prefixXVar->name, prefixYVar->name, NULL, NULL );
301 } else {
302 if ( _environment->movementDeltaX == 1) {
303 // INC prefixXVar
304 variable_increment( _environment, prefixXVar->name );
305 } else if ( _environment->movementDeltaX == -1) {
306 // DEC playerX
307 variable_decrement( _environment, prefixXVar->name );
308 }
309
310 if ( _environment->movementDeltaY == 1) {
311 // INC playerX
312 variable_increment( _environment, prefixYVar->name );
313 } else if ( _environment->movementDeltaY == -1) {
314 // DEC playerX
315 variable_decrement( _environment, prefixYVar->name );
316 }
317 }
318
319 if ( prefix && spriteLogic ) {
320 sprite_at_vars( _environment, prefix->name, prefixXVar->name, prefixYVar->name );
321 }
322 // WAIT 50 MS
323 wait_milliseconds( _environment, _environment->movementDelay );
324
325 if ( (_environment->movementDeltaX == 0) && (_environment->movementDeltaY == 0) ) {
326 // EXIT IF x = x1 AND y = y1
329 _environment,
330 variable_xor( _environment, prefixXVar->name, prefixTXVar->name )->name,
331 variable_xor( _environment, prefixYVar->name, prefixTYVar->name )->name
332 )->realName,
333 0, loopDoneLabel, 1 );
334 } else {
335 // DEC playerSteps
336 variable_decrement( _environment, prefixStepsVar->name );
337
338 // EXIT IF playerSteps = 0
339 cpu_compare_and_branch_8bit_const( _environment, prefixStepsVar->realName, 0, loopDoneLabel, 1 );
340
341 }
342
343 // LOOP
344 cpu_jump( _environment, loopLabel );
345
346 cpu_label( _environment, loopDoneLabel );
347
348 char reallyDoneLabel[MAX_TEMPORARY_STORAGE]; sprintf( reallyDoneLabel, "%sreallydone", label );
349
350 cpu_compare_and_branch_8bit_const( _environment, prefixSyncVar->realName, 0x00, reallyDoneLabel, 1 );
351
352 cpu_or_8bit_const( _environment, prefixNextVar->realName, 0x80, prefixNextVar->realName );
353
354 yield( _environment );
355
356 char waitSyncLabel2[MAX_TEMPORARY_STORAGE]; sprintf( waitSyncLabel2, "%swaitsync2", label );
357 cpu_label( _environment, waitSyncLabel2 );
358 cpu_compare_and_branch_8bit_const( _environment, variable_and_const( _environment, prefixNextVar->name, 0x04 )->realName, 0x04, reallyDoneLabel, 1 );
359 yield( _environment );
360 cpu_jump( _environment, waitSyncLabel2 );
361
362 cpu_label( _environment, reallyDoneLabel );
363
364 }
365
366 variable_store( _environment, prefixSyncVar->name, 0x00 );
367
368 // END PROC
369 end_procedure( _environment, NULL );
370
371}
372
void cpu_compare_and_branch_16bit_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:1578
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_or_8bit_const(Environment *_environment, char *_left, int _right, char *_result)
Definition 6309.c:4306
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
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_retrieve(Environment *_environment, char *_name)
void variable_decrement(Environment *_environment, char *_source)
Decrement a variable by one.
int variable_exists(Environment *_environment, char *_name)
Variable * variable_move(Environment *_environment, char *_source, char *_destination)
Store the value of a variable inside another variable by converting it.
Variable * variable_and_const(Environment *_environment, char *_destination, int _mask)
Calculate "and" mask for a variable and it as the result.
void variable_increment(Environment *_environment, char *_source)
Increment a variable by one.
Variable * variable_xor(Environment *_environment, char *_left, char *_right)
Calculate logical "xor" and return it as the result.
Variable * variable_define(Environment *_environment, char *_name, VariableType _type, int _value)
Define a variable for the program.
Variable * variable_store(Environment *_environment, char *_destination, unsigned int _value)
Store a direct value to a variable.
Variable * variable_or(Environment *_environment, char *_left, char *_right)
Calculate logical "or" and return it as the result.
void begin_procedure(Environment *_environment, char *_name)
Emit code for PROCEDURE ... END PROC.
void sprite_at_vars(Environment *_environment, char *_sprite, char *_x, char *_y)
Emit ASM code for SPRITE [expression] AT ([expression],[expression]).
Definition sprite_at.c:71
Variable * create_path(Environment *_environment, char *_x0, char *_y0, char *_x1, char *_y1)
Emit ASM code to implement CREATE PATH command.
Definition create_path.c:90
void end_procedure(Environment *_environment, char *_value)
Emit code for END PROC.
Definition end_proc.c:72
void movement(Environment *_environment, char *_identifier, char *_atlas, char *_prefix)
Emit code for MOVEMENT ....
Definition movement.c:123
void shared(Environment *_environment)
Manage variable as "global".
Definition shared.c:88
Structure of compilation environment.
Definition ugbc.h:2269
char * parametersEach[MAX_PARAMETERS]
Definition ugbc.h:2790
int protothread
Definition ugbc.h:2830
int movementDeltaY
Definition ugbc.h:3215
int movementDeltaX
Definition ugbc.h:3214
VariableType parametersTypeEach[MAX_PARAMETERS]
Definition ugbc.h:2800
int parameters
Definition ugbc.h:2785
int movementDelay
Definition ugbc.h:3213
char * procedureName
Definition ugbc.h:2775
int emptyProcedure
Definition ugbc.h:2932
char * name
Definition ugbc.h:979
VariableType type
Definition ugbc.h:988
int frameCount
Definition ugbc.h:1137
int value
Definition ugbc.h:1025
int initializedByConstant
Definition ugbc.h:1036
char * realName
Definition ugbc.h:982
Variable * travel_path(Environment *_environment, char *_p, char *_x, char *_y, char *_times, char *_limited)
Emit ASM code to implement TRAVEL PATH command.
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
struct _Variable Variable
Structure of a single variable.
struct _Environment Environment
Structure of compilation environment.
@ VT_THREAD
Definition ugbc.h:492
@ VT_POSITION
Definition ugbc.h:468
@ VT_MSPRITE
Definition ugbc.h:531
@ VT_BYTE
Definition ugbc.h:450
@ VT_SPRITE
Definition ugbc.h:501
@ VT_IMAGES
Definition ugbc.h:495
@ VT_PATH
Definition ugbc.h:540
#define CRITICAL_CANNOT_DEFINE_MOVEMENT_WITHOUT_STEPS(s)
Definition ugbc.h:3795
#define VT_BITWIDTH(t)
Definition ugbc.h:595
#define MAKE_LABEL
Definition ugbc.h:3351
#define CRITICAL_CANNOT_DEFINE_MOVEMENT_INSIDE_A_PROCEDURE(n)
Definition ugbc.h:3778
void wait_milliseconds(Environment *_environment, int _timing)
Emit ASM code for WAIT # [integer] MS.
void yield(Environment *_environment)
Emit code for YIELD.
Definition yield.c:63