ugBASIC 1.18
An isomorphic BASIC language compiler for retrocomputers
Loading...
Searching...
No Matches
tileset_load.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"
37#include "../../libs/msc1.h"
38#include "../../libs/tsx.h"
39
40/****************************************************************************
41 * CODE SECTION
42 ****************************************************************************/
43
51/* <usermanual>
52@keyword LOAD TILESET
53
54@english
55
56The ''LOAD TILESET'' command allows you to load a tileset with the "Tiled TSX"
57file format. Offset and other parameters will be calculated automatically
58on the base of the file content.
59
60The image will be converted into a way that can be efficiently drawn
61on the screen. It could be converted into indexed palette, and can be
62rescaled as well.
63
64Since it is possible to load only one file of the same type at a time, it is necessary
65to be able to indicate an "alias" with which to exceed this limit. In this regard, there is also
66the ''AS'' syntax, which allows you to load the same file several times but with different names.
67
68@italian
69Il comando ''LOAD TILESET'' permette di caricare un tileset con il formato file "Tiled TSX".
70L'offset e altri parametri verranno calcolati automaticamente sulla base del contenuto del file.
71
72L'immagine verrà convertita in un modo che possa essere disegnata in modo efficiente
73sullo schermo. Potrebbe essere convertita in una tavolozza indicizzata, e potrebbe essere
74anche ridimensionata.
75
76Dal momento in cui è possibile caricare un solo file dello stesso tipo alla volta,
77è necessario poter indicare un "alias" con cui superare questo limite. A tal riguardo
78esiste anche la sintassi ''AS'', che permette di caricare più volte lo stesso file
79ma con nomi diversi.
80
81@syntax = LOAD TILESET( filename )
82@syntax = LOAD TILESET( filename AS alias )
83
84@example x = LOAD TILESET("dungeon.tsx")
85@example x = LOAD TILESET("dungeon.tsx" AS "dungeon")
86
87@target all
88</usermanual> */
89Variable * tileset_load( Environment * _environment, char * _filename, char * _alias, int _mode, int _flags, int _transparent_color, int _background_color, int _bank_expansion ) {
90
91 Variable * final = variable_temporary( _environment, VT_IMAGES, 0 );
92
93 if ( _environment->emptyProcedure ) {
94 return final;
95 }
96
97 if ( _environment->tenLinerRulesEnforced ) {
98 CRITICAL_10_LINE_RULES_ENFORCED( "LOAD TILESET");
99 }
100
101 if ( _environment->sandbox ) {
102 CRITICAL_SANDBOX_ENFORCED( "LOAD TILESET");
103 }
104
105 LoadedFile * first = _environment->loadedFiles;
106 char *lookfor = _filename;
107 if ( _alias ) {
108 lookfor = _alias;
109 }
110 while( first ) {
111 if ( strcmp(lookfor, first->fileName ) == 0 ) {
112 return first->variable;
113 }
114 first = first->next;
115 }
116
117 int width = 0;
118 int height = 0;
119 int depth = 0;
120
121 char * lookedFilename = resource_load_asserts( _environment, _filename );
122
123 TsxTileset * tileset = tsx_load( lookedFilename );
124
125 final->originalTileset = tileset;
126
127 if ( !tileset ) {
129 }
130
131 if ( !tileset->image ) {
133 }
134
136 int x=0,y=0,z=0;
137 int bufferSize = 0;
138
139 TsxImage * tsxImage = tileset->image;
140
141 char * filename = strdup( _filename );
142 char * filenameWithPath = malloc( 1024 );
143 memset( filenameWithPath, 0, 1024 );
144 char * separator = strrchr( filename, '/' );
145 if ( separator ) {
146 *(separator+1) = 0;
147 strcopy( filenameWithPath, filename );
148 }
149 strcat( filenameWithPath, tsxImage->source );
150
151 AtlasDescriptor * atlasDescriptor = atlas_descriptor_create( _environment, filenameWithPath, _flags, tileset->margin, tileset->margin, tileset->tilewidth, tileset->tileheight, tileset->spacing, tileset->spacing );
152
153 ImageDescriptor * frame = atlasDescriptor->frames;
154 for( int i=0; i<atlasDescriptor->count; ++i ) {
155 result[i] = image_converter( _environment, frame->data, frame->width, frame->height, frame->depth, 0, 0, tileset->tilewidth, tileset->tileheight, _mode, _transparent_color, _flags );
156 bufferSize += result[i]->size;
157 frame = frame->next;
158 }
159
160 bufferSize += 3;
161
162 adiline1("LIS2:%x", bufferSize );
163
164 char * buffer = malloc( bufferSize );
165 char * ptr = buffer;
166 ptr[0] = atlasDescriptor->count;
167 ptr[1] = ( tileset->tilewidth & 0xff );
168 ptr[2] = ( tileset->tilewidth >> 8 ) & 0xff;
169
170 if ( ( result[0]->size * atlasDescriptor->count ) > 0xffff ) {
172 }
173
174 final->offsettingFrames = offsetting_size_count( _environment, result[0]->size, atlasDescriptor->count );
175 offsetting_add_variable_reference( _environment, final->offsettingFrames, final, 0 );
176
177 ptr += 3;
178 for(int i=0; i<atlasDescriptor->count; ++i ) {
179 memcpy( ptr, result[i]->valueBuffer, result[i]->size );
180 ptr += result[i]->size;
181 }
182 variable_store_buffer( _environment, final->name, buffer, bufferSize, 0 );
183 final->originalBitmap = atlasDescriptor->image->data;
184 final->originalWidth = atlasDescriptor->image->width;
185 final->originalHeight = atlasDescriptor->image->height;
186 final->originalDepth = atlasDescriptor->image->depth;
187 final->originalColors = atlasDescriptor->image->colorsCount;
188 memcpy( final->originalPalette, atlasDescriptor->image->colors, MAX_PALETTE * sizeof( RGBi ) );
189 final->frameWidth = tileset->tilewidth;
190 final->frameHeight = tileset->tileheight;
191 final->firstGid = tileset->firstgid;
192 final->frameSize = result[0]->size;
193 final->frameCount = atlasDescriptor->count;
194
195 for(int i=0; i<atlasDescriptor->count; ++i ) {
196 variable_temporary_remove( _environment, result[i]->name );
197 }
198
199 // stbi_image_free(source);
200
201 if ( _bank_expansion && _environment->expansionBanks ) {
202
203 Bank * bank = _environment->expansionBanks;
204
205 while( bank ) {
206 if ( bank->remains > final->size ) {
207 break;
208 }
209 bank = bank->next;
210 }
211
212 if ( ! bank ) {
214 }
215
216 final->bankAssigned = bank->id;
217 final->absoluteAddress = bank->address;
218 final->residentAssigned = _bank_expansion;
219 final->variableUniqueId = UNIQUE_RESOURCE_ID;
220 memcpy( &bank->data[bank->address], final->valueBuffer, final->size );
221
222 bank->address += final->size;
223 bank->remains -= final->size;
224
225 // Now we must calculate the effective size occupied by
226 // memory block, when it will be uncompressed. It is needed
227 // to have enough memory into the resident part of the
228 // memory. If uncompressed size is zero, it means that
229 // the memory block is not compressed -- so we can use the
230 // size as well.
231 // int realSize = final->uncompressedSize;
232 // if ( realSize == 0 ) realSize = final->size;
233
234 if ( _environment->maxExpansionBankSize[_bank_expansion] < final->frameSize ) {
235 _environment->maxExpansionBankSize[_bank_expansion] = final->frameSize;
236 }
237
238 } else if ( ( _flags & FLAG_COMPRESSED ) && !_environment->compressionForbidden ) {
239
240 // Try to compress the result of image conversion.
241 // This means that the buffer will be compressed using MSC1
242 // algorithm, up to 32 frequent sequences. The original size of
243 // the buffer will be considered as "uncompressed" size.
244 MSC1Compressor * compressor = msc1_create( 32 );
245 final->uncompressedSize = final->size;
246 MemoryBlock * output = msc1_compress( compressor, final->valueBuffer, final->uncompressedSize, &final->size );
247
248 int temporary;
249 MemoryBlock * outputCheck = msc1_uncompress( compressor, output, final->size, &temporary );
250 if ( memcmp( outputCheck, final->valueBuffer, final->uncompressedSize ) != 0 ) {
252 }
253 msc1_free( compressor );
254 // printf( "%s: %d bytes -> %d bytes\n", _filename, final->uncompressedSize, final->size );
255 // If the compressed memory is greater than the original
256 // size, we discard the compression and we will continue as
257 // usual.
258 if ( final->uncompressedSize < final->size ) {
259 final->size = final->uncompressedSize;
260 final->uncompressedSize = 0;
261 free( output );
262 }
263 // Otherwise, we can safely replace the original data
264 // buffer with the compressed one.
265 else {
266 free( final->valueBuffer );
267 final->valueBuffer = output;
268 }
269 final->residentAssigned = 1;
270 _environment->maxExpansionBankSize[1] = BANK_SIZE;
271
272 }
273
274 LoadedFile * loaded = malloc( sizeof( LoadedFile ) );
275 loaded->next = first;
276 loaded->variable = final;
277 loaded->fileName = lookfor;
278 _environment->loadedFiles = loaded;
279
280 if ( _alias ) {
281 const_define_numeric( _environment, _alias, UNIQUE_RESOURCE_ID );
282 }
283
284 final->readonly = 1;
285
286 return final;
287
288}
void const_define_numeric(Environment *_environment, char *_name, int _value)
void variable_temporary_remove(Environment *_environment, char *_name)
char * resource_load_asserts(Environment *_environment, char *_filename)
void offsetting_add_variable_reference(Environment *_environment, Offsetting *_first, Variable *_var, int _sequence)
Variable * variable_temporary(Environment *_environment, VariableType _type, char *_meaning)
Define a temporary variable.
Offsetting * offsetting_size_count(Environment *_environment, int _size, int _count)
Variable * variable_store_buffer(Environment *_environment, char *_destination, unsigned char *_buffer, int _size, int _at)
int size
Definition _optimizer.c:678
char * name
Definition _optimizer.c:672
Variable * image_converter(Environment *_environment, char *_data, int _width, int _height, int _depth, int _offset_x, int _offset_y, int _frame_width, int _frame_height, int _mode, int _transparent_color, int _flags)
#define BANK_SIZE
Definition atari.h:146
AtlasDescriptor * atlas_descriptor_create(Environment *_environment, char *_filename, int _flags, int _image_origin_x, int _image_origin_y, int _frame_width, int _frame_height, int _frame_offset_x, int _frame_offset_y)
MSC1Compressor * msc1_create(int _maximum_repeated_sequences)
Definition msc1.c:300
void msc1_free(MSC1Compressor *_msc1)
Definition msc1.c:740
MemoryBlock * msc1_uncompress(MSC1Compressor *_msc1, MemoryBlock *_input, int _size, int *_output_size)
Definition msc1.c:746
MemoryBlock * msc1_compress(MSC1Compressor *_msc1, MemoryBlock *_input, int _size, int *_output_size)
Definition msc1.c:381
unsigned char MemoryBlock
Definition msc1.h:90
struct _MSC1Compressor MSC1Compressor
struct _ImageDescriptor * frames
Definition ugbc.h:939
struct _ImageDescriptor * image
Definition ugbc.h:925
int remains
Definition ugbc.h:171
int address
Definition ugbc.h:159
int id
Definition ugbc.h:153
struct _Bank * next
Definition ugbc.h:185
char * data
Definition ugbc.h:177
LoadedFile * loadedFiles
Definition ugbc.h:2636
int compressionForbidden
Definition ugbc.h:3169
int maxExpansionBankSize[MAX_RESIDENT_SHAREDS]
Definition ugbc.h:3010
int sandbox
Definition ugbc.h:2990
Bank * expansionBanks
Definition ugbc.h:3005
int tenLinerRulesEnforced
Definition ugbc.h:2985
int emptyProcedure
Definition ugbc.h:2932
int colorsCount
Definition ugbc.h:918
RGBi * colors
Definition ugbc.h:917
char * data
Definition ugbc.h:911
struct _ImageDescriptor * next
Definition ugbc.h:919
char * fileName
Definition ugbc.h:1481
struct _LoadedFile * next
Definition ugbc.h:1486
Variable * variable
Definition ugbc.h:1483
char * source
Definition tsx.h:40
int spacing
Definition tsx.h:68
struct _TsxImage * image
Definition tsx.h:70
int margin
Definition tsx.h:67
int tilewidth
Definition tsx.h:62
int firstgid
Definition tsx.h:66
int tileheight
Definition tsx.h:63
int size
Definition ugbc.h:1077
Variable * tileset_load(Environment *_environment, char *_filename, char *_alias, int _mode, int _flags, int _transparent_color, int _background_color, int _bank_expansion)
Emit code for LOAD TILESERT(...).
TsxTileset * tsx_load(char *_filename)
Definition tsx.c:47
struct _TsxTileset TsxTileset
struct _TsxImage TsxImage
void * malloc(YYSIZE_T)
void free(void *)
#define FLAG_COMPRESSED
Definition ugbc.h:4570
#define CRITICAL_10_LINE_RULES_ENFORCED(v)
Definition ugbc.h:3550
struct _ImageDescriptor ImageDescriptor
struct _RGBi RGBi
Structure to store color components (red, green and blue).
#define MAX_TEMPORARY_STORAGE
Definition ugbc.h:563
#define adiline1(s, a)
Definition ugbc.h:4187
#define UNIQUE_RESOURCE_ID
Definition ugbc.h:3350
#define CRITICAL_TILESET_LOAD_IMAGE_TOO_BIG(v)
Definition ugbc.h:3665
struct _Variable Variable
Structure of a single variable.
struct _Environment Environment
Structure of compilation environment.
@ VT_IMAGES
Definition ugbc.h:495
struct _AtlasDescriptor AtlasDescriptor
#define CRITICAL_TILESET_LOAD_MISSING_IMAGE(v)
Definition ugbc.h:3632
#define MAX_PALETTE
Definition ugbc.h:568
#define CRITICAL_EXPANSION_OUT_OF_MEMORY_LOADING(v)
Definition ugbc.h:3568
#define CRITICAL_SANDBOX_ENFORCED(v)
Definition ugbc.h:3687
struct _LoadedFile LoadedFile
#define CRITICAL_COMPRESSION_FAILED(v)
Definition ugbc.h:3768
#define CRITICAL_TILESET_LOAD_UNKNOWN_FORMAT(v)
Definition ugbc.h:3631
struct _Bank Bank
Structure of a single bank.
char * strcopy(char *_dest, char *_source)