REM===================================================================== REM REM Program : WAT2PPM REM Purpose : Command-line translator, Watford 6-bit mono to 24-bit PPM REM Author : Ian Giblin (c) August 1996 REM Notes : Full size needs a minumum slot of 1440 K excluding Basic REM You could adjust the gamma by tweaking the LUT values. REM REM===================================================================== ON ERROR PRINT REPORT$;" at line ";ERL:END debug = FALSE taskname$ = "WAT2PPM" version = 1.00 half_size = FALSE DIM word$(10) wordcount% = 0 PROCparameters(word$(), wordcount%) IF wordcount%<2 THEN PRINT'"WAT2PPM "+STR$(version)+" by Ian Giblin " PRINT "Usage: wat2ppm [-halfsize] " PRINT "This quickly translates a Watford file into a PPM file" PRINT'" -halfsize makes 320 x 256 output (default is 640 x 512)" PRINT'"Terms: Freeware, carries no warranty, remains (c) Ian Giblin"' END ENDIF source$ = word$(wordcount%-1) dest$ = word$(wordcount%) IF NOT FNfile_exists(source$) THEN PRINT"Source file does not exist.":VDU7 END ENDIF IF wordcount%>2 THEN FOR w%=1 TO wordcount%-2 CASE word$(w%) OF WHEN "-halfsize": half_size = TRUE OTHERWISE: PRINT'"Error: Option '";word$(w%);"' unknown.":END ENDCASE NEXT w% ENDIF IF half_size THEN ppm_width% = 320 ppm_height% = 256 ELSE ppm_width% = 640 ppm_height% = 512 ENDIF SYS"Hourglass_On" t0 = TIME REM ***** INITIALISE ***** report_assembly = debug palette_is_redefinable = FALSE ppm_file_size% = (ppm_width% * ppm_height% * 3) + 16 DIM file% (ppm_file_size%+16) : REM ** This area used twice DIM image% (640*256*3) : REM ** This area used only once DIM LUT% 256 REM ***** BUILD LUT (GAMMA CORRECT HERE) ***** FOR i%=0 TO 63 : ?(LUT%+i%)=i%*4 : NEXT i% REM ***** INITIALISE ***** PROCasm_decompress PROCasm_interlace PROCasm_halfsize OSCLI("*LOAD "+source$+" "+STR$~(file%)) IF debug PRINT"Decompressing..."; A% = file% B% = image% C% = LUT% CALL decompress% IF debug PRINT"OK." REM ***** BUILD PPM HEADER ***** REM ** Do this here so the trailing zero is overwritten ** LF$ = CHR$10 a$ = "P6"+LF$+STR$(ppm_width%)+" "+STR$(ppm_height%)+LF$+"255"+LF$ $(file%+1)=a$ IF half_size THEN IF debug PRINT"Halfsizing..."; A% = image% B% = (file%+16) CALL halfsize% IF debug PRINT"OK." ELSE IF debug PRINT"Interlacing..."; A% = image% B% = (file%+16) CALL interlace% IF debug PRINT"OK." ENDIF IF debug PRINT"Processing time was ";(TIME-t0);" cs" IF debug PRINT"Saving to '"+dest$+"'..."; OSCLI("*SAVE "+dest$+" "+STR$~(file%+1)+" + "+STR$~(ppm_file_size%+15)) OSCLI("*SETTYPE "+dest$+" &69E") IF debug PRINT"OK." SYS"Hourglass_Off" IF debug PRINT"Total time was ";(TIME-t0);" cs" END REM===================================================================== REM REM Procedure ASSEMBLE_HALFSIZE REM DEFPROCasm_halfsize area_size% = 160 DIM halfsize% area_size% FOR pass%=0 TO 2 STEP 2 source = 0 dest = 1 count = 2 byte = 3 P% = halfsize% [ OPT pass% STMFD 13!,{0-12,14} ; Save everything MOV count, #(640*256) ; This is the number of pixels .halfsize_loop LDRB byte, [source], #01 ; Get first byte ADD source, source, #02 ; ..other 2 are the same ADD source, source, #03 ; ..and then skip 3 more STRB byte, [dest], #01 ; Store three times STRB byte, [dest], #01 ; STRB byte, [dest], #01 ; SUBS count, count, #02 ; Safe way to exit when done BNE halfsize_loop ; ..and loop as normal. .exit LDMFD 13!,{0-12,PC} ; Return ] NEXT pass% IF (P%-halfsize%)>area_size% THEN PRINT "ERROR: Halfsize has over-run it's allocated RAM area":END ENDIF IF report_assembly THEN PRINT "Halfsize assembled : ";(P%-halfsize%);" bytes "; PRINT "(";(area_size%-(P%-halfsize%));" to spare)" ENDIF ENDPROC REM===================================================================== REM REM Procedure ASSEMBLE_INTERLACE REM REM Purpose : A nice, fast way to interlace a decompressed picture. REM DEFPROCasm_interlace area_size% = 160 DIM interlace% area_size% FOR pass%=0 TO 2 STEP 2 REM -- R0 is the source REM -- R1 is the destination REM -- R2 is the line counter P% = interlace% [ OPT pass% STMFD 13!,{0-12,14} ; Save everything MOV R2, #&800 ; This is the number of loops required! .line_loop ; Each of these LDM-STM pairs is 36 bytes (= 12 pixels) except ; for the last one, which is 12 bytes (= 4 pixels) to get 160. LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 12 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 24 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 36 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 48 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 60 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 72 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 84 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 96 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 108 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 120 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 132 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 144 LDMIA R0!, {R3-R11} : STMIA R1!, {R3-R11} ; total 156 LDMIA R0!, {R3-R5} : STMIA R1!, {R3-R5} ; total 160 SUBS R2, R2, #01 ; Safe way to exit when done BEQ exit ; ; This bit - this is totally *wicked*. Check it! AND R3, R2, #07 ; Take lowest three bits of counter CMP R3, #03 ; ..does this number end in 011 ? SUBEQ R0, R0, #(640*3) ; Reset to start of source line BAL line_loop ; ..and loop as normal. .exit LDMFD 13!,{0-12,PC} ; Return ] NEXT pass% IF (P%-interlace%)>area_size% THEN PRINT "ERROR: Interlace has over-run it's allocated RAM area":END ENDIF IF report_assembly THEN PRINT "Interlace assembled : ";(P%-interlace%);" bytes "; PRINT "(";(area_size%-(P%-interlace%));" to spare)" ENDIF ENDPROC REM===================================================================== REM REM Procedure ASSEMBLE_DECOMPRESS REM REM Purpose : Sets up the m/c routine for "CALL decompress%" REM REM The routine expects A% = the (disc) file address REM B% = the destination address REM DEFPROCasm_decompress area_size% = 128 DIM decompress% area_size% FOR pass%=0 TO 2 STEP 2 source = 0 : REM --- Address of compressed data (from A%) dest = 1 : REM --- " " decompressed data (from B%) lookup = 2 : REM --- address of look-up table current = 3 : REM --- Value of current pixel count = 4 : REM --- Counter for run-length stuff total = 5 : REM --- Total-length-so-far counter byte = 6 : REM --- Data byte (from file) ramval = 7 : REM --- Ram value for screen plotting type = 8 : REM --- 0..3 pixel-type code jump_pt = 9 : REM --- counter for when we need extra pixels P% = decompress% [ OPT pass% MOV total,#0 ; Reset counter MOV current,#0 ; MOV jump_pt,#4 .loop ; LDRB byte,[source],#01 ; Grab byte AND count,byte,#%00111111 ; Mask out the "number" MOVS type,byte,LSR#6 ; Grab the code type MOVEQ current,count ; Zero is a special case MOVEQ count,#01 ; BEQ happy ; CMP type,#%10 ; Which code is it ? SUBLT current,current,#01 ; Pre-empt write-back ADDGT current,current,#01 ; Pre-empt write-back .happy ; ] IF palette_is_redefinable THEN [OPT pass% ; Use raw level MOV ramval,current : ] ELSE [OPT pass% ; Fetch value from LUT LDRB ramval,[lookup,+current] : ] ENDIF [OPT pass% ADD total,total,count ; ..accumulate total no. .repeat ; STRB ramval,[dest],#01 ; Put value into RAM STRB ramval,[dest],#01 ; STRB ramval,[dest],#01 ; SUBS jump_pt,jump_pt,#01 ; ..jumpy extra pixel? STREQB ramval,[dest],#01 ; ..if so, put twice STREQB ramval,[dest],#01 ; STREQB ramval,[dest],#01 ; MOVEQ jump_pt,#04 ; ..and reset counter SUBS count,count,#01 ; Count down (image pixels) BNE repeat ; ..loop if non-zero CMP total,#&20000 ; We want 128K of data BNE loop ; MOV R15,R14 ] NEXT pass% IF (P%-decompress%)>area_size% THEN PRINT "ERROR: Decompress has over-run it's allocated RAM area":END ENDIF IF report_assembly THEN PRINT "Decompress assembled : ";(P%-decompress%);" bytes "; PRINT "(";(area_size%-(P%-decompress%));" to spare)" ENDIF ENDPROC REM===================================================================== REM REM Procedure : PARAMETERS REM Purpose : Simplistic way to get the command line parameters REM Notes : Needs word$() and wordcount% to exist a priori. REM wordcount% is the number of *parameters*, maybe zero. DEFPROCparameters(RETURN word$(), RETURN wordcount%) LOCAL debug, c$, b$ , w% leader$ = "BASIC -quit " debug = FALSE SYS "OS_GetEnv" TO c$ IF LEFT$(c$, LEN(leader$))<>leader$ THEN PRINT'"Error from PROCparameters: Leader is not "+CHR$34+leader$+CHR$34 PRINT'"The full command line is: "+c$ PRINT'"You need to edit the program (or your sysvars!)."' END ENDIF c$ = RIGHT$(c$, LEN(c$)-LEN(leader$)) + " " WHILE INSTR(c$,CHR$(34))>0:MID$(c$,INSTR(c$,CHR$34))=" ":ENDWHILE IF debug THEN PRINT "c$="+CHR$34+c$+CHR$34 WHILE LEFT$(c$,1)=" ":c$=RIGHT$(c$,LEN(c$)-1):ENDWHILE IF debug THEN PRINT "c$="+CHR$34+c$+CHR$34 w% = 0 WHILE LEN(c$)>0 b$ = "" WHILE LEFT$(c$,1)<>" " b$ = b$+LEFT$(c$,1) c$ = RIGHT$(c$,LEN(c$)-1) ENDWHILE WHILE c$<>"" AND LEFT$(c$,1)=" ":c$=RIGHT$(c$,LEN(c$)-1):ENDWHILE IF debug THEN PRINT "c$="+CHR$34+c$+CHR$34+" word(";w%;") = "+b$ word$(w%) = b$ w% += 1 ENDWHILE wordcount% = w%-1 ENDPROC REM---------------------------------------------------------------------- REM REM Function : FILE_EXISTS REM Purpose : Tests for 'file' existence and returns TRUE or FALSE REM Notes : In more detail, R0 = 0 ==> Not found REM R0 = 1 ==> File found REM R0 = 2 ==> Directory found REM REM See page 850 in the RISC-OS 2 PRM's for more info. DEFFNfile_exists(a$) LOCAL R0,name% DIM name% 128 $name%=a$ SYS "OS_File",5,name% TO R0 =(R0<>0)