home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / program / lynxlib / spec.s < prev    next >
Text File  |  1993-10-23  |  14KB  |  575 lines

  1. ; This source file is part of the LynxLib miscellaneous library by
  2. ; Robert Fischer, and is Copyright 1990 by Robert Fischer.  It costs no
  3. ; money, and you may not make money off of it, but you may redistribute
  4. ; it.  It comes with ABSOLUTELY NO WARRANTY.  See the file LYNXLIB.DOC
  5. ; for more details.
  6. ; To contact the author:
  7. ;     Robert Fischer \\80 Killdeer Rd \\Hamden, CT   06517   USA
  8. ;     (203) 288-9599     fischer-robert@cs.yale.edu
  9.  
  10. ; Routines for loading spectrum pictures.  Handles SPC and SPU formats.
  11. ; Also converts from SPU to PI1 format.
  12. ; Made May 16, 1988
  13.  
  14. ;.include "atari.s"
  15.  
  16. ; Constants
  17.  
  18. scolr_len = 19104    ; length of Spectrum colors
  19. spec_len = 51104    ; length of a Spectrum file
  20. scr_len = 32000        ; length of screen memory in bytes
  21.  
  22. degas_plen = 32        ; length of degas palette
  23. degas_len = degas_plen + scr_len + 2    ; length of degas file
  24. full_len = 63680    ; 320*199 number of pixels in full color picture
  25.  
  26. ; Imports
  27.     .globl    _malloc
  28.     .globl    _free
  29.     .globl    _lmalloc
  30.     .globl    _read_bytes
  31.  
  32.         .text
  33. ; ---------------------------------------------
  34. ;_main::
  35. ;    move.l    #scolr_len, -(sp)    ; Allocate spec_colr
  36. ;    jsr        _lmalloc
  37. ;    move.l    d0, spec_colr
  38. ;    addq.l    #4, sp
  39. ;
  40. ;    move.l    spec_colr, -(sp)
  41. ;    Physbase
  42. ;    move.l    d0, -(sp)
  43. ;    move.l    #jan, -(sp)
  44. ;    jsr        _load_spc
  45. ;    lea        12(sp), sp
  46. ;
  47. ;    move.l    #pal, -(sp)
  48. ;    Physbase
  49. ;    move.l    d0, -(sp)
  50. ;    move.l    spec_colr, -(sp)
  51. ;    move.l    d0, -(sp)
  52. ;    jsr        _spu_to_degas
  53. ;    lea        16(sp), sp
  54. ;
  55. ;    move.l    spec_colr, -(sp)
  56. ;    jsr        _free
  57. ;    addq.l    #4, sp
  58. ;    Pterm0
  59. ;    .bss
  60. ;pal:    ds.w    16
  61. ;    .text
  62.  
  63. ; ---------------------------------------------
  64. ; Call: spu_to_degas(spec_pic, spec_colr, pic_pt, pal_pt)
  65. _spu_to_degas::
  66.     move.l    4(sp), spec_pic
  67.     move.l    8(sp), spec_colr
  68.     move.l    12(sp), pic_pt
  69.     move.l    16(sp), pal_pt
  70.  
  71.     move.l    #full_len*2, -(sp)    ; Allocate full_color
  72.     jsr        _lmalloc
  73.     tst.l    d0                ; Test for error
  74.     beq        ret_nofree1
  75.  
  76.     addq.l    #4, sp
  77.     move.l    d0, full_color
  78.  
  79.     movem.l    d3-d7/a3-a6,-(sp)    ; save registers
  80.  
  81. ; Set up sum square table for use in determining similarity
  82. ; of color vectors
  83. h0:
  84.         lea        color_dist,a0        ; a0 points to this 1911-byte buffer
  85.         move    #$f889,d6
  86.         move    #3822,d7
  87. he:
  88.         move    d6,d0        ; unpack 3 nybbles to d2, d1, d0
  89.         move    d6,d1
  90.         move    d6,d2
  91.         andi    #$f,d0
  92.         andi    #$f0,d1
  93.         andi    #$f00,d2
  94.         lsr        #4,d1
  95.         lsr        #8,d2
  96.  
  97.         cmp        #8,d2    ; if d2 >= 8
  98.         bcs.s    h2e        ; then
  99.         subi    #16,d2    ;   d2 := -(16-d2)
  100. h2e:
  101.         cmp        #8,d1    ; if d1 >= 8
  102.         bcs.s    h3a        ; then
  103.         subi    #16,d1    ;   d1 := -(16-d1)
  104.         addq    #1,d2    ;   d2 := d2 + 1
  105. h3a:
  106.         cmp        #8,d0    ; if d0 >= 8
  107.         bcs.s    h46        ; then
  108.         subi    #16,d0    ;   d0 := -(16-d0)
  109.         addq    #1,d1    ;   d1 := d1 + 1
  110. h46:
  111.         muls    d2,d2    ; d0 := d0^2 + d1^2 + d2^2
  112.         muls    d1,d1
  113.         muls    d0,d0
  114.         add        d2,d0
  115.         add        d1,d0
  116.         move.b    d0,(a0)+
  117.         addq    #1,d6
  118.         dbf        d7,he
  119.  
  120. ; Call subroutine "find_color" once for each pixel in scan lines 1..199
  121. ; Args:  d1 = scan line
  122. ;        d0 = pixel on line
  123. ; Put word result into table "full_color"
  124.  
  125.         move.l    full_color,a5
  126.         move    #$1,d7    ; Scan line 1
  127. hd4:
  128.         clr        d6        ; Pixel 0
  129. hd6:
  130.         move    d6,d0
  131.         move    d7,d1
  132.         bsr        find_color
  133.         move    d0,(a5)+
  134.         addq    #1,d6
  135.         cmp        #320,d6
  136.         bcs.s    hd6
  137.         addq    #1,d7
  138.         cmp        #200,d7
  139.         bcs.s    hd4
  140.  
  141.  
  142. ; Clear frequency table
  143.         lea        frequency,a0
  144.         move    #$ff,d7
  145. hfa:
  146.         clr.l    (a0)+
  147.         dbf        d7,hfa
  148.  
  149. ; Count how many times each of the 512 colors occurs
  150.         lea        frequency,a0
  151.         move.l    full_color,a5
  152.         move    #full_len-1,d7
  153. h110:
  154.         move    (a5)+,d0    ; get color word from next pixel
  155.         move    d0,d1        ; pack together 3 bits for each of 3 nybbles
  156.         andi    #$7,d1
  157.         add        d1,d0
  158.         move    d0,d1
  159.         andi    #$7e,d1
  160.         add        d1,d0
  161.         lsr        #1,d0
  162.         addq    #1,(a0,d0.w)    ; tally color
  163.         dbf        d7,h110
  164.  
  165. ; Choose 16 most frequently used colors for Degas palette
  166.         move.l    pal_pt, a6
  167.         move    #15,d7
  168.         move    #$400,d5        ; dummy index past end of frequency table
  169. h13c:
  170.         lea        frequency,a0
  171.         clr        (a0,d5.w)    ; remove last chosen color
  172.  
  173.         move    #511,d6        ; Scan for most frequent color
  174.         clr        d0            ; d0 = frequency
  175.         move    #-1,d5        ; d5 = color number of most frequent color 
  176. h150:    cmp        (a0)+,d0
  177.         bcc.s    h15a
  178.         move    d6,d5
  179.         move    -2(a0),d0
  180. h15a:    dbf        d6,h150
  181.  
  182.         tst        d5            ; if no remaining color used
  183.         bpl.s    h168        ; then begin
  184.         move    #-1,(a6)    ;    put end flag in Degas palette
  185.         bra.s    h176        ;   done coalescing colors
  186. h168:                        ; end
  187.         neg        d5            ; put complement of color word in Degas palette
  188.         addi    #511,d5        
  189.         move    d5,(a6)+
  190.         add        d5,d5        ; d5 = byte index of color in frequency table
  191.         dbf        d7,h13c
  192. h176:
  193.  
  194. ; Change Degas palette from 9 bit to 12 bit format
  195.         move.l    pal_pt,a0
  196.         move    #15,d7
  197. h180:
  198.         move    (a0),d0
  199.         bmi.s    h19a        ; branch if at end of palette
  200.         move    d0,d1
  201.         andi    #$1f8,d1
  202.         add        d1,d0
  203.         move    d0,d1
  204.         andi    #$380,d1
  205.         add        d1,d0
  206.         move    d0,(a0)+
  207.         dbf        d7,h180
  208. h19a:
  209.  
  210. ; Map all other colors into one of the chosen ones
  211.         lea        distance_base,a4
  212.         move.l    full_color,a5
  213.         move.l    pal_pt,a6
  214.         move    #full_len-1,d7
  215. h1b0:
  216.         move    #15,d6
  217.         move    (a5),d0        ; get color of next pixel
  218.  
  219. ; Find closest Degas color index in d4
  220.         lea        (a6),a0        ; address of next Degas color
  221.         move.b    #255,d2        ; d2 = maximum possible distance
  222. h1bc:
  223.         move    (a0)+,d1    ; get Degas color
  224.         bmi.s    h1d2        ; branch if at end of Degas palette
  225.         sub        d0,d1
  226.         move.b    $0(a4,d1.w),d3    ; d3 = distance squared between colors
  227.         cmp.b    d2,d3        ; if current palette color is closer
  228.         bcc.s    h1ce        ; then
  229.         move.b    d3,d2        ;    d2 = minimum distance so far
  230.         move    d6,d4        ;    d4 = corresponding palette position
  231. h1ce:
  232.         dbf        d6,h1bc
  233. h1d2:
  234.  
  235. ; put new color index into full color array
  236.         neg        d4            ; d4 = 15-d4
  237.         addi    #15,d4
  238.         move    d4,(a5)+
  239.         dbf        d7,h1b0
  240.  
  241. ;-----------------------------------------------
  242. ; Construct Degas file image
  243.  
  244. ; Set any unused Degas palette entries to zero
  245.         move.l    pal_pt,a0
  246.         move    #15,d7
  247. h1e8:
  248.         tst        (a0)+        ; locate end of Degas palette
  249.         dbmi    d7,h1e8
  250.         tst        d7            ; if there are unused colors
  251.         bmi.s    h1fa        ; then 
  252.         subq.l    #2,a0        ;    set them all to zeros
  253. h1f4:
  254.         clr        (a0)+
  255.         dbf        d7,h1f4
  256. h1fa:
  257.  
  258. ; Clear scan line 0 of Degas file image
  259.         move    #39,d7        ; #words-1 in one scan line of one bit plane
  260.         move.l    pic_pt, a0    ; Get ready to mess up picture image
  261. h1fe:
  262.         clr.l    (a0)+
  263.         dbf        d7,h1fe
  264.  
  265. ; Convert scan lines 1..199 of full color raster image to Degas format
  266.         move.l    full_color,a5
  267.         move    #full_len/16-1,d7    ; number of words in each bit plane
  268. h20e:                                ; pack 16 pixels into 4 bit plane words
  269.         move    #15,d6
  270. h212:
  271.         move    (a5)+,d5
  272.         lsr        #1,d5
  273.         roxl    #1,d0
  274.         lsr        #1,d5
  275.         roxl    #1,d1
  276.         lsr        #1,d5
  277.         roxl    #1,d2
  278.         lsr        #1,d5
  279.         roxl    #1,d3
  280.         dbf        d6,h212
  281.  
  282.         move    d0,(a0)+        ; put 4 bit plane words in screen memory
  283.         move    d1,(a0)+
  284.         move    d2,(a0)+
  285.         move    d3,(a0)+
  286.         dbf        d7,h20e
  287.  
  288.         move.l    full_color, -(sp)
  289.         jsr        _free
  290.         addq.l    #4, sp
  291.         move.l    #-1, d0
  292. ret_nofree1:
  293.         movem.l    (sp)+,d3-d7/a3-a6    ; restore registers
  294.         rts
  295. ; ---------------------------------------------
  296. .macro read_bytes handle, count, buf        ; calles _read_bytes
  297.     move.l    \buf,-(sp)
  298.     move.l    \count,-(sp)
  299.     move.l    \handle,-(sp)
  300.     jsr        _read_bytes
  301.     lea        12(sp), sp
  302. .endm
  303. ; ---------------------------------------------
  304. ; Call: load_spu(in, spec_pic, spec_colr)
  305. ;    VFILE *in;
  306. ; loads an SPU file into memory
  307. _load_spu::
  308.     move.l    d7, -(sp)
  309.  
  310. ; Read input file
  311.     move.l    8(sp), d7    ; d7 is file handle of input file
  312.  
  313.  
  314.     move.l    12(sp), d0    ; 12(sp) == spec_pic
  315.     read_bytes    d7, #scr_len, d0
  316.     tst.w    d0
  317.     beq        .quit        ; Branch on error
  318.  
  319.     move.l    16(sp), d0
  320.     read_bytes    d7, #scolr_len, d0    ; 16(sp) == spec_colr
  321.     tst.w    d0
  322.     beq        .quit        ; Branch on error
  323.  
  324.     move.l    (sp)+, d7    ; No error, return normally
  325.     move.l    #-1, d0
  326.     rts
  327.  
  328. .quit:    ; Return a FALSE
  329.     move.l    (sp)+, d7
  330.     move.l    #0, d0
  331.     rts
  332.  
  333. ; ------------------------------------------
  334. ; Subroutine to return color of specified pixel at row d1, column d0
  335. find_color:
  336.         move.l    spec_pic,a0
  337.         move.l    spec_colr,a1
  338.         move    d1,d4        ; d1 := d1*160 (offset into bitmap for row start)
  339.         add        d1,d1
  340.         add        d1,d1
  341.         add        d4,d1
  342.         lsl        #5,d1
  343.         move    d0,d2
  344.         move    d0,d3
  345.         andi    #$f,d2        ; d2 = bit position within bit plane word
  346.         andi    #$fff0,d3    ; d3 = byte offset for current column
  347.         lsr        #1,d3
  348.         add        d3,d1        ; a0 = address of 4 bitplane words
  349.         adda    d1,a0
  350.         neg        d2            ; d1 = mask with 1 at "position" d2
  351.         addi    #15,d2
  352.         clr        d1
  353.         bset    d2,d1
  354.         move    (a0)+,d3    ; extract bit from plane 0
  355.         and        d1,d3
  356.         sne        d2            ; pack it into d2
  357.         ror        #1,d2
  358.         move    (a0)+,d3    ; extract bit from plane 1
  359.         and        d1,d3
  360.         sne        d2            ; pack it into d2
  361.         ror        #1,d2
  362.         move    (a0)+,d3    ; extract bit from plane 2
  363.         and        d1,d3
  364.         sne        d2            ; pack it into d2
  365.         ror        #1,d2
  366.         move    (a0)+,d3    ; extract bit from plane 3
  367.         and        d1,d3
  368.         sne        d2            ; pack it into d2
  369.         rol        #3,d2
  370.         andi    #$f,d2        ; mask out unwanted bits
  371.         move    d2,d3        ; d2 = d3 = color index
  372.         add        d2,d2        ; d2 = 10*d2 + 1
  373.         add        d2,d2
  374.         add        d3,d2
  375.         add        d2,d2
  376.         addq    #1,d2
  377.         btst    #0,d3        ; if odd(d3)
  378.         beq.s    h2f0        ; then
  379.         subq    #6,d2        ;   d2 := d2 - 6
  380. ; Find the word in the color table corresponding to color index in d2
  381. h2f0:
  382.         add        d3,d3        ; initial color index
  383.         cmp        d2,d0        ; when does color change?
  384.         bcs.s    h306        ; branch if pixel is before first color change
  385.         addi    #32,d3        ; adjust color index
  386.         addi    #160,d2        ; move to right half of screen
  387.         cmp        d2,d0
  388.         bcs.s    h306        ; branch if pixel is before second color change
  389.         addi    #32,d3        ; adjust color index
  390. h306:
  391.         move    d4,d0        ; d4 = row number
  392.         move    d0,d2        ; d3 = 96*d4 (row offset into color table)
  393.         add        d0,d0
  394.         add        d2,d0
  395.         lsl        #5,d0
  396.         add        d0,d3
  397.         move    -96(a1,d3.w),d0    ; return color word
  398.         rts
  399. ;-----------------------------------------
  400. ; Calling sequence: load_spc(in, spec_pic, spec_colr)
  401. ;    VFILE *in
  402. _load_spc::
  403.     move.l    4(sp), name
  404.     move.l    8(sp), spec_pic
  405.     move.l    12(sp), spec_colr
  406.     movem.l    d3-d7/a3-a6,-(sp)    ; save registers
  407.  
  408.     ; Read 12 bytes from a file
  409.     move.l    name, d5    ; d5 is the file handle
  410.  
  411.     read_bytes    d5, #$c, #first_twelve
  412.     cmp.w      #$5350, first_twelve        ; Check for valid header (only this for SPC files)
  413.     bne        .ret_nofree        ; 6600 013e
  414.  
  415.     ; Allocate proper memory
  416.     move.l    pic_len, -(sp)    ; Allocate picbuf
  417.     jsr        _lmalloc
  418.     move.l    d0, picbuf
  419.     move.l    color_len, (sp)    ; Allocate colorbuf
  420.     jsr        _lmalloc
  421.     move.l    d0, colorbuf
  422.     addq.l    #4, sp
  423.  
  424.     ; Read the SPC file
  425.     read_bytes    d5, pic_len, picbuf        ; read picture info
  426.     tst.w        d0
  427.     beq            .ret_free
  428.  
  429.     read_bytes    d5, color_len, colorbuf        ; read color info
  430.     tst.w        d0
  431.     beq            .ret_free
  432.  
  433.     move.l    picbuf,a0        ; address of read data
  434.     move.l    spec_pic,a1
  435.     move    #$1,d1
  436.     move    #$7,d7
  437.     lea    $7d00(a1),a2        ; end of 32000 bytes of picture
  438.     lea    8(a2),a3
  439. .hb7a:
  440.     lea    -31840(a2),a1    ; = 160 - 32000
  441.  
  442. .hb7e:    ; get repetition count
  443.         ; positive:  copy count bytes
  444.         ; negative:  repeat next byte count times
  445.     move.b    (a0)+,d6
  446.     ext      d6
  447.     bmi.s    .hb90
  448.  
  449. .hb84:    ; "positive" branch -- copy count bytes into current bitplane
  450.     move.b    (a0)+,(a1)        ; Stick in the next byte
  451.     adda      d1,a1        ; increment output (a1) by 1 half the time, 7 half
  452.     exg        d1,d7
  453.     dbf        d6,.hb84; go around the # of times found out in the previous byte
  454.     bra.s    .hba0        ; skip past "negative" branch
  455.  
  456. .hb90:    ; "negative" branch -- repeat next byte count times into bitplane
  457.     neg      d6
  458.     addq      #1,d6
  459.     move.b    (a0)+,d0
  460. .hb96:
  461.     move.b    d0,(a1)        ; 1280
  462.     adda      d1,a1        ; d2c1
  463.     exg    d1,d7        ; c347
  464.     dbf    d6,.hb96        ; 51ce fff8
  465.  
  466. .hba0:
  467.     cmpa.l    a2,a1        ; have we filled the current bitplane?
  468.     bcs.s    .hb7e        ; no, so continue with next chunk of input file
  469.     bne    .ret_free            ; branch if we've overflowed bitplane
  470.     addq.l    #2,a2        ; set up for next bitplane
  471.     cmpa.l    a3,a2        ; a2=a3 when last bitplane is finished
  472.     bcs.s    .hb7a        ; branch if another bitplane needs doing
  473.  
  474.     move.l    a0,d0        ; check that all of input was used
  475.     addq.l    #1,d0
  476.     bclr    #$0,d0
  477.     sub.l    picbuf,d0
  478.     cmp.l    pic_len,d0
  479.     bne    .ret_free            ; branch if error
  480.  
  481. ; Decode color information
  482.     move.l    colorbuf,a0        ; 41f9 0000 a6f4
  483.     move.l    spec_colr,a1        ; 43f9 0000 ecea
  484.     move.w    #$254,d7        ; 3e3c 0254
  485.     clr      d0        ; 4240
  486. .hbd8:
  487.     move.w    #13,d6        ; set up loop to move 14 words to colortab
  488.     move.w    (a0)+,d1    ; first word is bitmap
  489.     lsr      #1,d1        ; discard rightmost bit
  490.     move.w    d0,(a1)+    ; put 0 into colortab
  491.  
  492. .hbe2:
  493.     lsr.w      #1,d1        ; get next bit of bitmap
  494.     bcc.s    .hbee        ; branch if it is a 0
  495.  
  496.     move.w    (a0)+,(a1)+    ; bit is 1 -- copy next word
  497.     dbf        d6,.hbe2
  498.     bra.s    .hbf4
  499. .hbee:
  500.     move.w    d0,(a1)+    ; bit is 0 -- copy in a zero
  501.     dbf        d6,.hbe2
  502.  
  503. .hbf4:
  504.     move.w    d0,(a1)+    ; put 0 in colortab
  505.     dbf        d7,.hbd8            ; go around again
  506.  
  507.     sub.l    colorbuf,a0    ; check that all data was used
  508.     cmp.l    color_len,a0
  509.  
  510.     move.l    colorbuf, -(sp)    ; Finished sucessfully, return TRUE
  511.     jsr        _free
  512.     move.l    picbuf, (sp)
  513.     jsr        _free
  514.     addq.l    #4, sp
  515.     movem.l    (sp)+,d3-d7/a3-a6    ; restore registers
  516.     move.l    #-1, d0
  517.     rts
  518.  
  519. .ret_free:        ; Error-returning stuff
  520.     move.l    colorbuf, -(sp)
  521.     jsr        _free
  522.     move.l    picbuf, (sp)
  523.     jsr        _free
  524.     addq.l    #4, sp
  525. .ret_nofree:
  526.     movem.l    (sp)+,d3-d7/a3-a6    ; restore registers
  527.     move.l    #0, d0
  528.     rts
  529. ;-----------------------------------------
  530. ;-----------------------------------------
  531.  
  532.         .bss
  533. name:    ds.l    1
  534. ;-----------------------------------------
  535. ; Spectrum file image
  536. ;spec_pic:    ds.b    scr_len                ; Screen image
  537. ;spec_colr:    ds.b    spec_len - scr_len    ; Color words
  538. spec_pic: ds.l    1    ; spec_pic and spec_colr are set up so their memory
  539. spec_colr: ds.l    1    ; is contiguous
  540. ;-----------------------------------------
  541. ; Full color bitmap with one color word per pixel
  542. ;full_color:            ds.w    full_len
  543. full_color:    ds.l 1
  544. ;-----------------------------------------
  545. ; Degas file image
  546. pal_pt:        ds.l    1    ; Pointer to standard format palette
  547. pic_pt:        ds.l    1    ; Pointer to standard format picture image
  548.  
  549. ; Degas file format
  550. ;            ds.b    2                ; resolution
  551. ;            ds.b    degas_plen        ; palette
  552. ;            ds.b    scr_len            ; screen
  553.  
  554. ;-----------------------------------------
  555. ; Frequency of occurrence of colors
  556. frequency:    ds.w    513
  557.  
  558. ; Table of color measures: a**2 + b**2 + c**2
  559. color_dist:    ds.b    1911
  560. distance_base:
  561.         ds.b    1
  562.         ds.b    1911
  563.  
  564. ; Stuff for loading SPC files
  565. first_twelve:    ds.w    2    ; First 12 bytes of a file
  566. pic_len:        ds.l    1
  567. color_len:        ds.l    1
  568.  
  569. picbuf:            ds.b    4
  570. colorbuf:        ds.b    4
  571.  
  572.     .data
  573. healthy:    dc.b    "HEALTHY.SPU"
  574. jan:        dc.b    "JAN.SPC"
  575.