home *** CD-ROM | disk | FTP | other *** search
/ 8bitfiles.net/archives / archives.tar / archives / genie-commodore-file-library / Information / HACKING6D.SFX / hacking6d
Encoding:
Text File  |  1993-09-17  |  34.8 KB  |  705 lines

  1.         Operational diagram of STA $DDFD,X:
  2.  
  3.           #  data  address  R/W  description
  4.          --- ----  -------  ---  ---------------------------------
  5.           1   9D     PCR     R   fetch opcode
  6.           2   FD    PCR+1    R   fetch address low
  7.           3   DC    PCR+2    R   fetch address high, add X to address low
  8.           4   xx    $DD0D    R   read from address, fix high byte of address
  9.           5   ac    $DE0D    W   write to right address
  10.  
  11.  
  12.   With branch instructions:
  13.  
  14.         ; acknowledge interrupts to CIA 2
  15.                 LDA #$00  ; clear N flag
  16.                 JMP $DD0A
  17.         DD0A    BPL $DC9D ; branch
  18.         DC9D    BRK       ; return
  19.  
  20.         You need the following preparations to initialize the CIA registers:
  21.  
  22.                 LDA #$91  ; argument of BPL
  23.                 STA $DD0B
  24.                 LDA #$10  ; BPL
  25.                 STA $DD0A
  26.                 STA $DD08 ; load the ToD values from the latches
  27.                 LDA $DD0B ; jam the ToD display
  28.                 LDA #$7F
  29.                 STA $DC0D ; assure that $DC0D is $00
  30.  
  31.         Operational diagram of BPL $DC9D:
  32.  
  33.           #  data  address  R/W  description
  34.          --- ----  -------  ---  ---------------------------------
  35.           1   10    $DD0A    R   fetch opcode
  36.           2   91    $DD0B    R   fetch argument
  37.           3   xx    $DD0C    R   fetch opcode, add argument to PCL
  38.           4   yy    $DD9D    R   fetch opcode, fix PCH
  39.         ( 5   00    $DC9D    R   fetch opcode )
  40.  
  41.  
  42.         ; acknowledge interrupts to CIA 1
  43.                 LDA #$00  ; clear N flag
  44.                 JMP $DCFA
  45.         DCFA    BPL $DD0D
  46.         DD0D    BRK
  47.  
  48.         ; Again you need to set the ToD registers of CIA 1 and the
  49.         ; Interrupt Control Register of CIA 2 first.
  50.  
  51.         Operational diagram of BPL $DD0D:
  52.  
  53.           #  data  address  R/W  description
  54.          --- ----  -------  ---  ---------------------------------
  55.           1   10    $DCFA    R   fetch opcode
  56.           2   11    $DCFB    R   fetch argument
  57.           3   xx    $DCFC    R   fetch opcode, add argument to PCL
  58.           4   yy    $DC0D    R   fetch opcode, fix PCH
  59.         ( 5   00    $DD0D    R   fetch opcode )
  60.  
  61.  
  62.         ; acknowledge interrupts to CIA 2 automagically
  63.                 ; preparations
  64.                 LDA #$7F
  65.                 STA $DD0D       ; disable CIA 2's all interrupt sources
  66.                 LDA $DD0E
  67.                 AND #$BE        ; ensure that $DD0C remains constant
  68.                 STA $DD0E       ; and stop the timer
  69.                 LDA #$FD
  70.                 STA $DD0C       ; parameter of BPL
  71.                 LDA #$10
  72.                 STA $DD0B       ; BPL
  73.                 LDA #$40
  74.                 STA $DD0A       ; RTI/parameter of LSR
  75.                 LDA #$46
  76.                 STA $DD09       ; LSR
  77.                 STA $DD08       ; load the ToD values from the latches
  78.                 LDA $DD0B       ; jam the ToD display
  79.                 LDA #$09
  80.                 STA $0318
  81.                 LDA #$DD
  82.                 STA $0319       ; change NMI vector to $DD09
  83.                 LDA #$FF        ; Try changing this instruction's operand
  84.                 STA $DD05       ; (see comment below).
  85.                 LDA #$FF
  86.                 STA $DD04       ; set interrupt frequency to 1/65536 cycles
  87.                 LDA $DD0E
  88.                 AND #$80
  89.                 ORA #$11
  90.                 LDX #$81
  91.                 STX $DD0D       ; enable timer interrupt
  92.                 STA $DD0E       ; start timer
  93.  
  94.                 LDA #$00        ; To see that the interrupts really occur,
  95.                 STA $D011       ; use something like this and see how
  96.         LOOP    DEC $D020       ; changing the byte loaded to $DD05 from
  97.                 BNE LOOP        ; #$FF to #$0F changes the image.
  98.  
  99.         When an NMI occurs, the processor jumps to Kernal code, which jumps to
  100.         ($0318), which points to the following routine:
  101.  
  102.         DD09    LSR $40         ; clear N flag
  103.                 BPL $DD0A       ; Note: $DD0A contains RTI.
  104.  
  105.         Operational diagram of BPL $DD0A:
  106.  
  107.           #  data  address  R/W  description
  108.          --- ----  -------  ---  ---------------------------------
  109.           1   10    $DD0B    R   fetch opcode
  110.           2   11    $DD0C    R   fetch argument
  111.           3   xx    $DD0D    R   fetch opcode, add argument to PCL
  112.           4   40    $DD0A    R   fetch opcode, (fix PCH)
  113.  
  114.  
  115.   With RTI:
  116.  
  117.         ; the fastest possible interrupt handler in the 6500 family
  118.                 ; preparations
  119.                 SEI
  120.                 LDA $01         ; disable ROM and enable I/O
  121.                 AND #$FD
  122.                 ORA #$05
  123.                 STA $01
  124.                 LDA #$7F
  125.                 STA $DD0D       ; disable CIA 2's all interrupt sources
  126.                 LDA $DD0E
  127.                 AND #$BE        ; ensure that $DD0C remains constant
  128.                 STA $DD0E       ; and stop the timer
  129.                 LDA #$40
  130.                 STA $DD0C       ; store RTI to $DD0C
  131.                 LDA #$0C
  132.                 STA $FFFA
  133.                 LDA #$DD
  134.                 STA $FFFB       ; change NMI vector to $DD0C
  135.                 LDA #$FF        ; Try changing this instruction's operand
  136.                 STA $DD05       ; (see comment below).
  137.                 LDA #$FF
  138.                 STA $DD04       ; set interrupt frequency to 1/65536 cycles
  139.                 LDA $DD0E
  140.                 AND #$80
  141.                 ORA #$11
  142.                 LDX #$81
  143.                 STX $DD0D       ; enable timer interrupt
  144.                 STA $DD0E       ; start timer
  145.  
  146.                 LDA #$00        ; To see that the interrupts really occur,
  147.                 STA $D011       ; use something like this and see how
  148.         LOOP    DEC $D020       ; changing the byte loaded to $DD05 from
  149.                 BNE LOOP        ; #$FF to #$0F changes the image.
  150.  
  151.         When an NMI occurs, the processor jumps to Kernal code, which jumps to
  152.         ($0318), which points to the following routine:
  153.  
  154.         DD0C    RTI
  155.  
  156.         How on earth can this clear the interrupts? Remember, the processor
  157.         always fetches two successive bytes for each instruction.
  158.  
  159.         A little more practical version of this is redirecting the NMI (or IRQ)
  160.         to your own routine, whose last instruction is JMP $DD0C or JMP $DC0C.
  161.         If you want to confuse more, change the 0 in the address to a
  162.         hexadecimal digit different from the one you used when writing the RTI.
  163.  
  164.         Or you can combine the latter two methods:
  165.  
  166.         DD09    LSR $xx         ; xx is any appropriate BCD value 00-59.
  167.                 BPL $DCFC
  168.         DCFC    RTI
  169.  
  170.         This example acknowledges interrupts to both CIAs.
  171.  
  172.  
  173.    If you want to confuse the examiners of your code, you can use any of
  174.  these techniques. Although these examples use no undefined opcodes, they do
  175.  not run correctly on CMOS processors. However, the RTI example should run on
  176.  65C02 and 65C816, and the latter branch instruction example might work as
  177.  well.
  178.  
  179.    The RMW instruction method has been used in some demos, others were
  180.  developed by Marko M"akel"a. His favourite is the automagical RTI method,
  181.  although it does not have any practical applications, except for some
  182.  time dependent data decryption routines for very complicated copy protections.
  183.  
  184.  
  185.  
  186.                 MAKING USE OF THE I/O REGISTERS
  187.  
  188.    If you are making a resident program and want to make as invisible to the
  189.  system as possible, probably the best method is keeping most of your code
  190.  under the I/O area (in the RAM at $D000-$DFFF). You need only a short routine
  191.  in the normally visible RAM that pushes the current value of the processor's
  192.  I/O register $01 on stack, switches I/O and ROMs out and jumps to this area.
  193.  Returning from the $D000-$DFFF area is easy even without any routine in the
  194.  normally visible RAM area. Just write a RTS to an I/O register and return
  195.  through it.
  196.  
  197.    But what if your program needs to use I/O? And how can you write the RTS
  198.  to an I/O register while the I/O area is switched off? You need a swap area
  199.  for your program in normally visible memory. The first thing your routine at
  200.  $D000-$DFFF does is copying the I/O routines (or the whole program) to
  201.  normally visible memory, swapping the bytes. For instance, if your I/O
  202.  routines are initially at $D200-$D3FF, exchange the bytes at $D200-$D3FF
  203.  with the contents of $C000-$C1FF. Now you can call the I/O routines from
  204.  your routine at $D000-$DFFF, and the I/O routines can switch the I/O area
  205.  temporarily on to access the I/O circuitry. And right before exiting your
  206.  program at $D000-$DFFF swaps the old contents of that I/O routine area in,
  207.  e.g. exchanges the memory areas $D200-$D3FF and $C000-$C1FF again.
  208.  
  209.    What I/O registers can you use for the RTS? There are two alternatives:
  210.  8-bit VIC sprite registers or CIA serial port register. The CIA register is
  211.  usually better, as changing the VIC registers might change the screen layout.
  212.  However, also the SP register has some drawbacks: If the machine's CNT1 and
  213.  CNT2 lines are connected to a frequency source, you must stop either CIA's
  214.  Timer A to use the SP register method. Normally the 1st CIA's Timer A is the
  215.  main hardware interrupt source. And if you use the Kernal's RS232, you cannot
  216.  stop the 2nd CIA's Timer A either. Also, if you don't want to lose any CIA
  217.  interrupts, remember that the RTS at SP register causes also the Interrupt
  218.  Control Register to be read.
  219.  
  220.    Also keep in mind that the user could press RESTORE while the Kernal ROM
  221.  and I/O areas are disabled. You could write your own NMI handler (using
  222.  the NMI vector at $FFFA), but a fast loader that uses very tight timing
  223.  would still stop working if the user pressed RESTORE in wrong time. So, to
  224.  make a robust program, you have to disable NMI interrupts. But how is this
  225.  possible? They are Non-Maskable after all. The NMI interrupt is
  226.  edge-sensitive, the processor jumps to NMI handler only when the -NMI line
  227.  drops from +5V to ground. Just cause a NMI with CIA2's timer, but don't
  228.  read the Interrupt Control register. If you need to read $DD0D in your
  229.  program, you must add a NMI handler just in case the user presses RESTORE.
  230.  And don't forget to raise the -NMI line upon exiting the program. This can
  231.  be done automatically by the latter two of the three following examples.
  232.  
  233.  
  234.         ; Returning via VIC sprite 7 X coordinate register
  235.  
  236.         Initialization:   ; This is executed when I/O is switched on
  237.                 LDA #$60
  238.                 STA $D015 ; Write RTS to VIC register $15.
  239.  
  240.         Exiting:          ; NOTE: This procedure must start at VIC register
  241.                           ; $12. You have multiple alternatives, as the VIC
  242.                           ; appears in memory at $D000+$40*n, where $0<=n<=$F.
  243.  
  244.                 PLA       ; Pull the saved 6510 I/O register state from stack
  245.                 STA $01   ; Restore original memory bank configuration
  246.                           ; Now the processor fetches the RTS command from the
  247.                           ; VIC register $15.
  248.  
  249.  
  250.         ; Returning via CIA 2's SP register (assuming that CNT2 is stable)
  251.  
  252.         Initialization:   ; This is executed when I/O is switched on
  253.                 LDA $DD0E ; CIA 2's Control Register A
  254.                 AND #$BF  ; Set Serial Port to input
  255.                 STA $DD0E ; (make the SP register to act as a memory place)
  256.                 LDA #$60
  257.                 STA $DD0C ; Write RTS to CIA 2 register $C.
  258.  
  259.         Exiting:          ; NOTE: This procedure must start at CIA 2 register
  260.                           ; $9. As the CIA 2 appears in memory at $DD00+$10*n,
  261.                           ; where 0<=n<=$F, you have sixteen alternatives.
  262.                 PLA
  263.                 STA $01   ; Restore original memory bank configuration
  264.                           ; Now the processor fetches the RTS command from
  265.                           ; the CIA 2 register $C.
  266.  
  267.  
  268.         ; Returning via CIA 2's SP register, stopping the Timer A
  269.         ; and forcing SP2 and CNT2 to output
  270.  
  271.         Initialization:   ; This is executed when I/O is switched on
  272.                 LDA $DD0E ; CIA 2's Control Register A
  273.                 AND #$FE  ; Stop Timer A
  274.                 ORA #$40  ; Set Serial Port to output
  275.                 STA $DD0E ; (make the SP register to act as a memory place)
  276.                 LDA #$60
  277.                 STA $DD0C ; Write RTS to CIA register $C.
  278.  
  279.         Exiting:          ; NOTE: This procedure must start at CIA 2 register
  280.                           ; $9. As the CIA 2 appears in memory at $DD00+$10*n,
  281.                           ; where, 0<=n<=$F, you have sixteen alternatives.
  282.                 PLA
  283.                 STA $01   ; Restore original memory bank configuration
  284.                           ; Now the processor fetches the RTS command from
  285.                           ; the CIA 2 register $C.
  286.  
  287.         
  288.    For instance, if you want to make a highly compatible fast loader, make
  289.  the ILOAD vector ($0330) point to the beginning of the stack area. Remember
  290.  that the BASIC interpreter uses the first bytes of stack while converting
  291.  numbers to text. A good address is $0120. Robust programs practically never
  292.  use so much stack that it could corrupt this routine. Usually only crunched
  293.  programs (demos and alike) use all stack in the decompression phase. They
  294.  also make use of the $D000-$DFFF area.
  295.  
  296.    This stack routine will jump to your routine at $D000-$DFFF, as described
  297.  above. For performance's sake, copy the whole byte transfer loop to the swap
  298.  area, e.g. $C000-$C1FF, and call that subroutine after doing the preliminary
  299.  work. But what about files that load over $C000-$C1FF? Wouldn't that destroy
  300.  the transfer loop and jam the machine? Not necessarily. If you copy those
  301.  bytes to your swap area at $D000-$DFFF, they will be loaded properly, as
  302.  your program restores the original $C000-$C1FF area.
  303.  
  304.    If you want to make your program user-friendly, put a vector initialization
  305.  routine to the stack area as well, so that the user can restore the fast
  306.  loader by issuing a SYS command, rather than loading it each time he has
  307.  pressed STOP & RESTORE or RESET.
  308.  
  309.  
  310.  
  311.                 NOTES
  312.  
  313.  See MCS 6500 Microcomputer Family Programming Manual for more information.
  314.  There is also a table showing functional description and timing for complete
  315.  6510 instruction set on C=Hacking magazine issue 1/92 (available via FTP at
  316.  ccosun.caltech.edu:/pub/rknop/hacking.mag/ and
  317.  nic.funet.fi:/pub/cbm/c=hacking/).
  318.  
  319.  
  320.  References:
  321.   C64 Memory Maps       C64 Programmer's Reference Guide pp. 262-267
  322.   6510 Block Diagram    C64 Programmer's Reference Guide  p. 404
  323.   Instruction Set       C64 Programmer's Reference Guide pp. 416-417
  324.                         C=Hacking Volume 1, issue #1, 1/92
  325.                         C=Lehti magazine 4/87
  326. =============================================================================
  327. A Heavy-Duty Power Supply for the C-64
  328. by John C. Andrews (no email address)
  329.  
  330.   As a Commodore User for the last 4 plus years, I am aware of the many
  331.   articles and letters in the press that have bemoaned the burn-out
  332.   problem of the C-64 power supply. When our Club BBS added a one meg
  333.   drive and stayed on around the clock, the need for heavy-duty power
  334.   supply became very apparent.... Three power supplies went in 3
  335.   successive days!
  336.  
  337.   Part of the problem was my ignoring the seasons. You see during the
  338.   winter I had set the power supply between the window and the screen,
  339.   Yes, outside! With the advent of Spring... well, you get the picture.
  340.  
  341.   The turn-around time forgetting a new commerical supply was not in the
  342.   best interest of the BBS and its members. Therefore, taking power
  343.   supply inhand, I proceeded to cut one open on my shop bandsaw. I do
  344.   not suggest that you do this. The parts are FIRMLY and COMPLETELY
  345.   encased in a hard plastic potting compound. The purpose of this is not
  346.   to make the item difficult to repair, but to make the entire unit
  347.   conductive to the heat generated inside. I doubt the wisedom of
  348.   potting the fuse as well. However, CBM was probably thinking of the
  349.   number of little fingers that could fit into an accessable fuse
  350.   holder. if you want the punch line it is: the final circuit board and
  351.   its componets are about the size of a box of matches. This includes
  352.   the built-in metal heat sink.
  353.  
  354.   From these minscule innards I traced out the circuit and increased the
  355.   size of ALL components.
  356.  
  357.   The handiest source of electronic parts is, of course, Radio Shack.
  358.   All but one part can be purchased there.
  359.  
  360.         212-1013        Capacitor, 35V, 4700 mF
  361.         212-1022        Capacitor, 35V, 10 uF
  362.         273-1515        Transformer, 2 Amp, 9-0-9 VAC
  363.         276-1184        Rectifier
  364.  
  365.         270- 742        Fuse Block
  366.         270-1275        Fuses
  367.  
  368.   Note that there are only five parts. The rest are fuses, fuse blocks,
  369.   heat sinks, wire and misc. hardware. Note also that I have not listed
  370.   any plugs and cords. This because you can clip the cords off of both
  371.   sides of your defunct power supply. This will save you the hassle of
  372.   wriing the DIN power plug correctly:
  373.  
  374.         DIN PIN OUT                   COLOR
  375.           pin 6         9VAC            black
  376.           pin 7         9VAC            black
  377.           pin 5         +5 Volts        blue
  378.           pin 1,2,3     shield, gnd     orange
  379.  
  380.   The part that you can NOT get at Radio Shack is the power regulator.
  381.   This part will have to be scrounged up from some local, big
  382.   electronics supply house:
  383.  
  384.         SK 9067    5 volt voltage regulator, 3+ amps. (I prefer the 5 amp.)
  385.  
  386.   Radio Shack does carry regulators, but their capacity is no larger
  387.   than that with which you started.
  388.  
  389.   The Heat sinks, (yes, more than one!) are the key to the success of
  390.   this project. The ones I used came from my Model Railroading days.
  391.   Sorry to say, I did just ahve them 'lying about'. The heat sinks that
  392.   I priced at the local electronics supply were more costly than the
  393.   other parts. The worst case situation is that you may need to drill
  394.   out a couple pieces of aluminum sheet. Try for 12 x 12, and bend them
  395.   into square bottomed U-shapes to save room. heat sinks should not
  396.   touch, or be electronically grounded to each other. You can also mount
  397.   them on stand-offs from your chassis for total air circulation.
  398.  
  399.   The Radio Shack transformer is rated at only 2 amps. If you can not
  400.   find one with a higher rating elsewhere, it is possible to hook two in
  401.   parallel to get a 4 ampere output. This si tricky, as it can be done
  402.   either right or wrong!
  403.  
  404.   Here is how to do it the right way:
  405.     Tape off one yellow secondary lead on each transformer. With tape
  406.     mark the four remaining secondary leads and letter them A and B on
  407.     one transformer, C and D onthe other. Hook up the black primary
  408.     leads to a plug to your 120 wall outlet:
  409.  
  410.                                     |-------------
  411.    Note: *'s - indicate connections |            3 ||
  412.          +'s - indicate skip overs  |            3 || (Transformer)
  413.                                     |            3 ||
  414.                                     |            3 ||
  415.                                     |   ----------
  416.                                     |   |
  417.           +--\  /-------------------*---+---------
  418.         --|120|/                        |        3 ||
  419.         --|Vlt|             ____        |        3 ||
  420.          -|Plg|------------|FUSE|-------*        3 ||
  421.           +--/              ----        |        3 || (Transformer)
  422.                                         |---------
  423.  
  424.     This would now be a good time to install a fuse in your 120 VAC
  425.     line. Now before plugging this into the wall, tie two of the
  426.     scondary leads (one from EACH transformer) together.
  427.  
  428.     Something like this: A--Xfmr--B+C--Xfmr--D
  429.  
  430.     Plug in your 120V side. Now using a VOM meter, measure the voltage
  431.     between A and D.
  432.       If the meter reads 18 volts, then:
  433.         1. unplug from the 120.
  434.         2. tie A and C together. tie B and D together.
  435.         3. your 2 transformers will now give you 9 volts at 4 amps.
  436.       If the meter reads 0 volts, then:
  437.         1. unplug from the 120.
  438.         2. tie A and D together. Tie B and C together.
  439.         3. your 2 transformers will now give you 9 volts at 4 amps.
  440.  
  441.   Below is the file corresponding to the full schematic of the power
  442.   supply. [Ed's note: in GeoPaint format, converted, then uuencoded]. As
  443.   you can see in the picture, I used only one transformer. Because it
  444.   got hot, I epoxied a small heat sink to it. While this solved the heat
  445.   problem, it did not increase the capacity of the total power supply.
  446.  
  447.   Note that I used fuses on all lines.
  448.  
  449. -----------------------------------------------------------------------------
  450. begin 700 schematic.
  451. M@PD,<V-H96UA=&ECH*"@H*"@H`D&`0=8!P8-,Q(`4%)'(&9O<FUA='1E9"!'
  452. M14]3(&9I;&4@5C$N,``CF````"```.``0X(``$5P<V]N($U8+3@P`*"@H*``
  453. MUH>-UH?(F!AE`H4"D`+F`V"@H*"@H*"@H`@%`0A6!`<,`"````"""@A30TA%
  454. M34%424.@H*"@H*"@````````````$P!"3$%35$52)U,@0T].5D525$52(%8R
  455. M+C4$6`<X"````@RP#0T].5D525*"@H*"@H*"@H"P2``99`Q$&`10`````
  456. M```````````````````````````````````````#%;_____```.@``6?__F5
  457. M55F:JJF555F:JJF555F:JJF555F:JJF?__F@``7```/___\```````-__[:`
  458. M`/Y__[R#!P$``/__``!086EN="!);6%G92!6,2XQ````````````````````
  459. M````````````9V5O4&%I;G0@("`@5C(N,``````@*$')!M`"J1*-(D"I`(TG
  460. M0"#]/Y`%J0"-)T`@#!\@2$&I`(VL7ZD`A1&I!X40J3^%%ZGQA1:I7X4-J:R%
  461. M#*!`J0X@3S&B_Z4"R0+P)LG_T`8@-$&X4*G)!M`-H$.I)B!/,2"APKA0F*VL
  462. M7_`&(+T\(($\8%!A:0#_"@#_`3P!>`)+`EL"/P&R`38!B@%Z`38!C@(G`/\`
  463. M_P#_`/\`_P#_`/\`_P#_`/\`_P#_`/\`_P#_`/\`_P#_`/\`_P#_`/\`_P#_
  464. M`/\`_P#_`/\`_P#_`/\`````````````````````````````````````````
  465. M````````````````````````````````````````````````````````````
  466. M````````````````````````````````````````````````````````````
  467. M`````````````````````````````````````````````````````````/\`
  468. M_P#_`/\`_P#_`/\`E0`"/R!%````````_P"%``,0_Q!$````````_P"&``+X
  469. M"/\`_P"B`/^_H;\``"`@,!@,_PP810``````_P``"!`0,&#@_\#`0P``````
  470. M_P``A1`#\!`0H`"("/\`_P#*``(@/X8``>#_`+```3"'(*@``F`PAA"8`(@0
  471. MH`"("/\`_P"B`/^_H;\`(*@`B!"8`(00!!\0$!!$`````/\```"$"`3X"`@(
  472. M_P#_`,(``O__A@`"X."&((L`#0$!`0($@("`#A$0$!.%``-98D.%``.,4MZ%
  473. M``/@D)"0``$'0P````````#_AP`!@,\`B""H_P#.``H#1$0HA0`##03$A0`#
  474. M@("9AP`!!*``B""H`(@0H`"("/\`_P#_`.,`'2D1$1$0````).0$),0```"E
  475. MI*2DF`````2HJ%!0HP"&(`)@8*(``1^$``P!$!#_````/-,``/B$``&`F`"(
  476. M"/\`_P"B`/^_H;\``+```3"'(*@``F`PAA"8`(@0H`"("/\`_P"B`/^_H;\`
  477. M(*@`B!"8`(00!!\0$!!$`````/\```"$"`3X"`@(_P#_`,(``O__A@`"X."&
  478. M((L`#0$!`0($@("`#A$0$!.%``-98D.%``.,4MZ%``/@D)"0``$'0P``````
  479. M``#_AP`!@,\`B""HS@`""`B&``(*BH8``@D!O@`"#PA#````````_P"&``R`
  480. M8``/##`P#`PP`/^%``,\`/^%``/``/^%``$$1`#_`````````P#_`84`"L#_
  481. M@,#@8"`@`/^'``'PAA"0``(&"(8`A!`,$A(2$V`0```\!(3.A``$<8J*BH0`
  482. M#,`@("<````X*"!P((<(`0^'``&`_P#_`,<``S\@((8``N`<B``1!`4%`@("
  483. M``"34E(B(B(``)N$20E(``"8)#P@))BR`(@(D0`Q`0$```$!`&"%A65EA85E
  484. M,`P,,#`,##`B(CPB(B(\`$!,4DY24DX`!&25AH:59```@(0``8"A`(@@A0`+
  485. M`0(*!!`0.$2"`0"`A@`"@$"0`(@0`H2$A@`"BG&&``(JRH8`#*"@`0$#`P4%
  486. M,,```(0%"&`8!`3R"@D1_P#_`)H`_[^AOP``````````````````````````
  487. M````````````````````````````````````````````````````````````
  488. M````````````````````````````````````````````````````````````
  489. M````````````````````````````````````````````````````````````
  490. M``````````````````````````````````"<``(!`T(```````#__P(``(0@
  491. M!N#@("`#`88`"/^`0"`0"`0$2O\``````````?B8`!<!`0```0$`986%966%
  492. MA64P#`\P,`P,,$8``/\```````,``/Z%`H@``3^'`!3X"P0"`0```(#G@(`!
  493. M@D0X(+]`@$(``````/\``(0``A#_AA!#`/\````````8!?P$`@(!`0"-B8G9
  494. M<7$`P.$A(2(2#`08_P#_`*T``@$#0@```````/__"P```"`@(.#@("`@B``$
  495. M`@$!`8@`'("`@$```'E$1'A$1```@("8I9VE```(",DJ#`S)`#<!`0```0$`
  496. M986%966%A64P#`PP,`P,,`!$"D0H*1$1$0`-!,0DY`0D`("`F:6DI*0````$
  497. M!*BH4)```0-#`````````/^'``'PAQ"8`(@0CP`!#(<``0B(``(X#X8(`F"`
  498. M_P#_`*``_[^AOP``````````````````````````````````````````````
  499. M````````````````````````````````````````````````````````````
  500. M````````````````````````````````````````````````````````````
  501. M`````````````````````````````````````````````````````+``B""0
  502. M`(5`%7]`0$1X````_P``I9P```#_```JR4(```#_``````<```#_```'A`0;
  503. M_`0$_P`],3TQ,`#_`+.VL['G`/\`O#`\L#P`A8`#_X"`0@``````_P``-0`!
  504. M`0``_P``986%8&"````P#`PP/P```!````#_````Q````/\```"8````_P``
  505. M`%````#_AP`$X"`@(*@`B!"8`(00!!\0$!"$`!3_`````@$!`/\``0$("`B(
  506. MCX@("(0`!/\```"$"`3X"`@(_P#_`,(``O__A@`"X."&((L`#0$!`0($@("`
  507. M#A$0$!.%``-98D.%``.,4MZ%``/@D)"0``$'0P````````H`_X<``8#/`(@@
  508. MJ`"($)@`B!"(``L"#```GJ&AH0@("(D`!&"PD("("/\`_P"B`/^_H;\```$,
  509. MAP`!"(@``C@/A@@"8(#_`/\`H`#_OZ&_````````````````````````````
  510. M````````````````````````````````````````````````````````````
  511. M````````````````````````````````````````````````````````````
  512. M````````````````````````````````````````````````````````````
  513. M````````````L`"(((4`)@$"'`0($"!`_P``$1$.``#_``!"0D$``/\``!!2
  514. MC```_P``D)"04```_P``````#0``_P``("`P&`S_#!A%``````#_```($!`P
  515. M8.#_P,!#``````#_``"%$`/P$!"(``2AH:&>A``)`2(B(AP```#`A(`#````
  516. MB`C_`/\`R@`"(#^&``'@_P"P``,P(`"%(*@``F`PAA"8`(@0H`"("/\`_P"B
  517. M`/^_H;\`_P`!`0@("(B/B`@(A``$_P```(0(!/@("`C_`/\`P@`"__^&``+@
  518. MX(8@BP`-`0$!`@2`@(`.$1`0$X4``UEB0X4``XQ2WH4``^"0D)#_`.D`B""H
  519. M`(@0F``*B!"@`(@(_P#_`/\`_P"$`(@@J`"($)@`B!"@`(@(_P#_`*(`_[^A
  520. MOP``#0``_P``("`P&`S_#!A%``````#_```($!`P8.#_P,!#``````#_``"%
  521. M$`/P$!"(``2AH:&>A``)`2(B(AP```#`A(`#````B`C_`/\`R@`"(#^&``'@
  522. M_P"P``,P(`"%(*@``F`PAA"8`(@0H`"("/\`_P"B`/^_H;\`_P`!`0@("(B/
  523. MB`@(A``$_P```(0(!/@("`C_`/\`P@`"__^&``+@X(8@BP`-`0$!`@2`@(`.
  524. M$1`0$X4``UEB0X4``XQ2WH4``^"0D)#_`.D`B""H`(@0F`"($*``B`C_`/\`
  525. M_P#S``$#AP(8_P``>V-[8V'_``!G;&9CSO\``'A@>&!XB("8`(@0B`"(`1G_
  526. M```],3TQ,/\``+.VL['G_P``O#`\L#S`AT")``,?$!"$$Q@(_P``VQO;&P#_
  527. M```[8S,;`/P$!,0$Q`3_`/\`D@#_OZ&_`(8``>#_`+```S`@`(4@J``"8#"&
  528. M$)@`B!"@`(@(_P#_`*(`_[^AOP#_``$!"`@(B(^("`B$``3_````A`@$^`@(
  529. M"/\`_P#"``+__X8``N#@AB"+``T!`0$"!("`@`X1$!`3A0`#66)#A0`#C%+>
  530. MA0`#X)"0D/\`V0`#`@(#0@``````"@``_X40`P``_X4``X"`@)T`B!"(``,!
  531. M`0%"`````````/^%"`,``/^%``-`0,"-``03$!`?A``$#@``_X0$!',``/^$
  532. M``3$!`3\_P#_`/\`]P"($*@`B!"8`(@(H`"(!/\`_P"B`/^_H;\`!,0$Q`3_
  533. M`/\`D@#_OZ&_`(8``>#_`+```S`@`(4@J``"8#"&$)@`B!"@`(@(_P#_`*(`
  534. M_[^AOP#_``$!"`@(B(^("`B$``3_````A`@$^`@("/\`_P#"``+__X8``N#@
  535. MAB"+``T!`0$"!("`@`X1$!`3A0`#66)#A0`#C%+>A0`#X)"0D/\`Z0"($*@`
  536. MB!"8`(@(H`"(!/\`_P#_`/\`A`"($*@`B!"8`(@(H`"(!/\`_P"B`/^_H;\`
  537. M_X4``T!`P(T`!!,0$!^$``0.``#_A`0$<P``_X0`!,0$!/S_`/\`_P#W`(@0
  538. MJ`"($)@`B`B@`(@$_P#_`*(`_[^AOP`$Q`3$!/\`_P"2`/^_H;\`A@`!X/\`
  539. ML``#,"``A2"H``)@,(80F`"($*``B`C_`/\`H@#_OZ&_`/\``0$("`B(CX@(
  540. M"(0`!/\```"$"`3X"`@(_P#_`,(``O__A@`"X."&((L`#0$!`0($@("`#A$0
  541. M$!.%``-98D.%``.,4MZ%``/@D)"0_P#I`(@0J`"($)@`B`B@``J(!/\`_P#_
  542. M`/@``P,$!(4``X%!0(00!``1$:*%``,.$9"4``0'"`@(A``,`H*!@1`0$``B
  543. M(D5%A``$'"(@((<`"P,````?$!`>P0@(B0`-<HN#@IH````N*2BHJ(4`$X"`
  544. M@`````$!!P$!`!\0$![!`1'_`/\`H@#_OZ&_`/\`L``#,"``A2"H``)@,(80
  545. MF`"($*``B`C_`/\`H@#_OZ&_`/\``0$("`B(CX@("(0`!/\```"$"`3X"`@(
  546. M_P#_`,(``O__A@`"X."&((L`#0$!`0($@("`#A$0$!.%``-98D.%``.,4MZ%
  547. M``/@D)"0_P#9``P$`P```P```$#`0("$``VBI$=$1````)!0T%%.DP`*!P`!
  548. M!@````^!@(4`$1!(CXB(`````Z"@HIP```#@A@`C`P(!$0X```#$(```("!`
  549. M````BHIR````0<)H:2X```#!(("%``+P((0`#`<$!`0.````B$!;2H0`!`$!
  550. M@4&$``3P``#@_P#_`/\`XP`3!P0$!`<$!`2(0%M*B@H*"@``@81!"4!@@`#@
  551. M$!`0X)``"P@("`\("`@`@+>4A!0#````A8`:`"`@0$"`@(```@(#`@("```M
  552. M)<4%!04``,"%(!X``$!`0$%"2P@0($"```'D!`A`X!`0$.````<$!`2$``2*
  553. >"@H*A``$0$`*04"$``00$!#@_P#_`)8`_[^AOP`*
  554. `
  555. end
  556.  
  557. =============================================================================
  558. LZW Compression
  559. by Bill Lucier (Blucier@ersys.edmonton.ab.ca, b.lucier1 on Genie)
  560.  
  561. LZW is perhaps the most widely used form of data compression today. It
  562. is simple to implement and achieves very decent compression at a fairly
  563. quick pace. LZW is used in PKZIP (shrink),PKARC (crunch), gifs,V.42bis
  564. and unix's compress. This article will attempt to explain how the
  565. compression works with a short example and 6502 source code in Buddy
  566. format.
  567.  
  568. Originally named lz78, it was invented by Jacob Ziv and Abraham Lempel
  569. in 1978 , it was later modified by Terry Welch to its present format.
  570. The patent for the LZW compression method is presently held by Unisys.
  571.  
  572. LZW compresses data by taking phrases and compressing them into codes.
  573. The size of the codes could vary from 9 bits to 16 bits. Although for
  574. this implementation we will be using only 12 bits. As byte are read in
  575. from a file they are added to a dictionary. For a 12-bit implementation
  576. a dictionary will be 4k (2^12=4096) . Each entry in the dictionary
  577. requires five bytes, which will be built in the form of a tree. It is
  578. not a binary tree because each node may have more than two offsprings.
  579. In fact, because our dictionary can hold up to 4096 different codes it
  580. is possible to have one node with 3800 children nodes, although this is
  581. not likely to happen. The five bytes that make up our tree will be:
  582.  
  583. The parent code: Each node has one and only one parent node. When the parent
  584.                  code is less then 255 it is the end of a phrase. The codes
  585.                  0-255 do not actually exist in the tree. The following
  586.                  values do not appear either as they have special meaning:
  587.  
  588.                  256 : End of Stream-This marks the end of one compressed file
  589.                  257 : This tells the decompressor to increase the number
  590.                        of bits its reading by one.
  591.                  258 : Wipe out dictionary
  592.                  
  593. The code value : This is the code that will be sent to the compressor. 
  594. The character  : The value contained at this node. It have a value of 0-255.
  595.  
  596. Initially we send out codes that are 9 bits long, this will cover the values
  597. 0-511. Once we have reached 511, we will need to increase the number of
  598. bits to write by 1. This will give room for code numbers 512-1023, or
  599. (2^10)-1. At this point we must ensure that the decompressor knows how
  600. bits to read in at once so a code number 257 is sent to indicate that
  601. the number of bits to be read is to be bumped up by one. The size of the
  602. dictionary is finite so at some point we do have to be concerned with
  603. what we will do when it does fill up. We could stop compiling new
  604. phrases and just compress with the ones that are already in the
  605. dictionary. This is not a very good choice, files tend to change
  606. frequently (eg. program files as they change from code to data) so
  607. sticking with the same dictionary will actually increase the size of the
  608. file or at best, give poor compression. Another choice is to wipe the
  609. dictionary out and start building new codes and phrases, or wipe out
  610. some of the dictionary leaving behind only the newer codes and phrases.
  611. For the sake of simplicity this program will just wipe out the
  612. dictionary when it becomes full.
  613.  
  614. To illustrate how LZW works a small phrase will be compressed : heher.
  615. To start the first two characters would be read in. The H would be
  616. treated as the parent code and E becomes the character code. By means of
  617. a hashing routine (the hashing routine will be explained more fully in
  618. the source code) the location where HE should be is located. Since we
  619. have just begun there will be nothing there,so the phrase will be added
  620. to the dictionary. The codes 0-258 are already taken so we start using
  621. 259 as our first code. The binary tree would look something like this:
  622.             
  623.           node # 72 - H
  624.                  |
  625.      node #3200 259 - E
  626.  
  627.  The node # for E is an arbitrary one. The compressor may not choose
  628. that location, 3200 is used strictly for demonstration purposes. So at
  629. node #3200 the values would be:
  630.  
  631. Parent code - 72
  632. code value  - 259
  633. character   - E
  634.  
  635. The node #72 is not actually used. As soon as a value less than 255 is
  636. found it is assumed to be the actual value. We can't compress this yet
  637. so the value 72 is sent to the output file(remember that it is sent in 9
  638. bits). The E then becomes the parent code and a new character code ( H )
  639. is read in. After again searching the dictionary the phrase EH is not
  640. found. It is added to the dictionary as code number 260. Then we send
  641. the E to the disk and H becomes the new parent code and the next E
  642. becomes the new character code. After searching the dictionary we find
  643. that we can compress HE into the code 259,we want to compress as much as
  644. possible into one code so we make 259 the parent code. There may be a
  645. longer string then HE that can be compressed. The R is read in as the
  646. new character code. The dictionary is searched for the a 259 followed a
  647. R, since it is not found it is added to the dictioary and it looks like
  648. this:
  649.  
  650.            node #72 - H             node #69 - E
  651.                  |                        | 
  652.     node #3200  259 - E    node #1600    260 - H
  653.                  |
  654.     node #1262  261 - R
  655.  
  656. Then the value 259 is sent to the output file (to represent the HE) and
  657. since that is the EOF the R is sent as well,as well as a 256 to indicate
  658. the EOF has been reached.
  659.  
  660. Decompression is extremely simple. As long as the decompressor maintains
  661. the dictionary as the compressor did, there will be no problems,except
  662. for one problem that can be handled as an exceptional case. All of the
  663. little details of increasing the number of bits to read, and when to
  664. flush the dictionary are taken care of by the compressor. So if the
  665. dictionary was increased to 8k, the compressor would have to be set up
  666. to handle a larger dictionary, but the decompressor only does as the
  667. compressed file tells it to and will work with any size dictionary. The
  668. only problem would be that a larger dictionary will creep into the ram
  669. under the rom or possibly even use all available memory, but assuming
  670. that the ram is available the decompressor will not change. The
  671. decompressor would start out reading 9 bits at a time, and starts it
  672. free code at 259 as the compressor did. To use the above input from the
  673. compressor as an example, the output was:
  674.  
  675. 72  - For the First H
  676. 69  - For the First E
  677. 259 - For the Compressed HE
  678. 82  - For the R
  679. 256 - Eof indicator
  680.  
  681.  To begin decompressing, two values are needed. The H and E are read in,
  682. (note they will both be 9 bits long). As they are both below 256 they
  683. are at the end of the string and are sent straight to the output file.
  684. The first free code is 259 so that is the value assigned to the phrase
  685. HE. Note when decompressing there is no need for the hashing routine,
  686. the codes are the absolute locations in the dictionary (i.e. If the
  687. dictionary was considered to be an array then the entry number 259 would
  688. be dictionary[259]), because of this, the code value is no longer
  689. needed. So the decompressor would have an entry that looks like this:
  690.  
  691. Node # 259
  692. Parent Code - H
  693. Character   - E
  694.  
  695. The decompressor will read in the next value (259). Because the node
  696. number is at the end of the compressed string we will have to take the
  697. code value and place it on a stack, and take them off in a
  698. Last-in,First-out (LIFO) fashion. That is to say that the first
  699. character to go on the stack (in this case the E) will be the last to
  700. come off. The size of the stack is dependent on the size of the
  701. dictionary, so for this implementation we need a stack that is 4k long.
  702. After all the characters from the string have been placed on the stack
  703. they are taken off and sent to the outputfile.
  704.  
  705.