Re: [Ql-Users] SAV files
On 3 Jan 2010, at 19:33, Norman Dunbar wrote: On 03/01/10 19:20, Dilwyn Jones wrote: Does anyone have information on the format of _sav basic files (as used by Liberation Software's QSAVE utility and the equivalent command in SBASIC)? I'm thinking that I might have some information somewhere. However, I once wrote a SB program to decode a _SAV file and 'print' the output in SuperBasic - I was attempting to write a librarian program that could extract procs and FNs from a _SAV (plus dependencies) and write them out as normal SuperBasic code. (ASCII in other words!) If I can find the code I'll send it over. Failing that, Jan Jones or Tony Tebby's docs have all the details - a _SAV is simply a tokenised SUperBasic program in the format it is stored internally in the 'program file' area. George will probably know all the details from his work on the Turbo stuff. I don't know the exact form of _SAV files but they are pretty certainly copies of the tokenised program. The tokens used by SMSQ/E incorporate Minerva additions to the original QL SuperBASIC as described by Jan Jones, and these will be in SMSQ/E _SAV files. George ___ QL-Users Mailing List http://www.q-v-d.demon.co.uk/smsqe.htm
Re: [Ql-Users] SAV files
Evening Dilwyn, On 03/01/10 19:20, Dilwyn Jones wrote: Does anyone have information on the format of _sav basic files (as used by Liberation Software's QSAVE utility and the equivalent command in SBASIC)? I'm thinking that I might have some information somewhere. However, I once wrote a SB program to decode a _SAV file and 'print' the output in SuperBasic - I was attempting to write a librarian program that could extract procs and FNs from a _SAV (plus dependencies) and write them out as normal SuperBasic code. (ASCII in other words!) If I can find the code I'll send it over. Failing that, Jan Jones or Tony Tebby's docs have all the details - a _SAV is simply a tokenised SUperBasic program in the format it is stored internally in the 'program file' area. George will probably know all the details from his work on the Turbo stuff. Cheers, Norman. ___ QL-Users Mailing List http://www.q-v-d.demon.co.uk/smsqe.htm
Re: [Ql-Users] SAV files
Thanks, Norman. Dilwyn Jones - Original Message - From: Norman Dunbar nor...@dunbar-it.co.uk To: ql-us...@q-v-d.com Sent: Sunday, January 03, 2010 7:33 PM Subject: Re: [Ql-Users] SAV files Evening Dilwyn, On 03/01/10 19:20, Dilwyn Jones wrote: Does anyone have information on the format of _sav basic files (as used by Liberation Software's QSAVE utility and the equivalent command in SBASIC)? I'm thinking that I might have some information somewhere. However, I once wrote a SB program to decode a _SAV file and 'print' the output in SuperBasic - I was attempting to write a librarian program that could extract procs and FNs from a _SAV (plus dependencies) and write them out as normal SuperBasic code. (ASCII in other words!) If I can find the code I'll send it over. Failing that, Jan Jones or Tony Tebby's docs have all the details - a _SAV is simply a tokenised SUperBasic program in the format it is stored internally in the 'program file' area. George will probably know all the details from his work on the Turbo stuff. Cheers, Norman. ___ QL-Users Mailing List http://www.q-v-d.demon.co.uk/smsqe.htm No virus found in this incoming message. Checked by AVG - www.avg.com Version: 9.0.725 / Virus Database: 270.14.124/2598 - Release Date: 01/03/10 09:41:00 ___ QL-Users Mailing List http://www.q-v-d.demon.co.uk/smsqe.htm
Re: [Ql-Users] SAV files
Dilwyn, attached is a file that decodes a SAV file - as promised. Hope you can read my code after all these years! Cheers, Norman. 1000 REMark _SAV file decoder 1005 : 1010 CLS 1015 PRINT 'SAV File Decoder'\\ 1020 INPUT 'Which _sav file ? ';sav$ 1025 IF sav$ = '' THEN STOP: END IF 1030 : 1035 initialise 1040 decode_header 1045 IF NOT quit 1050decode_name_table 1055decode_program 1060 END IF 1065 RELEASE_HEAP float_buffer 1070 CLOSE #3 1075 : 1080 DEFine PROCedure decode_header 1085 LOCal head$(4), name_table_length 1090 quit = 0 1095 OPEN_IN #3,sav$ 1100 head$ = FETCH_BYTES(#3, 4) 1105 IF (head$ 'Q1' CHR$(0) CHR$(0)) AND (head$ 'Q1' CHR$(2) CHR$(192)) 1110 PRINT head$, head$(1);head$(2)!!CODE(head$(3))!CODE(head$(4))\ 1115 PRINT sav$ ' is not a SAV file, or has a new flag.' 1120 CLOSE #3 1125 quit = 1 1130 RETurn 1135 END IF 1140 name_table_entries = GET_WORD(#3) 1145 name_table_length = GET_WORD(#3) 1150 program_lines = GET_WORD(#3) 1155 max_name_size = name_table_length - (4 * name_table_entries) / name_table_entries 1160 : 1165 PRINT sav$ 1170 PRINT 'Number of name table entries : '; name_table_entries 1175 PRINT 'Name table length: '; name_table_length 1180 PRINT 'Number of program lines : '; program_lines 1185 PRINT 1190 : 1195 DIM name_table$(name_table_entries -1, max_name_size) 1200 float_buffer = RESERVE_HEAP(6) 1205 quit = (float_buffer 1) 1210 END DEFine decode_header 1215 : 1220 DEFine PROCedure decode_name_table 1225 LOCal x, name_type, line_no, name_length, name$, lose_it$(1) 1230 LOCal num_procs, num_fns 1235 num_procs = 0 1240 num_fns = 0 1245 FOR x = 0 TO name_table_entries -1 1250 name_type = GET_WORD(#3) 1255 line_no = GET_WORD(#3) 1260 name_length = GET_WORD(#3) 1265 name$ = FETCH_BYTES(#3, name_length) 1270 IF name_length 1 1275lose_it$ = INKEY$(#3) 1280 END IF 1285 IF name_type = 5122 THEN num_procs = num_procs + 1 1290 IF name_type = 5377 AND name_type = 5379 1295num_fns = num_fns + 1 1300 END IF 1305 PRINT x;' Name type = '; HEX$(name_type, 16) ' '; 1310 PRINT 'Line number = '; line_no ' '; 1315 PRINT 'Name length = '; name_length; ' '; 1320 PRINT 'Name = ' name$ '' 1325 name_table$(x) = name$ 1330 END FOR x 1335 PRINT 'There are ' num_procs ' PROCs' 1340 PRINT 'There are ' num_fns ' FNs' 1345 END DEFine decode_name_table 1350 : 1355 : 1360 DEFine PROCedure decode_program 1365 LOCal x, type_byte, program_line 1370 : 1375 REMark WORD = size change 1380 REMark LONG = $8D00.line number 1385 REMark rest of line 1390 : 1395 REPeat program_line 1400 IF EOF(#3) THEN EXIT program_line: END IF 1405 line_size = line_size + GET_WORD(#3) 1410 IF line_size 65536 THEN line_size = line_size - 65536: END IF 1415 IF GET_WORD(#3) HEX('8d00') 1420PRINT 'Program out of step.' 1425CLOSE #3 1430STOP 1435 END IF 1440 PRINT GET_WORD(#3); ' '; 1445 line_done = 0 1450 REPeat line_contents 1455 type_byte = CODE(INKEY$(#3)) 1460 SELect ON type_byte 1465 = HEX('80'): multi_spaces 1470 = HEX('81'): keywords 1475 = HEX('84'): symbols 1480 = HEX('85'): operators 1485 = HEX('86'): monadics 1490 = HEX('88'): names 1495 = HEX('8B'): strings 1500 = HEX('8C'): text 1505 = HEX('8E'): separators 1510 = REMAINDER : floating_points 1515 END SELect 1520 IF line_done THEN EXIT line_contents: END IF 1525 END REPeat line_contents 1530 END REPeat program_line 1535 END DEFine decode_program 1540 : 1545 : 1550 DEFine PROCedure multi_spaces 1555 : 1560 REMark $80.nn = print nn spaces 1565 : 1570 PRINT FILL$(' ', GET_BYTE(#3)); 1575 END DEFine multi_spaces 1580 : 1585 : 1590 DEFine PROCedure keywords 1595 : 1600 REMark $81.nn = keyword$(nn) 1605 : 1610 PRINT keyword$(GET_BYTE(#3));' '; 1615 END DEFine keywords 1620 : 1625 : 1630 DEFine PROCedure symbols 1635 LOCal sym 1640 : 1645 REMark $84.nn = symbol$(nn) 1650 : 1655 sym = GET_BYTE(#3) 1660 PRINT symbol$(sym); 1665 line_done = (sym = 10) 1670 END DEFine symbols 1675 : 1680 : 1685 DEFine PROCedure operators 1690 : 1695 REMark $85.nn = operator$(nn) 1700 : 1705 PRINT operator$(GET_BYTE(#3)); 1710 END DEFine operators 1715 : 1720 : 1725 DEFine PROCedure monadics 1730 : 1735 REMark $86.nn = monadic$(nn) 1740 : 1745 PRINT monadic$(GET_BYTE(#3)); 1750 END DEFine monadic 1755 : 1760 : 1765 DEFine PROCedure names 1770 LOCal ignore 1775 : 1780 REMark $8800. = name_table$() 1785 : 1790 ignore = GET_BYTE(#3) 1795 ignore = GET_WORD(#3) 1800 IF ignore 32768 THEN ignore = ignore - 32768: END IF 1805 PRINT name_table$(ignore); 1810 END DEFine names 1815 : 1820 : 1825 DEFine PROCedure strings 1830 LOCal delim$(1), size 1835 : 1840
Re: [Ql-Users] SAV files
On 03/01/10 19:52, Norman Dunbar wrote: Dilwyn, attached is a file that decodes a SAV file - as promised. Hope you can read my code after all these years! Cheers, Norman. Sorry folks, didn't mean to send that to everyone. However, now you have it, if you want to use it, you'll need DJToolkit to be able to run it. Cheers, Norman. ___ QL-Users Mailing List http://www.q-v-d.demon.co.uk/smsqe.htm
Re: [Ql-Users] SAV files
Evening, as TT has rerwritten QLIBs QLOAD/QSAVE plus QMERGE, it should be seen in the source codes of SMSQ/E. Failing that, Jan Jones or Tony Tebby's docs have all the details - a _SAV is simply a tokenised SUperBasic program in the format it is stored internally in the 'program file' area. No (AFAIK). This (strict) way was done via TT's Software Production Kit (FBOOT/FSAVE/FLOAD, released via Sinclair, the early used copy protection). QLOAD seems to use another way as it also works, if needed resident extensions are absent. TTs way crashes. Cheers...Ralf ___ QL-Users Mailing List http://www.q-v-d.demon.co.uk/smsqe.htm
Re: [Ql-Users] SAV files
Dilwyn Jones writes: Does anyone have information on the format of _sav basic files (as used by Liberation Software's QSAVE utility and the equivalent command in SBASIC)? Heres (an incomplete) decode of the file structure. Below that an example file. HTH Per QSAVE file structure March 22nd 2001 * Head dc.w 'Q1'00 flag dc.w $0380 02 ? version ? This with SMSQ/E2.xx $0380 = Hex bin ? $02C0, $ from Norman - dont know what it implies, perhaps vanilla? dc.w count 04 number of names dc.w source-names06 size of name list dc.w lines 08 number of lines in program * names0A start names list For each name: dc.w type00 bits 0..11 as for name-table entry bits 12..15 ? bit #12: var is paramter bit #13: var is ? dc.w valp02 value pointer? Always 0? dc.w nlen04 name length dc.b namechars 06.. name bytes, padded to even number * source actual tokenised SB program file --- Example code of test program (SMSQ/E): 10 REMark Test 20 number=1 30 PRINT number 40 number = two dc.w'Q1'flag dc.w$0380 ? vers? Ive seen 0B40, 0100, 120,. dc.w3 count names dc.wsource-namessize of name list dc.w4 line count names dc.w$0800 dc.w$ dc.w5,'PRINT ' dc.w$0202 type Top bit or two set on some, for some reason dc.w$ dc.w6,'number' dc.w$0202 type dc.w$ dc.w3,'two ' source dc.w$0010 dc.w$8D00 line number dc.w10 10 dc.w$811E REMarkREMark dc.w$8C00 rem text dc.w4,'Test' Test dc.w$840A eol dc.w$0002 ? dc.w$8D00 dc.w20 20 dc.w$8800 namenumber dc.w$0001 name index dc.w$8401 = = dc.w$F801 dc.l $4000 float1 dc.w$840A eol dc.w$FFFE ? dc.w$8D00 line number dc.w30 30 dc.w$8800 namePRINT dc.w$ name index dc.w$8001 one space dc.w$8800 namenumber dc.w$0001 name index dc.w$840A eol dc.w$0004 ? dc.w$8D00 line num dc.w40 dc.w$8800 namenumber dc.w$0001 index dc.w$8001 space dc.w$8401 = = dc.w$8001 space dc.w$8800 name two dc.w$0002 index dc.w$840A eol ___ QL-Users Mailing List http://www.q-v-d.demon.co.uk/smsqe.htm