Spr2RLE
100 rem $$asmb=win1_uti_spr_Spr2RLE_bin,0,10
102 :
104 rem + ------------------------------------------------------------------------ +
106 rem |< Spr2RLE >|
108 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
110 rem | Compress a simple, single GD2 sprite |
112 rem | |
114 rem | PRINT FEW(<path>Spr2RLE; '<input file name>') |
116 rem | or |
118 rem | |
120 rem | PRINT FEW(<path>Spr2RLE; '/F"<input file name>" [/O<output file name>]') |
122 rem | |
124 rem | If no output file name given result overwrites ram1_sprite_spr |
126 rem | |
128 rem | With either just a pattern or a mask, or both. |
130 rem | Assumes sprite is made in a regular/standard way, without sprite, block, |
132 rem | options or chained sprites. If any part of the sprite is already |
134 rem | compressed it gives up. |
136 rem | |
138 rem | Dependencies: BTST%; tks ENRLE, EVEN, DETAB$ |
140 rem + ------------------------------------------------------------------------ +
142 rem | V0.01, pjw, 2019 Jun 10 |
144 rem | V0.02, pjw, 2024 Sep 02, debugged and much improved |
146 rem + ------------------------------------------------------------------------ +
148 :
150 :
152 EXT_FN 'ENRLE', 'EVEN', 'DETAB$'
154 :
156 quote$ = '"' & "'"
158 spr = GetCmd(CMD$)
160 IF spr < 0: QUIT er
162 :
164 fl = FLEN(#spr): CLOSE#spr
166 spr = ALCHP(fl + fl + 16)
168 tsp = spr + fl: rem New sprite address..
170 LBYTES ifn$, spr: rem ..in top half of buffer
172 :
174 ctr% = PEEK(spr + 3): rem Control byte
176 :
178 rem Weed out stuff we dont handle
180 IF PEEK(spr) <> 2: Tidy -19: rem GD2 only
182 IF BTST%(ctr%, 7) OR BTST%(ctr%, 6): Tidy -8: rem Some data was already compressed
184 IF BTST%(ctr%, 4) OR BTST%(ctr%, 2): Tidy -19: rem Cant handle Options or Sprite Block
186 IF PEEK_L(spr + 20): Tidy -14: rem No chained sprites
188 :
190 hdsz = 24: rem Header size of simple sprite
192 md% = PEEK(spr + 1): rem Colour mode
194 SELect ON md%
196 = 16: rlesz = 1
198 = 32, 33: rlesz = 2: rem Work out blob's RLE element size
200 = 64: rlesz = 4
202 = REMAINDER : Tidy -19: rem We only handle these sprites
204 END SELect
206 sx = PEEK_W(spr + 4): rem X size
208 sy = PEEK_W(spr + 6): rem Y-size
210 :
212 rem Get pattern (if any)
214 IF PEEK_L(spr + 12) THEN
216 patadr = spr + PEEK_L(spr + 12) + 12: rem Abs addr of pattern data
218 ELSE
220 patadr = 0
222 END IF
224 :
226 rem Get mask (if any)
228 IF PEEK_L(spr + 16) THEN
230 mskadr = spr + PEEK_L(spr + 16) + 16: rem Abs addr of mask data
232 alpha = ctr% && 32: rem alpha <> 0 if alpha
234 ELSE
236 mskadr = 0: alpha = 0
238 END IF
240 :
242 rem Calculate data size
244 patsz = 4 * INT((sx * rlesz + 3) / 4) * sy: rem Data size, rounded to nearest long
246 patsz = EVEN(patsz): rem Round up to even
248 IF NOT alpha THEN
250 msksz = patsz: rem Mask size same as pattern..
252 ELSE
254 msksz = EVEN(sx * sy): rem ..unless alpha
256 END IF
258 npsz = 0: rem New pattern size
260 nmsz = 0: rem New mask size
262 :
264 rem Do it!
266 rlex = 0: rem Extra room for RLE header(s)
268 IF patadr THEN
270 npsz = ENRLE(patadr, tsp + hdsz + 8, patsz, rlesz): rem New pattern size
272 IF npsz < 0: Tidy npsz: rem Doesnt compress
274 :
276 POKE$ tsp + hdsz, 'RLE' & rlesz: rem Set RLE header
278 POKE_L tsp + hdsz + 4, patsz
280 ctr% = ctr% || 64: rem Flag pattern compressed
282 rlex = 8: rem This much added to data
284 END IF
286 :
288 nxadr = tsp + hdsz + npsz + rlex: rem Next address
290 IF mskadr THEN
292 IF alpha THEN
294 nmsz = ENRLE(mskadr, nxadr + 8, msksz, 1)
296 ELSE
298 nmsz = ENRLE(mskadr, nxadr + 8, msksz, rlesz)
300 END IF
302 IF nmsz < 0: Tidy nmsz: rem Doesnt compress
304 :
306 IF alpha THEN : rem Set RLE header
308 POKE$ nxadr, 'RLE1'
310 ELSE
312 POKE$ nxadr, 'RLE' & rlesz
314 END IF
316 POKE_L nxadr + 4, msksz
318 ctr% = ctr% || 128: rem Flag mask compressed
320 rlex = rlex + 8: rem Add room for header
322 END IF
324 :
326 rem Save sprite
328 POKE$ tsp, PEEK$(spr, hdsz)
330 POKE tsp + 3, ctr%: rem Blob and/or Pattern compressed
332 IF patadr THEN
334 POKE_L tsp + 12, 12: rem Offset to pattern..
336 ELSE
338 POKE_L tsp + 12, 0: rem ..unless none
340 END IF
342 IF mskadr THEN
344 IF npsz THEN
346 POKE_L tsp + 16, npsz + 16: rem Offset to mask..
348 ELSE
350 POKE_L tsp + 16, 8: rem ..but no pattern => blob
352 END IF
354 ELSE
356 POKE_L tsp + 16, 0: rem No mask
358 END IF
360 :
362 SBYTES_O ofn$, tsp, hdsz + npsz + nmsz + rlex
364 BEEP 2000, 2: Tidy 0: rem All ok!
366 :
368 :
370 rem + ************************************************************************ +
372 rem *< General Utils >*
374 rem + ************************************************************************ +
376 :
378 :
380 DEFine FuNction BTST%(flg%, btn%)
382 RETurn (2 ^ btn% && flg%) <> 0
384 END DEFine BTST%
386 :
388 :
390 DEFine PROCedure Tidy(er)
392 RECHP spr
394 IF er <> 0: BEEP 2000, 200: rem Error: Burp
396 QUIT er
398 END DEFine Tidy
400 :
402 :
404 rem + ------------------------------------------------------------------------ +
406 rem |< Command Line >|
408 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
410 rem | Parses command line and sets defaults |
412 rem | |
414 rem | /F - Input file name |
416 rem | /O - Output file name (optional) |
418 rem | |
420 rem | Dependencies: DETAB$ |
422 rem | GLOBal quote$ |
424 rem + ------------------------------------------------------------------------ +
426 rem | V0.01, pjw, 2019 Jul 01, base version |
428 rem | V0.01, pjw, 2024 Sep 02, Spr2RLE version
430 rem + ------------------------------------------------------------------------ +
432 :
434 DEFine FuNction GetCmd(cl$)
436 LOCal p%, t$(50)
438 :
440 IF cl$ = '': RETurn -15
442 :
444 rem Get input file name
446 ifn$ = Getent$("F")
448 IF ifn$ = '' THEN
450 ifn$ = cl$
452 ofn$ = 'ram1_sprite_spr'
454 ELSE
456 ofn$ = Getent$('O')
458 IF ofn$ = '': ofn$ = 'ram1_sprite_spr'
460 END IF
462 :
464 RETurn FOP_IN(ifn$)
466 END DEFine GetCmd
468 :
470 DEFine FuNction Getent$(c$)
472 rem Caller's cl$, p%, t$
474 rem Given the character get the entry
476 rem /C [<spaces>] ["|'] <entry> ["|'] <space> | <space> /C+1 | <eol>
478 :
480 p% = '/' & c$ INSTR cl$
482 IF p% = 0: RETurn ''
484 t$ = DETAB$(cl$(p% + 2 TO LEN(cl$)))
486 p% = ' /' INSTR t$
488 IF p% > 0: t$ = t$(1 TO p%): ELSE : p% = LEN(t$)
490 FOR p% = LEN(t$) TO 1 STEP -1
492 IF NOT t$(p%) INSTR ' /': EXIT p%
494 END FOR p%
496 :
498 t$ = t$(1 TO p%)
500 IF LEN(t$) > 1 THEN
502 p% = t$(1) INSTR quote$
504 IF p% THEN
506 IF (t$(LEN(t$)) INSTR quote$) = p% THEN
508 t$ = t$(2 TO LEN(t$) - 1)
510 END IF : END IF : END IF
512 RETurn t$
514 END DEFine Getent$
516 :
518 :
Generated with sb2htm on 2024 Sep 02
©pjwitte 2oo1 - 2o22
QL Software
