📄 exa3.html
字号:
<!doctype html public "-//W3C//DTD HTML 3.2//EN"><html><head><title>Example 3: Better compression and multi-format loader</title><meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /><meta http-equiv="content-language" content="en" /><meta name="resource-type" content="document"><meta name="copyright" content="This document copyright 2001 by Richard Murray. Use for non-profit and education purposes explicitly granted."><meta name="author" content="Richard Murray"><meta name="rating" content="general"></head><!-- /assembler/exa3.html --><!-- --><!-- (C) Copyright 1999 Richard Murray --><!-- Designed by Richard Murray --><!-- rmurray@heyrick.co.uk --><!-- --><body bgcolor="#f0f0f0" text="#000000" link="#0022dd" vlink="#002288"><table border = "0" width="100%"> <tr> <td align=center width=100> <img src="arm3.gif" width=79 height=78 align = middle> </td> <td> <h1 align="center"><font color="#800080">Example 3<br>Better compressor<br>and<br> multi-format loader</font></h1> </td> <td align=center width=100> <img src="arm3.gif" width=79 height=78 align = middle> </td> </tr></table><p> <p>In the last part I said, "So we shall, in the next part, propose a new format that willmake the compression even more efficient."<p>So, then, how can we make the compression more efficient? Remember that our compression was goodon solid areas of colour but a bit rubbish when it came down to dithered or complicated images.Consider:<p><pre> HEADER: (26 bytes)-"BudgieScrn (compressed 2)" <cr> MODE: (1 byte)-Screen mode. PALETTE: (16 * 6 bytes)-Bytes giving R, G & B components of first flash colour. Bytes giving R, G, & B components of second flash colour. IMAGE DATA: If byte = 255, then loop data follows. Next byte is the colour. Third byte is a count (0 - 254) of how many pixels of this colour to fill in. If byte <> 255, then byte is regular screen memory. Just stick it straight to the screen...</pre>Immediately, two things should be noticed:<ol> <li> If the legitimate pair is colour 15, then the byte will be 255 causing a loop. Thus, in a sequence of aligned doubles of colour 15 with something in between, it could begin to get wasteful. However such a sequence seems unlikely. If the colour 15 double extends for further pixels, a loop <i>would</i> be required. <li> This will better cope with dithered images, as two pixels will therefore take one byte instead of four (previously, loop count and colour for each pixel).</ol>It sounds horribly complex doesn't it? However in reality all we need is a look-ahead andsomething to fiddle occurances of colour 15 doubles. For a change, we shall present the savecode in BASIC because it is easier to follow (and additionally I have not coded an assemblerversion yet! :-) ). As usual, the loader is more or less a reverse of the saver, and that is inassembler.<p>The program is commented, so shouldn't need any further explanation. Converting it to assembleris left as an exercise for the reader.<p><pre>REM >Ssaver2REM Compress sprites using BudgieSoft compression algorithmREM (type 2).REMREM by Richard Murray Winter 1997REMREM Downloaded from: http://www.heyrick.co.uk/assembler/:ON ERROR PRINT REPORT$+" at "+STR$(ERL/10) : END:REM Open output file (put your own path here, or read fromREM command line).x%=OPENOUT("IDEFS::Willow.$.WWW.WWWsite.assembler.sw.screen2/raw"):REM Write out the identification header...BPUT#x%, "BudgieScrn (compressed 2)":REM ...and the current screenmode.BPUT#x%, MODE:REM Build up palette entries, and write out.FOR loop% = 0 TO 15 SYS "OS_ReadPalette", loop%, 16 TO ,,f%, s% r1% = (f% >> 8) AND 255 : REM First flash colour REM red component g1% = (f% >> 16) AND 255 : REM First flash colour REM green component b1% = (f% >> 24) AND 255 : REM First flash colour REM blue component r2% = (s% >> 8) AND 255 : REM Second flash colour REM red component g2% = (s% >> 16) AND 255 : REM Second flash colour REM green component b2% = (s% >> 24) AND 255 : REM Second flash colour REM blue component BPUT#x%, r1% : BPUT#x%, g1% : BPUT#x%, b1% BPUT#x%, r2% : BPUT#x%, g2% : BPUT#x%, b2%NEXT:REM Get our screen sizes. This is not written to file. TheREM loader will have to figure out it's own screen dimensions.REM Then switch off the cursor.DIM b% 19b%!0=149 : b%!4=7 : b%!8=-1SYS "OS_ReadVduVariables", b%, b%+12base%=b%!12 : length%=b%!16 :end%=base%+length%SYS "XOS_RemoveCursors"::REM Now read from base% to end% (via posn%) calculating theREM data, writing it out to file as necessary.:posn% = base%REPEAT REM Read four pixels (two bytes) at a time. REM If they match, begin a loop. col1% = posn%?0 col2% = posn%?1 IF col1% = col2% THEN REM They match, so... BPUT#x%, 255 BPUT#x%, col1% counter% = 0 REPEAT col1% = posn%?0 IF col1% = col2% THEN counter%+=1 posn%+=1 ENDIF UNTIL counter% = 255 OR (col1% <> col2%) BPUT#x%, counter% ELSE REM Otherwise write out pixels. BPUT#x%, col1% IF col1% = 255 THEN REM A little hack for colour 15 double (byte = 255). BPUT#x%, col1% BPUT#x%, 0 ENDIF posn% += 1 ENDIF REM Until end.UNTIL posn% >=end%:REM Close file and exit.CLOSE#x%END</pre>Apart from a few little changes in the loader routine, it is very similar to the existing loader.The differences, mainly, are:<pre> .main_loop Read a byte. Is it '255'? If so, branch with link to read_loop. Write byte (pixel pair) to screen. Look to see if we are at the end of screen. If not, branch to main_loop. Close and exit etc etc. .read_loop Read colour byte. Read length byte. .loop2 Subtract 1 from length. Write colour byte to screen. Length is zero? If not, branch to loop2. End of screen? If not, branch to main_loop. Otherwise exit.</pre>I'll leave you to compare the above flow with the program itself. It is commented so youshouldn't have too many problems.<p><div align = right><a href="sw/ssaver2.basic"><i>Download example: ssaver2.basic</i></a></div><p> <p> <p>To current date there is no type 2 saver in assembler. I use the BASIC code mentioned previously.So instead I will treat you to a loader that handles <i>all three</i> versions.<p>The code is commented, but it is not split into annotated chunks as before. You should be able tofollow what is going on.<pre>REM >Sloader2 BudgieSoft screen loader (all versions)REM Version 0.21REMREM by Richard Murray Winter 1997REMREM Downloaded from: http://www.heyrick.co.uk/assembler/:ON ERROR PRINT REPORT$+" at "+STR$(ERL/10) : END:PROCassembleOSCLI("Save <Obey$Dir>.Loader "+STR$~(code%)+" "+STR$~(O%))OSCLI("SetType <Obey$Dir>.Loader &FFC")END:DEFPROCassemble DIM code% &1000 FOR pass% = 4 TO 6 STEP 2 P%=0 O%=code% [ OPT pass% MOV R10, R14 MOV R0, #&4C SWI "XOS_Find" BVS exit MOV R5, R0 ; Skip header MOV R8, #0 .skip_header MOV R1, R5 BL read_byte ADD R8, R8, #1 CMP R8, #23 BLT skip_header MOV R1, R5 BL read_byte CMP R0, #10 ; Newline - version 0. BEQ version_zero CMP R0, #49 ; '1' - version 1. BEQ version_one CMP R0, #50 ; '2' - version 2. BEQ version_two ADR R0, unknown_string SWI "OS_PrettyPrint" SWI "OS_NewLine" SWI "OS_NewLine" B exit .unknown_string EQUS "Unable to load this screen - the format" EQUS " has not been recognised..." EQUB 0 ALIGN ; *** VERSION ZERO HANDLER *** .version_zero B load_old_format ; *** VERSION ONE HANDLER *** .version_one MOV R1, R5 BL read_byte BL read_byte B load_old_format ; *** VERSION TWO HANDLER .version_two MOV R1, R5 BL read_byte BL read_byte B load_new_format ; *** OLD FORMAT LOADER *** .load_old_format BL switch_screen_mode BL get_screen_info BL load_palette .old_loop MOV R1, R5 BL read_byte MOV R4, R0 BL read_byte .old_loop2 SUB R0, R0, #1 STRB R4, [R2, #1]! CMP R0, #0 BGT old_loop2 CMP R2, R3 BLT old_loop B exit ; *** NEW FORMAT LOADER *** .load_new_format BL switch_screen_mode BL get_screen_info BL load_palette .new_loop MOV R1, R5 BL read_byte CMP R0, #255 BLEQ read_loop STRB R0, [R2, #1]! CMP R2, R3 BLT new_loop B exit ; *** RESOURCES *** .switch_screen_mode MOV R12, R14 MOV R0, #&87 SWI "XOS_Byte" MOV R1, R5 BL read_byte CMP R0, R2 SWINE &100 + 22 SWINE "OS_WriteC" MOV PC, R12 .get_screen_info ADR R0, vdu_block ADD R1, R0, #12 SWI "OS_ReadVduVariables" LDR R2, [R1] LDR R3, [R1, #4] ADD R3, R3, R2 SUB R2, R2, #1 MOV PC, R14 .load_palette MOV R12, R14 MOV R4, #0 ADR R7, os_block .col_loop MOV R1, R5 STRB R4, [R7, #0] MOV R0, #17 STRB R0, [R7, #1] BL read_byte STRB R0, [R7, #2] BL read_byte STRB R0, [R7, #3] BL read_byte STRB R0, [R7, #4] MOV R0, #&0C MOV R1, R7 SWI "OS_Word" MOV R1, R5 MOV R0, #18 STRB R0, [R7, #1] BL read_byte STRB R0, [R7, #2] BL read_byte STRB R0, [R7, #3] BL read_byte STRB R0, [R7, #4] MOV R0, #&0C MOV R1, R7 SWI "OS_Word" ADD R4, R4, #1 CMP R4, #16 BLT col_loop MOV R0, #0 MOV PC, R12 .exit MOV R2, R0 MOV R1, R5 MOV R0, #0 SWI "XOS_Find" MOV PC, R10 .read_byte SWI "XOS_BGet" MOVVC PC, R14 .read_loop ; Read and deal with loop data. MOV R1, R5 BL read_byte ; Read colour MOV R4, R0 BL read_byte ; Read length .loop2 SUB R0, R0, #1 STRB R4, [R2, #1]! CMP R0, #0 ; More to loop? BGT loop2 CMP R2, R3 ; End of screen? BLT new_loop B exit .vdu_block EQUD 149 EQUD 7 EQUD -1 EQUD 0 EQUD 0 .os_block EQUD 0 EQUB 0 ALIGN ] NEXTENDPROC</pre>This concludes our series on creating compressed screen software. If you wish to write anassembler saver for type 2 files, please do so. Likewise, bug reports and such would also bewelcomed.<p><div align = right><a href="sw/sloader2.basic"><i>Download example: sloader2.basic</i></a></div><div align = right><a href="sw/screen2.raw"><i>Download example compressed screen (type 2):screen2.raw</i></a></div><p> <p> <p>By way of comparison, here is a type 1 version of the above image. It is a moderately balancedimage, a textured JPEG and textured windows alongside plain windows.<p><div align = right><a href="sw/compscrn.raw"><i>Download example compressed screen:compscrn.raw</i></a></div><p>The type 1 screen is 159771 bytes.<br>The type 2 screen is 123369 bytes.<p><hr size = "3"><a href="index.html#15">Return to assembler index</a><hr size = "3"><address>Copyright © 1999 Richard Murray</address></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -