ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
put_image.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
53/* <usermanual>
54@keyword PUT IMAGE
55
56@english
57This function draws an image at a specific position on the screen.
58The programmer can draw on the screen a single image (''IMAGE''), a
59frame of a series of images (''IMAGES'') or a frame of a pose of a
60sequence of images (''SEQUENCES''). In all cases the syntax changes
61slightly.
62
63@italian
64Questa funzione disegna una immagine in una specifica posizione dello schermo.
65Il programmatore può disegnare sullo schermo una singola immagine
66(''IMAGE''), un frame di una serie di immagini (''IMAGES'') oppure
67un frame di una posa di una sequenza di immagini (''SEQUENCES'').
68In tutti i casi la sintassi cambia leggermente.
69
70@syntax PUT IMAGE resource AT [x],[y]
71@syntax PUT IMAGE resource FRAME frame AT [x],[y]
72@syntax PUT IMAGE resource STRIP sequence FRAME frame AT [x],[y]
73
74@example PUT IMAGE airplane AT 10,10
75
76@usedInExample contrib_themill.bas
77@usedInExample defines_screen_01.bas
78@usedInExample images_load_05.bas
79
80@target all
81</usermanual> */
82void put_image_vars_original( Environment * _environment, char * _image, char * _x1, char * _y1, char * _x2, char * _y2, char * _frame, char * _sequence, char * _flags ) {
83
84 if ( _environment->emptyProcedure ) {
85 return;
86 }
87
89
90 Variable * image = variable_retrieve( _environment, _image );
91
92 image->usedImage = 1;
93
94 Resource * resource = build_resource_for_sequence( _environment, _image, _frame, _sequence );
95
96 Variable * x1 = variable_retrieve_or_define( _environment, _x1, VT_POSITION, 0 );
97 Variable * y1 = variable_retrieve_or_define( _environment, _y1, VT_POSITION, 0 );
98 Variable * realFrame = NULL;
99 Variable * frame = NULL;
100 if ( _frame) {
101 frame = variable_retrieve_or_define( _environment, _frame, VT_BYTE, 0 );
102 realFrame = frame;
103 }
104 Variable * sequence = NULL;
105 if ( _sequence) {
106 sequence = variable_retrieve_or_define( _environment, _sequence, VT_BYTE, 0 );
107 realFrame = frame;
108 }
109
110 switch( resource->type ) {
111 case VT_SEQUENCE:
112 if ( image->bankAssigned != -1 ) {
113
114 Variable * frameSize = variable_temporary( _environment, VT_WORD, "(temporary)");
115 variable_store( _environment, frameSize->name, image->frameSize );
116 Variable * offset = variable_temporary( _environment, VT_ADDRESS, "(temporary)");
117
118 if ( !sequence ) {
119 if ( !frame ) {
120 vic2_calculate_sequence_frame_offset(_environment, offset->realName, "", "", image->frameSize, image->frameCount );
121 } else {
122 vic2_calculate_sequence_frame_offset(_environment, offset->realName, "", frame->realName, image->frameSize, image->frameCount );
123 }
124 } else {
125 if ( !frame ) {
126 vic2_calculate_sequence_frame_offset(_environment, offset->realName, sequence->realName, "", image->frameSize, image->frameCount );
127 } else {
128 vic2_calculate_sequence_frame_offset(_environment, offset->realName, sequence->realName, frame->realName, image->frameSize, image->frameCount );
129 }
130 }
131
132 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(temporary)");
133 variable_store( _environment, address->name, image->absoluteAddress );
134 variable_add_inplace_vars( _environment, address->name, offset->name );
135
136 Resource resource;
137 resource.realName = strdup( address->realName );
138 resource.bankNumber = image->bankAssigned;
139 resource.isAddress = 1;
140
141 vic2_put_image( _environment, &resource, x1->name, y1->name, NULL, NULL, image->frameSize, 0, _flags );
142
143 } else {
144 if ( !sequence ) {
145 if ( !frame ) {
146 vic2_put_image( _environment, resource, x1->name, y1->name, "", "", image->frameSize, image->frameCount, _flags );
147 } else {
148 vic2_put_image( _environment, resource, x1->name, y1->name, frame->realName, "", image->frameSize, image->frameCount, _flags );
149 }
150 } else {
151 if ( !frame ) {
152 vic2_put_image( _environment, resource, x1->name, y1->name, "", sequence->realName, image->frameSize, image->frameCount, _flags );
153 } else {
154 vic2_put_image( _environment, resource, x1->name, y1->name, frame->realName, sequence->realName, image->frameSize, image->frameCount, _flags );
155 }
156 }
157 }
158 break;
159 case VT_IMAGES:
160 if ( image->bankAssigned != -1 ) {
161
162 Variable * frameSize = variable_temporary( _environment, VT_WORD, "(temporary)");
163 variable_store( _environment, frameSize->name, image->frameSize );
164 Variable * offset = variable_temporary( _environment, VT_ADDRESS, "(temporary)");
165
166 if ( sequence ) {
167 if ( image->strips ) {
168 realFrame = variable_temporary( _environment, VT_BYTE, "(real frame)" );
169 outline1("LDA %s", sequence->realName);
170 outline0("ASL");
171 outline0("TAY");
172 outline1("LDA #<%sstrip", image->realName);
173 outline0("STA TMPPTR");
174 outline1("LDA #>%sstrip", image->realName);
175 outline0("STA TMPPTR+1");
176 outline0("LDA (TMPPTR),Y" );
177 outline0("STA TMPPTR2");
178 outline0("INY" );
179 outline0("LDA (TMPPTR),Y" );
180 outline0("STA TMPPTR2+1");
181 outline1("LDA %s", frame->realName );
182 outline0("TAY" );
183 outline0("LDA (TMPPTR2),Y" );
184 outline1("STA %s", realFrame->realName );
185 } else {
187 }
188 }
189
190 if ( !frame ) {
191 vic2_calculate_sequence_frame_offset(_environment, offset->realName, NULL, "", image->frameSize, 0 );
192 } else {
193 vic2_calculate_sequence_frame_offset(_environment, offset->realName, NULL, realFrame->realName, image->frameSize, 0 );
194 }
195
196 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(temporary)");
197 variable_store( _environment, address->name, image->absoluteAddress );
198 variable_add_inplace_vars( _environment, address->name, offset->name );
199
200 Resource resource;
201 resource.realName = strdup( address->realName );
202 resource.bankNumber = image->bankAssigned;
203 resource.isAddress = 1;
204
205 vic2_put_image( _environment, &resource, x1->name, y1->name, NULL, NULL, image->frameSize, 0, _flags );
206
207 } else {
208
209 if ( sequence ) {
210 if ( image->strips ) {
211 realFrame = variable_temporary( _environment, VT_BYTE, "(real frame)" );
212 outline1("LDA %s", sequence->realName);
213 outline0("ASL");
214 outline0("TAY");
215 outline1("LDA #<%sstrip", image->realName);
216 outline0("STA TMPPTR");
217 outline1("LDA #>%sstrip", image->realName);
218 outline0("STA TMPPTR+1");
219 outline0("LDA (TMPPTR),Y" );
220 outline0("STA TMPPTR2");
221 outline0("INY" );
222 outline0("LDA (TMPPTR),Y" );
223 outline0("STA TMPPTR2+1");
224 outline1("LDA %s", frame->realName );
225 outline0("TAY" );
226 outline0("LDA (TMPPTR2),Y" );
227 outline1("STA %s", realFrame->realName );
228 } else {
230 }
231 }
232
233 if ( !frame ) {
234 vic2_put_image( _environment, resource, x1->name, y1->name, "", NULL, image->frameSize, 0, _flags );
235 } else {
236 vic2_put_image( _environment, resource, x1->name, y1->name, realFrame->realName, NULL, image->frameSize, 0, _flags );
237 }
238 }
239 break;
240 case VT_IMAGE:
241 case VT_TARRAY:
242 if ( image->bankAssigned != -1 ) {
243
244 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(temporary)");
245 variable_store( _environment, address->name, image->absoluteAddress );
246
247 Resource resource;
248 resource.realName = strdup( address->realName );
249 resource.bankNumber = image->bankAssigned;
250 resource.isAddress = 1;
251
252 vic2_put_image( _environment, &resource, x1->name, y1->name, NULL, NULL, 1, 0, _flags );
253 } else {
254 vic2_put_image( _environment, resource, x1->name, y1->name, NULL, NULL, 1, 0, _flags );
255 }
256 break;
257 default:
259 }
260
261
262}
263
264void put_image_vars_imageref( Environment * _environment, char * _image, char * _x1, char * _y1, char * _x2, char * _y2, char * _frame, char * _sequence, char * _flags ) {
265
267
268 char labelNoBank[MAX_TEMPORARY_STORAGE]; sprintf( labelNoBank, "%snobank", label );
269 char labelNoBankLong[MAX_TEMPORARY_STORAGE]; sprintf( labelNoBankLong, "%snobanklong", label );
270 char labelDone[MAX_TEMPORARY_STORAGE]; sprintf( labelDone, "%sdone", label );
271
272 Variable * image = variable_retrieve( _environment, _image );
273
274 Variable * x1 = variable_retrieve_or_define( _environment, _x1, VT_POSITION, 0 );
275 Variable * y1 = variable_retrieve_or_define( _environment, _y1, VT_POSITION, 0 );
276 Variable * frame = NULL;
277 if ( _frame) {
278 frame = variable_retrieve_or_define( _environment, _frame, VT_BYTE, 0 );
279 }
280 Variable * sequence = NULL;
281 if ( _sequence) {
282 sequence = variable_retrieve_or_define( _environment, _sequence, VT_BYTE, 0 );
283 }
284
285 Variable * address = variable_temporary( _environment, VT_ADDRESS, "(stub)" );
286
287 if ( !_environment->putImageRefUnsafe ) {
288 outline1("LDA %s", address_displacement( _environment, image->realName, "5") );
289 outline1("BNE %sskipx", label );
290 outline1("JMP %sskip", label );
291 outhead1("%sskipx:", label );
292 }
293
294 // Y = OFFSET
295
296 outline0("LDA #0" );
297 outline0("STA TMPPTR" );
298 outline0("STA TMPPTR+1" );
299
300 if ( _sequence ) {
301
302 outline0("CLC" );
303 outline0("LDA TMPPTR" );
304 outline0("ADC #3" );
305 outline0("STA TMPPTR" );
306 outline0("LDA TMPPTR+1" );
307 outline0("ADC #0" );
308 outline0("STA TMPPTR+1" );
309
310 if ( strlen(_sequence) == 0 ) {
311
312 } else {
313 outline1("LDA %s", sequence->realName );
314 outline0("STA MATHPTR0" );
315 cpu_call_indirect( _environment, address_displacement( _environment, image->realName, "10") );
316 }
317 if ( _frame ) {
318 if ( strlen(_frame) == 0 ) {
319
320 } else {
321 outline1("LDA %s", frame->realName );
322 outline0("STA MATHPTR0" );
323 cpu_call_indirect( _environment, address_displacement( _environment, image->realName, "8") );
324 }
325 }
326
327 } else {
328
329 if ( _frame ) {
330
331 outline0("CLC" );
332 outline0("LDA TMPPTR" );
333 outline0("ADC #3" );
334 outline0("STA TMPPTR" );
335 outline0("LDA TMPPTR+1" );
336 outline0("ADC #0" );
337 outline0("STA TMPPTR+1" );
338 if ( strlen(_frame) == 0 ) {
339
340 } else {
341 outline1("LDA %s", frame->realName );
342 outline0("STA MATHPTR0" );
343 cpu_call_indirect( _environment, address_displacement( _environment, image->realName, "8") );
344 }
345
346 outline0("LDA TMPPTR" );
347 outline1("STA %s", address->realName );
348 outline0("LDA TMPPTR+1" );
349 outline1("STA %s", address_displacement(_environment, address->realName, "1") );
350
351 } else {
352
353 outline1("LDA %s", image->realName );
354 outline1("STA %s", address->realName );
355 outline1("LDA %s", address_displacement( _environment, image->realName, "1") );
356 outline1("STA %s", address_displacement(_environment, address->realName, "1") );
357
358 }
359
360 }
361
362 // Bank assigned?
363 outline1( "LDA %s", address_displacement( _environment, image->realName, "5" ) );
364 outline0( "AND #$04" );
365 outline1( "BNE %s", labelNoBank );
366 outline1( "JMP %s", labelNoBankLong );
367
368 cpu_label( _environment, labelNoBank );
369 outline1( "LDA %s", address_displacement( _environment, image->realName, "4" ) );
370 outline0( "STA BANKPTR" );
371 outline0( "LDA #$FF" );
372 outline0( "STA BANKUSE" );
373 outline0( "CLC" );
374 outline0( "LDA TMPPTR" );
375 outline1( "ADC %s", address_displacement( _environment, image->realName, "0" ) );
376 outline0( "STA TMPPTR" );
377 outline0( "LDA TMPPTR+1" );
378 outline1( "ADC %s", address_displacement( _environment, image->realName, "1" ) );
379 outline0( "STA TMPPTR+1" );
380
381 Resource resource;
382 resource.realName = strdup( address->realName );
383 resource.bankNumber = image->bankAssigned;
384 resource.isAddress = 1;
385
386 vic2_put_image( _environment, &resource, x1->name, y1->name, NULL, NULL, 0, 0, _flags );
387
388 cpu_jump( _environment, labelDone );
389
390 cpu_label( _environment, labelNoBankLong );
391
392 resource.realName = strdup( address->realName );
393 resource.isAddress = 1;
394
395 vic2_put_image( _environment, &resource, x1->name, y1->name, NULL, NULL, 1, 0, _flags );
396
397 cpu_label( _environment, labelDone );
398
399 if ( !_environment->putImageRefUnsafe ) {
400 outhead1("%sskip:", label );
401 }
402
403}
404
405void put_image_vars( Environment * _environment, char * _image, char * _x1, char * _y1, char * _x2, char * _y2, char * _frame, char * _sequence, char * _flags ) {
406
407 if ( _environment->emptyProcedure ) {
408 return;
409 }
410
411 Variable * image = variable_retrieve( _environment, _image );
412
413 switch( image->type ) {
414 case VT_IMAGE:
415 case VT_IMAGES:
416 case VT_SEQUENCE:
417 case VT_ADDRESS:
418 put_image_vars_original( _environment, _image, _x1, _y1, _x2, _y2, _frame, _sequence, _flags );
419 break;
420 case VT_IMAGEREF:
421 put_image_vars_imageref( _environment, _image, _x1, _y1, _x2, _y2, _frame, _sequence, _flags );
422 break;
423 default:
425 }
426
427}
428
429void put_image_vars_flags( Environment * _environment, char * _image, char * _x1, char * _y1, char * _x2, char * _y2, char * _frame, char * _sequence, int _flags ) {
430
431 char flagsConstantName[MAX_TEMPORARY_STORAGE]; sprintf( flagsConstantName, "PUTIMAGEFLAGS%4.4x", _flags );
432 char flagsConstantParameter[MAX_TEMPORARY_STORAGE]; sprintf( flagsConstantParameter, "#PUTIMAGEFLAGS%4.4x", _flags );
433
434 Constant * flagsConstant = constant_find( _environment, flagsConstantName );
435
436 if ( !flagsConstant ) {
437 flagsConstant = malloc( sizeof( Constant ) );
438 memset( flagsConstant, 0, sizeof( Constant ) );
439 flagsConstant->name = strdup( flagsConstantName );
440 flagsConstant->realName = strdup( flagsConstantName );
441 flagsConstant->value = _flags;
442 flagsConstant->type = CT_INTEGER;
443 flagsConstant->next = _environment->constants;
444 _environment->constants = flagsConstant;
445 }
446
447 put_image_vars( _environment, _image, _x1, _y1, _x2, _y2, _frame, _sequence, flagsConstantParameter );
448}
void cpu_label(Environment *_environment, char *_label)
Definition 6309.c:356
void cpu_call_indirect(Environment *_environment, char *_value)
Definition 6309.c:3765
void cpu_jump(Environment *_environment, char *_label)
Definition 6309.c:3739
Variable * variable_retrieve(Environment *_environment, char *_name)
Variable * variable_retrieve_or_define(Environment *_environment, char *_name, VariableType _type, int _value)
Resource * build_resource_for_sequence(Environment *_environment, char *_image, char *_frame, char *_sequence)
void variable_add_inplace_vars(Environment *_environment, char *_source, char *_destination)
Add two variable and return the sum of them on the first.
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.
char * address_displacement(Environment *_environment, char *_address, char *_displacement)
Constant * constant_find(Environment *_environment, char *_name)
int offset
Definition _optimizer.c:681
void put_image_vars_original(Environment *_environment, char *_image, char *_x1, char *_y1, char *_x2, char *_y2, char *_frame, char *_sequence, char *_flags)
Emit ASM code for PUT IMAGE [image] AT [int],[int].
Definition put_image.c:53
void put_image_vars_imageref(Environment *_environment, char *_image, char *_x1, char *_y1, char *_x2, char *_y2, char *_frame, char *_sequence, char *_flags)
Definition put_image.c:289
void put_image_vars_flags(Environment *_environment, char *_image, char *_x1, char *_y1, char *_x2, char *_y2, char *_frame, char *_sequence, int _flags)
Definition put_image.c:430
void put_image_vars(Environment *_environment, char *_image, char *_x1, char *_y1, char *_x2, char *_y2, char *_frame, char *_sequence, char *_flags)
Definition put_image.c:406
char * name
Definition ugbc.h:800
int value
Definition ugbc.h:815
ConstantType type
Definition ugbc.h:805
struct _Constant * next
Definition ugbc.h:832
char * realName
Definition ugbc.h:803
int putImageRefUnsafe
Definition ugbc.h:3271
Constant * constants
Definition ugbc.h:2611
int emptyProcedure
Definition ugbc.h:2932
int bankNumber
Definition ugbc.h:556
int isAddress
Definition ugbc.h:557
VariableType type
Definition ugbc.h:559
char * realName
Definition ugbc.h:555
int bankAssigned
Definition ugbc.h:1172
char * name
Definition ugbc.h:979
VariableType type
Definition ugbc.h:988
char * realName
Definition ugbc.h:982
void * malloc(YYSIZE_T)
struct _Resource Resource
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
@ CT_INTEGER
Definition ugbc.h:788
struct _Variable Variable
Structure of a single variable.
struct _Environment Environment
Structure of compilation environment.
@ VT_TARRAY
Definition ugbc.h:480
@ VT_WORD
Definition ugbc.h:455
@ VT_POSITION
Definition ugbc.h:468
@ VT_BYTE
Definition ugbc.h:450
@ VT_IMAGEREF
Definition ugbc.h:537
@ VT_IMAGES
Definition ugbc.h:495
@ VT_ADDRESS
Definition ugbc.h:465
@ VT_IMAGE
Definition ugbc.h:489
@ VT_SEQUENCE
Definition ugbc.h:513
struct _Constant Constant
Structure of a single constant.
#define CRITICAL_CANNOT_PUT_IMAGE_WITHOUT_STRIP(s)
Definition ugbc.h:3855
#define outline0(s)
Definition ugbc.h:4252
#define CRITICAL_PUT_IMAGE_UNSUPPORTED(v, t)
Definition ugbc.h:3532
#define outline1(s, a)
Definition ugbc.h:4253
#define MAKE_LABEL
Definition ugbc.h:3351
#define outhead1(s, a)
Definition ugbc.h:4247
char DATATYPE_AS_STRING[][16]
void vic2_calculate_sequence_frame_offset(Environment *_environment, char *_offset, char *_sequence, char *_frame, int _frame_size, int _frame_count)
Definition vic2.c:3931
void vic2_put_image(Environment *_environment, Resource *_image, char *_x, char *_y, char *_frame, char *_sequence, int _frame_size, int _frame_count, char *_flags)
Definition vic2.c:3871