Pic2Spr

Routine to convert a PIC of any QL or GD2 mode to a solid, compressed or uncompressed sprite of the same mode.

Note: Systems with GD2 drivers (SMSQ/E) can display sprites of any mode. However, systems with the old drivers, even if using PE2, can only display QL mode sprites. Wman2 may, at least, support compressed sprites.

Without modification this routine will only run under SMSQ/E as it uses SBASIC's PEEK$/POKE$

Requires the RLE toolkit.

Under SMSQ/E simply EX the SBASIC program, supplying the name of the PIC to convert on the command line.

The harness is not very sophisticated, so to alter the behaviour (compress or not, overwrite or not) you need to make a few changes to the program code's line 30 (or write yourself a more versatile harness!)

100 rem $$asmb=win1_uti_spr_cv_Pic2Spr_bin,0,10
102 rem $$stak=4096
104 rem $$chan=3
106 :
108 EXT_FN 'DETAB$', 'ENRLE'
110 :
112 rem + ************************************************************************ +
114 rem *<                                Pic2Spr                                 >*
116 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
118 rem *           Convert PIC to uncompressed or compressed, solid SPR           *
120 rem *                                                                          *
122 rem * Modes 0, 8, 16, 32, 33, 64 supported                                     *
124 rem *                                                                          *
126 rem * Note: Odd-Xed sprites will have a black stripe down the rightmost edge   *
128 rem *                                                                          *
130 rem * Command line parameters:                                                 *
132 rem *   /F - or /I - Input file name                                           *
134 rem *   /O - Output file name (optional)                                       *
136 rem *   /C - RLE Compress: on/off, default on (Only responds to off or 0!)     *
138 rem *   /W - overWrite:    on/off, default on (Only responds to off or 0!)     *
140 rem *                                                                          *
142 rem * If no Output file name given then outputs to input file name with spr    *
144 rem * extension                                                                *
146 rem + ------------------------------------------------------------------------ +
148 rem * V0.01, pjw, 2026 Mar 28                                                  *
150 rem + ************************************************************************ +
152 :
154 :
156 cm$ = CMD$
158 quote$ = '"' & "'"
160 :
162 er = GetCmd(cm$): IF er < 0: QUIT er
164 :
166 l% = LEN(fni$)
168 IF NOT fni$(l% - 2 TO l%) == 'pic': QUIT -19
170 :
172 er = Pic2Spr(fni$, fno$, rle, wrt)
174 BEEP 2000, 2
176 QUIT er
178 :
180 :
182 rem + ------------------------------------------------------------------------ +
184 rem |<                                Pic2Spr                                 >|
186 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
188 rem |   Convert PIC to compressed (if possible), or uncompressed, solid SPR    |
190 rem |                                                                          |
192 rem | Modes 0/4, 8, 16, 32, 33, 64                                             |
194 rem | cmpr%  - 1 => compress (if possible), cmpr% = 0 => Dont compress         |
196 rem | overw - 1 => unconditional overwrite, 0 => error if file already exists! |
198 rem |                                                                          |
200 rem | Dependencies: EnPad and DePad (below), which use POKE$/PEEK$ (SMSQ/E)    |
202 rem | ENRLE - external toolkit command                                         |
204 rem + ------------------------------------------------------------------------ +
206 rem | V0.03, pjw, 2020 May 16, universal                                       |
208 rem | V0.04, pjw, 2020 May 17, selective compress                              |
210 rem | V0.05, pjw, 2020 Nov 26, potential buffer overrun issue fixed (!!)       |
212 rem | V0.06, pjw, 2021 Jan 08, minute tweaks and improved(?) comments          |
214 rem + ------------------------------------------------------------------------ +
216 :
218 DEFine FuNction Pic2Spr(ifn$, ofn$, cmpr%, overw)
220 LOCal ch, f%, x%, y%, l%, m%
222 LOCal ll%, sm%, bpp, sz, asz, pic, spr
224 LOCal rle%, csz, ct%, buf, pac
226 :
228 rem     Check out PIC
230 ch = FOP_IN(ifn$): IF ch < 0: RETurn ch
232 fl = FLEN(#ch): IF fl < 12: CLOSE#ch: RETurn -15: rem Cant be a PIC
234 WGET#ch; f%, x%, y%, l%, m%:            rem Get PIC header
236 CLOSE#ch
238 IF f% <> 19196: RETurn -15:             rem if flag <> $4AFC: Not a PIC
240 :
242 rem     Calculate modes and properities (bpp = Bytes Per Pixel)
244 m% = m% DIV 256:                        rem Mode in MS byte
246 SELect ON m%
248  =  0, 4: m% = 0: sm% = 1: bpp = .25
250  =  8:    m% = 1: sm% = 1: bpp = .25
252  = 16:            sm% = 2: bpp = 1
254  = 32, 33:        sm% = 2: bpp = 2
256  = 64:            sm% = 2: bpp = 4
258  = REMAINDER : RETurn -19
260 END SELect
262 IF sm% = 1: rle% = 2: ELSE : rle% = bpp: rem Use RLE2 for QL modes
264 :
266 rem     Calculate correct (for sprites) line length
268 ll% = 4 * INT((bpp * x% + 3) / 4)
270 :
272 rem     Calculate requirement, reserve memory, and load PIC
274 sz  = 24 + y% * ll%:                    rem This is the proper uncompressed size
276 asz = 24 + y% *  l%:                    rem However, it could be padded this big!
278 IF sz > asz: asz = sz
280 fl  = fl + 14:                          rem Extra for sprite header differential
282 IF fl > asz: asz = fl:                  rem Use largest space for buffer !!
284 spr = ALCHP(asz):                       rem This is your sprite
286 IF spr <= 0: RETurn -3:                    rem Out of memeory
288 pic = spr + 14:                         rem PIC position relative to top of sprite
290 LBYTES ifn$, pic
292 :
294 rem     Pad sprite data if necessary
296 IF l% < ll% THEN
298  EnPad pic + 10, y%, l%, ll%:           rem Extra padding needed
300 ELSE
302  IF l% > ll%: DePad pic + 10, y%, l%, ll%:      rem Remove unnecessary padding
304 END IF
306 rem If l% = ll% => Padding is just fine
308 :
310 rem     Compress (if wanted and possible)
312 IF cmpr% THEN
314  pac = ALCHP(asz + 8):                  rem Extra space for sprite RLE header
316  IF pac <= 0 THEN
318   RECHP spr
320   RETurn -3
322  END IF
324  csz = ENRLE(spr + 24, pac + 32, sz - 24, rle%): rem Compress!
326  IF csz > 0 THEN
328   POKE$  pac + 24, 'RLE' & rle%:        rem Set sprite's RLE header..
330   POKE_L pac + 28, sz - 24:             rem adding uncompressed size of data
332   sz = csz + 32:                        rem Data size + RLE header + sprite header
334   ct% = 64:                             rem Flag that pattern is compressed
336   csz = spr: spr = pac:                 rem Fudge this
338  ELSE
340   RECHP pac:                            rem Comp not possible. Discard buffer
342   pac = 0:                              rem Flag: no buffer here
344   ct% = 0:                              rem Pattern not compressed
346  END IF
348 ELSE
350  pac = 0:                               rem Compression not wanted
352  ct% = 0:                               rem Pattern not compressed
354 END IF
356 :
358 rem     Set header and..
360 POKE   spr +  0, sm%, m%, 0, ct%
362 POKE_W spr +  4, x%, y%, 0, 0
364 POKE_L spr + 12, 12, 0, 0
366 :
368 rem     save sprite
370 IF overw THEN
372  SBYTES_O ofn$, spr, sz
374  sz = 0
376 ELSE
378  ch = FOPEN(ofn$)
380  IF ch = -7 THEN
382   SBYTES ofn$, spr, sz
384   sz = 0
386  ELSE
388   IF ch < 0: sz = ch: ELSE : CLOSE#ch: sz = -8
390  END IF
392 END IF
394 :
396 rem     Release buffers LIFO
398 RECHP spr:                              rem Release (compressed) sprite buffer
400 IF ct% <> 0: RECHP csz:                 rem Release original sprite/pic buffer
402 :
404 RETurn sz:                              rem sz re-purposed as error code
406 END DEFine Pic2Spr
408 :
410 :
412 rem + ------------------------------------------------------------------------ +
414 rem |<                                 EnPad                                  >|
416 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
418 rem |  Add padding to graphic data, eg to pad line length to word or longword  |
420 rem |                                                                          |
422 rem | Done in situ to avoid extra buffer.                                      |
424 rem | But then the buffer must be large enough !!                              |
426 rem | newll% MUST be greater then oldll% !                                     |
428 rem + ------------------------------------------------------------------------ +
430 rem | V0.02, pjw, 2018 Apr 03; EnPad in situ from end of data up               |
432 rem | V0.03, pjw, 2021 Jan 08; Limit LOCal string variable sizes               |
434 rem + ------------------------------------------------------------------------ +
436 :
438 DEFine PROCedure EnPad(adr, ysz%, oldll%, newll%)
440 LOCal y%, fa, ta, ll$(newll%), pad$(newll% - oldll%)
442 pad$ = FILL$(CHR$(0),  newll% - oldll%):rem Pad by this much
444 fa = adr + ysz% * oldll%:               rem FROM address
446 ta = adr + ysz% * newll%:               rem  TO  address
448 :
450 FOR y% = 1 TO ysz%
452  fa = fa - oldll%
454  ta = ta - newll%
456  ll$ = PEEK$(fa, oldll%)
458  POKE$ ta, ll$ & pad$
460 END FOR y%
462 END DEFine EnPad
464 :
466 :
468 rem + ------------------------------------------------------------------------ +
470 rem |<                                 DePad                                  >|
472 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
474 rem |                Re-pad graphics data, eg to remove padding                |
476 rem |                                                                          |
478 rem | Done in situ overwriting old data.                                       |
480 rem | NB oldll% MUST be greater than newll% !                                  |
482 rem + ------------------------------------------------------------------------ +
484 rem | V0.01, pjw, 2018 Apr 03                                                  |
486 rem | V0.02, pjw, 2021 Jan 08; Limit LOCal string variable size                |
488 rem + ------------------------------------------------------------------------ +
490 :
492 DEFine PROCedure DePad(adr, ysz%, oldll%, newll%)
494 LOCal y%, fa, ta, ll$(oldll%)
496 fa = adr:                               rem FROM address
498 ta = adr:                               rem  TO  adress
500 FOR y% = 1 TO ysz%
502  ll$ = PEEK$(fa, oldll%)
504  POKE$ ta, ll$(1 TO newll%)
506  fa = fa + oldll%
508  ta = ta + newll%
510 END FOR y%
512 END DEFine DePad
514 :
516 :
518 rem + ************************************************************************ +
520 rem *<                             General Utils                              >*
522 rem + ************************************************************************ +
524 :
526 :
528 rem + ------------------------------------------------------------------------ +
530 rem |<                                Command Line                            >|
532 rem + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +
534 rem |                    Parses command line and sets defaults                 |
536 rem |                                                                          |
538 rem |  /F - or /I - Input file name                                            |
540 rem |  /O - Output file name (optional)                                        |
542 rem |  /C - RLE Compress: on/off, default on (Only responds to off or 0!)      |
544 rem |  /W - overWrite:    on/off, default on (Only responds to off or 0!)      |
546 rem |                                                                          |
548 rem | Dependencies: DETAB$                                                     |
550 rem | GLObal quote$, fni$, fno$, rle, wrt                                      |
552 rem + ------------------------------------------------------------------------ +
554 rem | V0.01, pjw, 2019 Jul 01, base version                                    |
556 rem | V0.01, pjw, 2026 Mar 28, Pic2Spr version                                 |
558 rem + ------------------------------------------------------------------------ +
560 :
562 DEFine FuNction GetCmd(cl$)
564 LOCal p%, t$(48)
566 :
568 IF cl$ = '': RETurn -15
570 :
572 rem     Get input file name
574 fni$ = Getent$("F")
576 IF fni$ = '': fni$ = Getent$("I")
578 IF fni$ = '' THEN
580  fni$ = cl$
582  IF LEN(fni$) < 6: RETurn -12
584  fno$ = ''
586 ELSE
588  fno$ = Getent$('O')
590 END IF
592 :
594 IF fno$ = '' THEN
596  fno$ = fni$(1 TO LEN(fni$) - 4) & '_spr'
598 END IF
600 IF LEN(fno$) < 6: RETurn -12
602 :
604 t$ = Getent$("C")
606 IF t$ == 'off' OR t$ = '0' THEN
608  rle = 0
610 ELSE
612  rle = 1
614 END IF
616 :
618 t$ = Getent$("W")
620 IF t$ == 'off' OR t$ = '0' THEN
622  wrt = 0
624 ELSE
626  wrt = 1
628 END IF
630 :
632 RETurn 0
634 END DEFine GetCmd
636 :
638 DEFine FuNction Getent$(c$)
640 rem Caller's cl$, p%, t$
642 rem Given the character get the entry
644 rem /C [<spaces>] ["|'] <entry> ["|'] <space> | <space> /C+1 | <eol>
646 :
648 p% = '/' & c$ INSTR cl$
650 IF p% = 0: RETurn ''
652 t$ = DETAB$(cl$(p% + 2 TO LEN(cl$)))
654 p% = ' /' INSTR t$
656 IF p% > 0: t$ = t$(1 TO p%): ELSE : p% = LEN(t$)
658 FOR p% = LEN(t$) TO 1 STEP -1
660  IF NOT t$(p%) INSTR ' /': EXIT p%
662 END FOR p%
664 :
666 t$ = t$(1 TO p%)
668 IF LEN(t$) > 1 THEN
670  p% = t$(1) INSTR quote$
672  IF p% THEN
674   IF (t$(LEN(t$)) INSTR quote$) = p% THEN
676    t$ = t$(2 TO LEN(t$) - 1)
678   END IF : END IF : END IF
680 RETurn t$
682 END DEFine Getent$
684 :
686 :

  
Generated with sb2htm on 2020 Dec 14
©pjwitte March 2oi9