home *** CD-ROM | disk | FTP | other *** search
/ Kosovo Orphans' Appeal Charity CD / KosovoOrphansAppeal.iso / archimedesworld_cd2 / acornanswers / _scape2 / s / dith next >
Text File  |  1996-01-23  |  18KB  |  424 lines

  1.  
  2. ; g256wnp_internal
  3. ; a leaf APCS function
  4. ; to dither from source to destination sprite
  5. ;
  6. ; C prototype
  7. ; void g256wnp_internal(int x, int y, char *dp, char *sp, compact_dither_error *de, char *lut, unsigned int *pal256def)
  8. ; x is sprite width in pixels, y is height in pixels,
  9. ; dp pts to destination sprite image (8bpp),
  10. ; sp pts to source image (32bpp),
  11. ; de pts to line buffer to hold compact_dither_errors (each of form er,eg,eb,byte-to-pad - all signed chars),
  12. ; lut pts to 32768 byte look up table to map 15 bit rbg colour to nearest available colour number in default palette,
  13. ; pal256def pts to 256 int list of default palette
  14. ;
  15.  
  16.                 ^       4, fp
  17. dxp             #       4
  18. dyp             #       4
  19. ddp             #       4
  20. dsp             #       4
  21. dde             #       4
  22. dlut            #       4
  23. dpal256def      #       4
  24.  
  25. gwi_xp          RN      r0
  26. gwi_yp          RN      r1      ;nb also is gwi_m4
  27. gwi_m4          RN      r1      ;nb also is gwi_yp
  28. gwi_dp          RN      r2
  29. gwi_sp          RN      r3
  30. gwi_de          RN      r4
  31. gwi_lut         RN      r5
  32. gwi_pal256def   RN      r6
  33. gwi_r           RN      r7
  34. gwi_g           RN      r8
  35. gwi_b           RN      r9
  36. gwi_i           RN      r10
  37. gwi_m3          RN      r11     ;nb also is fp
  38. gwi_m2          RN      r12
  39. gwi_m1          RN      r13
  40. gwi_lde         RN      r14
  41.  
  42.         ASSERT  gwi_m1>gwi_m2 :LAND: gwi_m2>gwi_m3 :LAND: gwi_m3>gwi_m4
  43.                 ;Note, scanning of image is done in a serpentine fashion to reduce dither
  44.                 ;pattern effects, & to maintain speed the main processing code is replicated,
  45.         MACRO            ;more or less, three times: 1st to scan the top row (for which we have no
  46. $label  gwi_seg1        ;precalculated errors from a row above), & then twice more, once to scan odd
  47.                 ;rows right to left & once for scanning even rows left to right.
  48.                 ;This macro contains code common to each of the three incidents - it is
  49.                 ;entered with gwi_r, _g & _b containing the desired destination colour
  50.                 ;(including any error terms added in), & it writes to destination image the
  51.                 ;nearest colour available, then calculates the error term for this pixel in
  52.                 ;gwi_lde (last dither error).
  53. $label  MOV     gwi_m1, gwi_r, ASR #3    ;from here . . .
  54.         CMP     gwi_r, #255
  55.         MOVGT   gwi_m1, #31
  56.         CMP     gwi_r, #0
  57.         MOVLT   gwi_m1, #0        ;to here, round r component down to 5 bits & clip to 0-31 (into _m1 bits 0-4)
  58.         MOV     gwi_m2, gwi_g, ASR #3
  59.         CMP     gwi_g, #255
  60.         MOVGT   gwi_m2, #31
  61.         CMP     gwi_g, #0
  62.         MOVLT   gwi_m2, #0
  63.         ADD     gwi_m1, gwi_m1, gwi_m2, ASL #5    ;as above, for g component, into _m1 bits 5-9
  64.         MOV     gwi_m2, gwi_b, ASR #3
  65.         CMP     gwi_b, #255
  66.         MOVGT   gwi_m2, #31
  67.         CMP     gwi_b, #0
  68.         MOVLT   gwi_m2, #0
  69.         ADD     gwi_m1, gwi_m1, gwi_m2, ASL #10    ;as above, for b component, into _m1 bits 10-14
  70.                     ;ie _m1 is now the desired 15 bits rgb colour
  71.         LDRB    gwi_m1, [gwi_lut, gwi_m1]    ;set _m1 to number of nearest available colour via a look up table
  72.         STRB    gwi_m1, [gwi_dp, #0]        ;write this to destination image
  73.         LDR     gwi_m1, [gwi_pal256def, gwi_m1, ASL #2]    ;read the 24 bit rgb value of the colour just written
  74.         MOV     gwi_m2, gwi_m1, LSL #16        ;from here . . .
  75.     SUB    gwi_m3, gwi_r, gwi_m2, LSR #24
  76.         CMP     gwi_m3, #127
  77.         MOVGT   gwi_m3, #127
  78.         CMP     gwi_m3, #-127
  79.         MOVLT   gwi_m3, #-127
  80.         AND     gwi_m3, gwi_m3, #255        ;to here, calc (desired red)-(used red), & clip to a signed 8 bit value
  81.         MOV     gwi_m2, gwi_m1, LSL #8
  82.         SUB     gwi_m2, gwi_g, gwi_m2, LSR #24
  83.         CMP     gwi_m2, #127
  84.         MOVGT   gwi_m2, #127
  85.         CMP     gwi_m2, #-127
  86.         MOVLT   gwi_m2, #-127
  87.         AND     gwi_m2, gwi_m2, #255
  88.         ADD     gwi_m3, gwi_m3, gwi_m2, LSL #8    ;as above, for green, inserting the error into correct bits in _m3
  89.         SUB     gwi_m2, gwi_b, gwi_m1, LSR #24
  90.         CMP     gwi_m2, #127
  91.         MOVGT   gwi_m2, #127
  92.         CMP     gwi_m2, #-127
  93.         MOVLT   gwi_m2, #-127
  94.         AND     gwi_m2, gwi_m2, #255
  95.         ADD     gwi_lde, gwi_m3, gwi_m2, LSL #16    ;as above, for blue - _lde now holds all three signed
  96.                             ;8 bit error terms
  97.         MEND
  98.  
  99. gwi_asl DCD     0                    ;storage for sl, fp & sp, during internal calcs
  100. gwi_afp DCD     0
  101. gwi_asp DCD     0
  102.  
  103. gwi_aj          DCD     0                ;current row number
  104.  
  105.         EXPORT  g256wnp_internal
  106.  
  107. gwinsta DCB     "g256wnp_internal", 0
  108.         ALIGN
  109. gwinend DCD     &ff000000 + gwinend - gwinsta
  110.  
  111. g256wnp_internal
  112.  
  113.         MOV     ip, sp
  114.         STMFD   sp!, {a1-a4}        ;stack fn args x,y,dp & sp onto stack below remaining args de,lut & pal256def
  115.         STMFD   sp!, {r4-r9, fp, ip, lr, pc}
  116.         SUB     fp, ip, #20             ;leaf fn & little need of stack, so don't bother with stack checking
  117.  
  118.         STR     sl, gwi_asl
  119.         STR     fp, gwi_afp
  120.         STR     sp, gwi_asp             ; strictly, don't need to save this, as restore frame from fp which
  121.                                         ; contains old sp, however keep it here in case change code st need
  122.                                         ; to make an external APCS call
  123.         ;set up regs now
  124.         LDR     gwi_xp, dxp        ;note dxp etc are register relative - so this actually does LDR _xp, [fp, #4]
  125.         LDR     gwi_yp, dyp        ;sprite heights in pixels (xp is corresponding widths)
  126.         LDR     gwi_dp, ddp        ;ptr to destination sprite image (ie image data itself & not the spr hdr)
  127.         LDR     gwi_sp, dsp        ;ptr to source sprite image
  128.         LDR     gwi_de, dde        ;ptr to a buffer for error terms (must be xp words long)
  129.         LDR     gwi_lut, dlut        ;ptr to lut to map 15bit rgb colour to nearest available in default 8bpp pal
  130.         LDR     gwi_pal256def, dpal256def    ;ptr to default 8bpp 256 entry palette (used to calc errors)
  131.  
  132.         ;code
  133.         MOV     gwi_i, gwi_xp        ;current column number (actually, xp-number)
  134.         CMP     gwi_i, #0
  135.         BLE     gwi_xloop1done
  136.  
  137. gwi_xloop1
  138.     LDR    gwi_m1, [gwi_sp, #0]
  139.         AND     gwi_r, gwi_m1, #255    ;from here . . .
  140.         MOV     gwi_g, gwi_m1, LSR #8
  141.         AND     gwi_g, gwi_g, #255
  142.         MOV     gwi_b, gwi_m1, LSR #16
  143.         AND     gwi_b, gwi_b, #255    ;to here, extract three r,g & b 8 bit components into _r, _g & _b
  144.         CMP     gwi_i, gwi_xp
  145.         BEQ     gwi_xl1_b1
  146.                     ;if not on first pixel in row, there is an error term to add in from left:
  147.         MOV     gwi_m1, gwi_lde, LSL #24    ;extract red error from _lde &
  148.         MOV     gwi_m1, gwi_m1, ASR #24        ;sign extend it to 32 bits
  149.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3    ;from here . . .
  150.         ADDMI   gwi_m1, gwi_m1, #15        ;    (need to ensure *7/16 will round towards 0, rather than down)
  151.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4    ;to here, add to _r 7/16 lde red error term
  152.         MOV     gwi_m1, gwi_lde, LSL #16    ;from here . . .
  153.         MOV     gwi_m1, gwi_m1, ASR #24
  154.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3
  155.         ADDMI   gwi_m1, gwi_m1, #15
  156.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4    ;to here, extract green error & add 7/16 of it into _g
  157.         MOV     gwi_m1, gwi_lde, LSL #8        ;from here . . .
  158.         MOV     gwi_m1, gwi_m1, ASR #24
  159.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3
  160.         ADDMI   gwi_m1, gwi_m1, #15
  161.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;to here, extract blue error from lde & add 7/16 into _b
  162.         STR     gwi_lde, [gwi_de, gwi_i, ASL #2]    ;buffer lde for when processing row below
  163.  
  164. gwi_xl1_b1
  165.  
  166.         gwi_seg1                ;write to destination image & calculate error for this pixel (into lde)
  167.  
  168.         ADD     gwi_dp, gwi_dp, #1        ;step through destination image one pixel
  169.         ADD     gwi_sp, gwi_sp, #4        ;step through source image one pixel
  170.         SUBS    gwi_i, gwi_i, #1
  171.         BGT     gwi_xloop1            ;& repeat till all of first row processed
  172. gwi_xloop1done
  173.                         ;now step down to next row (remember, serpentine scanning)
  174.         RSB     gwi_m2, gwi_xp, #4
  175.         AND     gwi_m1, gwi_m2, #3        ; . . . to get past righthand wastage of last row, dest image
  176.         ADD     gwi_m1, gwi_m1, gwi_xp        ; . . . to get past end of next row
  177.         SUB     gwi_m1, gwi_m1, #1        ; . . . to get back to last pixel on that row
  178.         ADD     gwi_dp, gwi_dp, gwi_m1        ;make the adjustment to _dp
  179.     ADD     gwi_sp, gwi_sp, gwi_xp, LSL #2    ;from here . . .
  180.         SUB     gwi_sp, gwi_sp, #4        ;to here, as above for src image (note, it has 4*xp bytes per row)
  181.  
  182.         SUBS    gwi_m1, gwi_yp, #2
  183.         BMI     gwi_yloopdone            ;carry on with next row, unless all rows done (note, subtract
  184.         STR     gwi_m1, gwi_aj            ; 2 from yp initially since yp is # rows counting from 1, &
  185.                         ; branch cond is MI, ie loop counts rows including 0)
  186.                     ;note, de buffer holds errors for row above, running from right in low
  187.                     ;memory to left side in high mem. Next row will be scanned right to
  188. gwi_yloop                ;left, so need extract errors from buffer in increasing memory order.
  189.  
  190.         STR     gwi_lde, [gwi_de, #0]    ;buffer error for final pixel from last row
  191.         MOV     gwi_i, #1
  192.         CMP     gwi_i, gwi_xp
  193.         BGT     gwi_xloop2done
  194.                     ;all remaining code is similar to preceeding, except have to add in
  195. gwi_xloop2                ;errors from row above, & scan row in reverse direction
  196.     LDR    gwi_m1, [gwi_sp, #0]
  197.         AND     gwi_r, gwi_m1, #255    ;from here . . .
  198.         MOV     gwi_g, gwi_m1, LSR #8
  199.         AND     gwi_g, gwi_g, #255
  200.         MOV     gwi_b, gwi_m1, LSR #16
  201.         AND     gwi_b, gwi_b, #255    ;to here, extract three r,g & b 8 bit components into _r, _g & _b
  202.  
  203.         SUB     gwi_m4, gwi_i, #1    ;from here . . .
  204.         LDR     gwi_m4, [gwi_de, gwi_m4, ASL #2]
  205.         MOV     gwi_m1, gwi_m4, LSL #24
  206.         MOV     gwi_m1, gwi_m1, ASR #24
  207.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #2
  208.         ADDMI   gwi_m1, gwi_m1, #15
  209.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4
  210.         MOV     gwi_m1, gwi_m4, LSL #16
  211.         MOV     gwi_m1, gwi_m1, ASR #24
  212.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #2
  213.         ADDMI   gwi_m1, gwi_m1, #15
  214.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4
  215.         MOV     gwi_m1, gwi_m4, LSL #8
  216.         MOV     gwi_m1, gwi_m1, ASR #24
  217.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #2
  218.         ADDMI   gwi_m1, gwi_m1, #15
  219.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;to here, add in 5/16 error for pixel above
  220.  
  221.         CMP     gwi_i, #1
  222.         BEQ     gwi_xl2_b1
  223.  
  224.         SUB     gwi_m2, gwi_i, #2        ;similiarly (if not on rightmost column) . . .
  225.         LDR     gwi_m4, [gwi_de, gwi_m2, ASL #2]
  226.         MOV     gwi_m1, gwi_m4, LSL #24
  227.         MOVS    gwi_m1, gwi_m1, ASR #24
  228.         ADDMI   gwi_m1, gwi_m1, #15
  229.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4
  230.         MOV     gwi_m1, gwi_m4, LSL #16
  231.         MOVS    gwi_m1, gwi_m1, ASR #24
  232.         ADDMI   gwi_m1, gwi_m1, #15
  233.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4
  234.         MOV     gwi_m1, gwi_m4, LSL #8
  235.         MOVS    gwi_m1, gwi_m1, ASR #24
  236.         ADDMI   gwi_m1, gwi_m1, #15
  237.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;add in 1/16 error for pixel to above right
  238.  
  239.         STR     gwi_lde, [gwi_de, gwi_m2, ASL #2]    ;can now safely overwrite value in buffer with lde for next row
  240.  
  241.         MOV     gwi_m1, gwi_lde, LSL #24
  242.         MOV     gwi_m1, gwi_m1, ASR #24
  243.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3
  244.         ADDMI   gwi_m1, gwi_m1, #15
  245.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4
  246.         MOV     gwi_m1, gwi_lde, LSL #16
  247.         MOV     gwi_m1, gwi_m1, ASR #24
  248.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3
  249.         ADDMI   gwi_m1, gwi_m1, #15
  250.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4
  251.         MOV     gwi_m1, gwi_lde, LSL #8
  252.         MOV     gwi_m1, gwi_m1, ASR #24
  253.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3
  254.         ADDMI   gwi_m1, gwi_m1, #15
  255.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;now add in 7/16 error for pixel to right
  256.  
  257. gwi_xl2_b1
  258.         CMP     gwi_i, gwi_xp
  259.         BEQ     gwi_xl2_b2
  260.  
  261.         LDR     gwi_m4, [gwi_de, gwi_i, ASL #2]    ;if not on far left column . . .
  262.         MOV     gwi_m1, gwi_m4, LSL #24
  263.         MOV     gwi_m1, gwi_m1, ASR #24
  264.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #1
  265.         ADDMI   gwi_m1, gwi_m1, #15
  266.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4
  267.         MOV     gwi_m1, gwi_m4, LSL #16
  268.         MOV     gwi_m1, gwi_m1, ASR #24
  269.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #1
  270.         ADDMI   gwi_m1, gwi_m1, #15
  271.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4
  272.         MOV     gwi_m1, gwi_m4, LSL #8
  273.         MOV     gwi_m1, gwi_m1, ASR #24
  274.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #1
  275.         ADDMI   gwi_m1, gwi_m1, #15
  276.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;add in 3/16 error for pixel to above left
  277.  
  278. gwi_xl2_b2
  279.  
  280.         gwi_seg1                ;write destination pixel & calc new error for pixel
  281.  
  282.         SUB     gwi_dp, gwi_dp, #1
  283.         SUB     gwi_sp, gwi_sp, #4
  284.         ADD     gwi_i, gwi_i, #1
  285.         CMP     gwi_i, gwi_xp
  286.         BLE     gwi_xloop2            ;loop back til all of right to left row processed
  287. gwi_xloop2done
  288.  
  289.         RSB     gwi_m2, gwi_xp, #4
  290.         AND     gwi_m1, gwi_m2, #3
  291.         ADD     gwi_m1, gwi_m1, gwi_xp
  292.         ADD     gwi_m1, gwi_m1, #1
  293.         ADD     gwi_dp, gwi_dp, gwi_m1
  294.     ADD     gwi_sp, gwi_sp, gwi_xp, LSL #2
  295.         ADD     gwi_sp, gwi_sp, #4        ;step sp, dp to next row (to be scanned left to right)
  296.  
  297.         LDR     gwi_m1, gwi_aj
  298.         SUBS    gwi_m1, gwi_m1, #1
  299.         STR     gwi_m1, gwi_aj
  300.         BMI     gwi_yloopdone            ;continue with next row, unless all done
  301.  
  302.         SUB     gwi_m1, gwi_xp, #1
  303.         STR     gwi_lde, [gwi_de, gwi_m1, ASL #2]    ;buffer error for final pixel on last row
  304.         MOV     gwi_i, gwi_xp
  305.         CMP     gwi_i, #0
  306.         BLE     gwi_xloop3done
  307.  
  308. gwi_xloop3
  309.     LDR    gwi_m1, [gwi_sp, #0]
  310.         AND     gwi_r, gwi_m1, #255    ;from here . . .
  311.         MOV     gwi_g, gwi_m1, LSR #8
  312.         AND     gwi_g, gwi_g, #255
  313.         MOV     gwi_b, gwi_m1, LSR #16
  314.         AND     gwi_b, gwi_b, #255    ;to here, extract three r,g & b 8 bit components into _r, _g & _b
  315.  
  316.         SUB     gwi_m4, gwi_i, #1        ;for pixel above . . .
  317.         LDR     gwi_m4, [gwi_de, gwi_m4, ASL #2]
  318.         MOV     gwi_m1, gwi_m4, LSL #24
  319.         MOV     gwi_m1, gwi_m1, ASR #24
  320.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #2
  321.         ADDMI   gwi_m1, gwi_m1, #15
  322.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4
  323.         MOV     gwi_m1, gwi_m4, LSL #16
  324.         MOV     gwi_m1, gwi_m1, ASR #24
  325.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #2
  326.         ADDMI   gwi_m1, gwi_m1, #15
  327.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4
  328.         MOV     gwi_m1, gwi_m4, LSL #8
  329.         MOV     gwi_m1, gwi_m1, ASR #24
  330.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #2
  331.         ADDMI   gwi_m1, gwi_m1, #15
  332.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;add in 5/16 error
  333.  
  334.         CMP     gwi_i, gwi_xp
  335.         BEQ     gwi_xl3_b1
  336.                         ;if not on leftmost column . . .
  337.         LDR     gwi_m4, [gwi_de, gwi_i, ASL #2]
  338.         MOV     gwi_m1, gwi_m4, LSL #24
  339.         MOVS    gwi_m1, gwi_m1, ASR #24
  340.         ADDMI   gwi_m1, gwi_m1, #15
  341.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4
  342.         MOV     gwi_m1, gwi_m4, LSL #16
  343.         MOVS    gwi_m1, gwi_m1, ASR #24
  344.         ADDMI   gwi_m1, gwi_m1, #15
  345.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4
  346.         MOV     gwi_m1, gwi_m4, LSL #8
  347.         MOVS    gwi_m1, gwi_m1, ASR #24
  348.         ADDMI   gwi_m1, gwi_m1, #15
  349.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;add in 1/16 error for pixel to above left
  350.  
  351.         STR     gwi_lde, [gwi_de, gwi_i, ASL #2]    ;buffer last error
  352.  
  353.         MOV     gwi_m1, gwi_lde, LSL #24
  354.         MOV     gwi_m1, gwi_m1, ASR #24
  355.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3
  356.         ADDMI   gwi_m1, gwi_m1, #15
  357.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4
  358.         MOV     gwi_m1, gwi_lde, LSL #16
  359.         MOV     gwi_m1, gwi_m1, ASR #24
  360.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3
  361.         ADDMI   gwi_m1, gwi_m1, #15
  362.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4
  363.         MOV     gwi_m1, gwi_lde, LSL #8
  364.         MOV     gwi_m1, gwi_m1, ASR #24
  365.         RSBS    gwi_m1, gwi_m1, gwi_m1, ASL #3
  366.         ADDMI   gwi_m1, gwi_m1, #15
  367.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;& add in 7/16 error for pixel to left
  368.  
  369. gwi_xl3_b1
  370.         CMP     gwi_i, #1
  371.         BEQ     gwi_xl3_b2
  372.                         ;if not on far right . . .
  373.         SUB     gwi_m2, gwi_i, #2
  374.         LDR     gwi_m4, [gwi_de, gwi_m2, ASL #2]
  375.         MOV     gwi_m1, gwi_m4, LSL #24
  376.         MOV     gwi_m1, gwi_m1, ASR #24
  377.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #1
  378.         ADDMI   gwi_m1, gwi_m1, #15
  379.         ADD     gwi_r, gwi_r, gwi_m1, ASR #4
  380.         MOV     gwi_m1, gwi_m4, LSL #16
  381.         MOV     gwi_m1, gwi_m1, ASR #24
  382.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #1
  383.         ADDMI   gwi_m1, gwi_m1, #15
  384.         ADD     gwi_g, gwi_g, gwi_m1, ASR #4
  385.         MOV     gwi_m1, gwi_m4, LSL #8
  386.         MOV     gwi_m1, gwi_m1, ASR #24
  387.         ADDS    gwi_m1, gwi_m1, gwi_m1, ASL #1
  388.         ADDMI   gwi_m1, gwi_m1, #15
  389.         ADD     gwi_b, gwi_b, gwi_m1, ASR #4    ;add in 3/16 error for pixel to above right
  390.  
  391. gwi_xl3_b2
  392.  
  393.         gwi_seg1            ;write destination pixel & calc its error
  394.  
  395.         ADD     gwi_dp, gwi_dp, #1
  396.         ADD     gwi_sp, gwi_sp, #4
  397.         SUBS    gwi_i, gwi_i, #1
  398.         BGT     gwi_xloop3        ;continue till all of left to right row processed
  399. gwi_xloop3done
  400.  
  401.         RSB     gwi_m2, gwi_xp, #4
  402.         AND     gwi_m1, gwi_m2, #3
  403.         ADD     gwi_m1, gwi_m1, gwi_xp
  404.         SUB     gwi_m1, gwi_m1, #1
  405.         ADD     gwi_dp, gwi_dp, gwi_m1
  406.     ADD     gwi_sp, gwi_sp, gwi_xp, LSL #2
  407.         SUB     gwi_sp, gwi_sp, #4    ;step dp, sp to start of next right-to-left row
  408.  
  409.         LDR     gwi_m1, gwi_aj
  410.         SUBS    gwi_m1, gwi_m1, #1
  411.         STR     gwi_m1, gwi_aj
  412.         BPL     gwi_yloop        ;& repeat, until all rows done
  413.  
  414. gwi_yloopdone
  415.         ;all done
  416.         LDR     sp, gwi_asp
  417.         LDR     fp, gwi_afp
  418.         LDR     sl, gwi_asl
  419.         LDMEA   fp, {r4-r9, fp, sp, pc}^    ;get out of here!
  420.  
  421.  
  422.  
  423.         END
  424.